我的应用有一个UITableViewController,在追加行后会收到“无效更新:第0节中的行数无效...”。事情是,它只发生在%0.2的会话中。我们的应用程序有数百万个会话,所以崩溃加起来。
流程很简单。它是将用户的音乐与我们的视频目录相匹配的功能的一部分。后台线程发出一系列请求。请求结束,响应返回结果,然后这些结果将附加到我们的一个选项卡中的tableView。请求分批进行,可以累加大量结果行。因此,不是在批处理进入后调用reloadData,而是想要正确地附加它们。工作很棒,但偶尔会崩溃。
我能够在设备上重现这一次。它从未发生在模拟器上。据我所知,崩溃是相当随机的,虽然它主要发生在3gs。最少的崩溃来自4s。
这是代码。响应回来了。在这种情况下,allMatches是到目前为止的每个匹配项(表的数据源)。 batchMatches是新艺术家的数量。两者都是数组:
[self.tableView beginUpdates];
NSMutableArray *paths = [[NSMutableArray alloc] init];
for (int i = [allMatches count] - [batchMatches count]; i < [allMatches count]; ++i) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[paths addObject: indexPath];
}
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
[paths release];
代码非常简单。它只是将行追加到最后,每个结果一行。永远不要删除。完整异常消息的示例是“无效更新:第0节中的无效行数。更新后现有部分中包含的行数(131)必须等于更新前该部分中包含的行数( 131),加上或减去从该部分插入或删除的行数(插入20个,删除0个),加上或减去移入或移出该部分的行数(0移入,0移出)。“实际崩溃报告中的数字到处都是,因此它不是特定的批号。
像我说的那样,它几乎总能奏效。它通常在3GS上崩溃。我想知道这是否可能是一个框架错误。我总是可以在每个批次返回后调用reloadData,但每次都会导致表格单元格的丑陋闪烁。我故意触发了异常,之后表似乎已经死了,所以我无法使用reloadData作为catch块中的回退进行try / catch。那里有人可以解决一些问题吗?对这篇文章的篇幅感到抱歉。
编辑:服务器请求是使用NSOperationQueue完成的,因此它们位于后台线程上。当响应返回时,我在主线程上发布通知,这会导致表代码运行。通知发布如下:
NSNotification *notification = [NSNotification notificationWithName:notificationName object:self];
[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
post notificiation只是[[NSNotificationCenter defaultCenter] postNotification:notification]的包装器。所以表格代码应该在主线程上。
答案 0 :(得分:1)
我的猜测是,您正在后台线程中执行表视图更新。你应该在主线程上这样做。
将您的代码放在dispatch_async块中。
dispatch_async(dispatch_get_main_queue(), ^(void) {
// ..
});