reloadRowsAtIndexPaths:withRowAnimation:崩溃我的应用程序

Anh*_* Do 20 iphone crash uitableview

我的UITableView出现了一个奇怪的问题:我reloadRowsAtIndexPaths:withRowAnimation:用来重新加载一些特定的行,但应用程序崩溃时出现了一个看似无关的异常:NSInternalInconsistencyException - 尝试删除多于部分中存在的行.

我的代码如下所示:

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
Run Code Online (Sandbox Code Playgroud)

当我reloadRowsAtIndexPaths:withRowAnimation:用一个简单的替换该消息时reloadData,它完美地工作.

有任何想法吗?

Nek*_*kto 29

问题是你可能已经改变了你的桌子的大小.例如,您已为表视图添加或删除某些源数据.

在这种情况下,当您调用reloadData表时,将完全重新加载,包括节的大小和节的数量.

但是当你调用reloadRowsAtIndexPaths:withRowAnimation:表视图的参数时不会重新加载.这会导致下一个问题:当您尝试重新加载某些单元格表时,请检查表视图的大小并查看它是否已更改.这会导致崩溃.只有当您不想重新加载单元格视图时才能使用此方法(例如,标签已更改或您想要更改其大小).

现在,如果要从/向表视图中删除/添加单元格,则应使用下一种方法:

  1. 通知表通过调用方法,它的大小将被改变beginUpdatesUITableView
  2. 通过使用方法通知插入新行 - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
  3. 通知使用方法删除行 - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
  4. 通知表通过调用方法,它的尺寸已经改变endUpdatesUITableView

希望它会有所帮助


小智 9

我认为以下代码可能有效:

[self.tableView beginUpdates];

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];

[self.tableView endUpdates];
Run Code Online (Sandbox Code Playgroud)

  • 我认为这无济于事 (2认同)

Seo*_*ras 5

我有这个问题,这是由调用reloadRowsAtIndexPaths:withRowAnimation:的块和调用reloadData的并行线程引起的。崩溃是由于reloadRowsAtIndexPaths:withRowAnimation找到一个空表,即使我没有理智地检查numberOfRowsInSection和numberOfSections。

我采取的态度是,我真的不在乎它是否会引起异常。作为应用程序用户,我可能会遭受视觉破坏,而不是整个应用程序崩溃。

这是我对此的解决方案,我很乐意分享并欢迎建设性的批评。如果有更好的解决方案,我很想听听吗?

- (void) safeCellUpdate: (NSUInteger) section withRow : (NSUInteger) row {
    // It's important to invoke reloadRowsAtIndexPaths implementation on main thread, as it wont work on non-UI thread
    dispatch_async(dispatch_get_main_queue(), ^{
        NSUInteger lastSection = [self.tableView numberOfSections];
        if (lastSection == 0) {
            return;
        }
        lastSection -= 1;
        if (section > lastSection) {
            return;
        }
        NSUInteger lastRowNumber = [self.tableView numberOfRowsInSection:section];
        if (lastRowNumber == 0) {
            return;
        }
        lastRowNumber -= 1;
        if (row > lastRowNumber) {
            return;
        }
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
        @try {
            if ([[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] == NSNotFound) {
                // Cells not visible can be ignored
                return;
            }
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        }

        @catch ( NSException *e ) {
            // Don't really care if it doesn't work.
            // It's just to refresh the view and if an exception occurs it's most likely that that is what's happening in parallel.
            // Nothing needs done
            return;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)