Ios 当我同时插入和删除时,为什么UITableView会崩溃?

Ios 当我同时插入和删除时,为什么UITableView会崩溃?,ios,objective-c,uitableview,cocoa-touch,Ios,Objective C,Uitableview,Cocoa Touch,我有以下代码: @property (nonatomic, strong) NSMutableArray *rows; // pre-filled with 2 rows // ... - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.rows.count; } - (void)tableView:(UITableView *)

我有以下代码:

@property (nonatomic, strong) NSMutableArray *rows; // pre-filled with 2 rows

// ...

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.rows.count;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSIndexPath *newRowIndexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section];
    MyRowRepresentation *newRowRepresentation = [MyRowRepresentation new];
    [self.rows insertObject:newRowRepresentation atIndex:newIndexPath.row];

    NSMutableIndexSet *indicesToRemove = [NSMutableIndexSet indexSet];
    NSMutableArray<NSIndexPath*> *indexPathsToRemove = [NSMutableArray array];

    for (int i = 0; i < self.row.count; i++)
    {
        MyRowRepresentation *mrr = self.rows[i];
        if (mrr != newRowRepresentation && [self meetsDeletionRequirements:mrr])
        {
            [indicesToRemove addIndex:i];
            [indexPathsToRemove addObject:[NSIndexPath indexPathForRow:i inSection:indexPath.section]];
        }
    }

    [tableView beginUpdates];
    [tableView insertRowsAtIndexPaths:@[newRowIndexPath] withRowAnimation:UITableViewRowAnimationTop];
    [self.rows removeObjectsAtIndexes:indicesToRemove];
    [tableView deleteRowsAtIndexPaths:indexPathsToRemove withRowAnimation:UITableViewRowAnimationTop];
    [tableView endUpdates]; // crash here
}
当我选择一行时,我得到:

2015-12-14 20:27:17.761 Now[1685:1753114] ERROR CRASH #(null) attempt to insert row 3 into section 1, but there are only 3 rows in section 1 after the update
2015-12-14 20:27:17.828 Now[1685:1753114] ERROR Stack Trace: (
    0   CoreFoundation                      0x0000000185684248 <redacted> + 160
    1   libobjc.A.dylib                     0x00000001970a80e4 objc_exception_throw + 60
    2   CoreFoundation                      0x00000001856840ec <redacted> + 0
    3   Foundation                          0x0000000186538ed4 <redacted> + 112
    4   UIKit                               0x000000018a2e57ec <redacted> + 5256
    5   Now                                 0x0000000100092914 -[MyTableViewController tableView:didSelectRowAtIndexPath:] + 1234
    ...
)
2015-12-14 20:44:48.933 Now[1692:1754780] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 3 into section 1, but there are only 3 rows in section 1 after the update'
但是我很困惑;以下步骤应该有效,不是吗

我将新行表示插入到跟踪数组中。 我开始更新表,这将使其处于暂停状态。 我从跟踪数组中删除了不需要的行表示,其中不包括新的行表示。 我删除了对应于已删除行表示的表视图行。 我插入对应于新行表示的表视图行。 要使应用程序崩溃,我从原来的两行中选择一行,然后选择另一行

我不明白是什么原因导致此崩溃?

我无法回答原因,但我确实通过使用一个重新加载调用而不是多个插入/删除调用解决了此问题:

@property (nonatomic, strong) NSMutableArray *rows; // pre-filled with 2 rows

// ...

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.rows.count;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView beginUpdates];
    NSIndexPath *newRowIndexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section];
    MyRowRepresentation *newRowRepresentation = [MyRowRepresentation new];
    [self.rows insertObject:newRowRepresentation atIndex:newIndexPath.row];

    NSMutableIndexSet *indicesToRemove = [NSMutableIndexSet indexSet];
    NSMutableArray<NSIndexPath*> *indexPathsToRemove = [NSMutableArray array];

    for (int i = 0; i < self.row.count; i++)
    {
        MyRowRepresentation *mrr = self.rows[i];
        if (mrr != newRowRepresentation && [self meetsDeletionRequirements:mrr])
        {
            [indicesToRemove addIndex:i];
            [indexPathsToRemove addObject:[NSIndexPath indexPathForRow:i inSection:indexPath.section]];
        }
    }

    [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
}

将BeginUpdate移动到方法的顶部对deleteRowsAtIndexPaths的调用必须在对insertRowsAtIndexPaths的调用之前。@Paulw11无需移动BeginUpdate。它只需要在调用各种表修改方法之前。@rmaddy它实际上比这更微妙吗?第二次执行任何操作的索引路径是否会受到第一次执行的操作的影响,因此,如果先调用delete,则插入点可能无效,反之亦然?@Paulw11正确。这在iOS的表视图编程指南中都有介绍。