【问题标题】:iPhone-App crashes when a row of UITableView is deleted删除一行UITableView时iPhone-App崩溃
【发布时间】:2011-06-02 22:47:48
【问题描述】:

我有一个使用单例对象作为数据源的 UITableView。

我已经实现了以下方法来允许用户删除 UITableView 中的行。但是当我单击删除按钮时,应用程序崩溃并出现异常

方法:

-(void)viewDidLoad
{

some initialization code-----

UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:@"Delete"                                                        style:UIBarButtonItemStyleBordered                                                                 target:self                                                     action:@selector(toggleEdit:)];
       self.navigationItem.rightBarButtonItem = editButton;
       [editButton release];

}

-(IBAction)toggleEdit:(id)sender
{
    [self.myOrderTable setEditing:!self.myOrderTable.editing animated:YES];
    
    if(self.myOrderTable.editing)
        [self.navigationItem.rightBarButtonItem setTitle:@"Done"];
    else 
    {
     [self.navigationItem.rightBarButtonItem setTitle:@"Delete"];
    }

}

-(void)tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath*)indexPath
{
    NSUInteger row = [indexPath row];
    
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                     withRowAnimation:UITableViewRowAnimationFade];
    
}

但是,当我尝试单击删除按钮时出现以下异常:

-[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:995 中的断言失败

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第 1 节中的行数无效。更新后现有节中包含的行数 (1) 必须等于行数更新前包含在该节中 (1),加上或减去从该节插入或删除的行数(0 插入,1 删除)。'

*** Call stack at first throw:
(
    0   CoreFoundation                      0x010305a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x01184313 objc_exception_throw + 44
    2   CoreFoundation                      0x00fe8ef8 
+[NSException raise:format:arguments:] + 136
    3   Foundation                          0x001153bb -
[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
    4   UIKit                               0x00398e8b -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 8420
    5   UIKit                               0x00387cf8 -
[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 56
    6   Restaurant                          0x000117f9 -
[MyOrderViewController tableView:commitEditingStyle:forRowAtIndexPath:] + 114
    7   UIKit                               0x00385037 -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] + 101
    8   UIKit                               0x0031a4fd -[UIApplication sendAction:to:from:forEvent:] + 119
    9   UIKit                               0x003aa799 -[UIControl sendAction:to:forEvent:] + 67
    10  UIKit                               0x003acc2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
    11  UIKit                               0x003ab7d8 -[UIControl touchesEnded:withEvent:] + 458
.............

..........
.............
)
terminate called after throwing an instance of 'NSException'

我可以从哪里着手解决这个问题?

【问题讨论】:

    标签: iphone uitableview


    【解决方案1】:

    "更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (1),加上或减去插入的行数或从该部分删除(插入 0 个,删除 1 个)。'"

    错误清楚地说明了问题所在。我会检查你的 numberOfRowsInSection 方法。您需要考虑被删除的行。您不能总是返回相同数量的行。如果您要从表中删除一行,您的 numberOfRowsInSection 需要返回它的旧返回值减去 1。

    例如:

    假设我使用一个字符串数组来填充表格视图;

    我的 numberOfRowsInSection 方法会使用

    return [array count];
    

    我的 cellForRowAtIndexPath 方法将使用

    cell.textLabel.text = (NSString*)[array objectAtIndex:indexPath.row];
    

    当我从 tableView 中删除一行(比如第 3 行)时,我也会从数组中删除该对象:

    [array removeObjectAtIndex:3];
    

    这样当再次调用 numberOfRowsInSection 时,数组会小一个对象,并且 numberOfRowsInSection 返回比之前少一个数字,这就是删除行的原因。

    【讨论】:

      【解决方案2】:

      您是否阅读了错误信息?它说:

      原因:'无效更新:第 1 节中的行数无效。

      所以...您的 tableView 中的行数现在是错误的。为什么?

      更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (1),加上或减去从该节中插入或删除的行数(插入 0 个,删除 1 个)。

      当您从 tableView 中删除一行时,您还必须从 tableView 中显示的对象数组中删除相应的对象。你没有那样做。因此,UITableView 抛出了异常。

      【讨论】:

        【解决方案3】:

        您是否要从 commitEditingStyle: 中的数据源中删除项目?如果表数据源有 2 个项目,并且您在 commitEditingStyle: 中删除了一行,您还应该从数据源中删除一个项目,这样现在表视图和数据源都有 1 个元素。

        【讨论】: