reloadRowsAtIndexPaths 崩溃
attempt to delete row 44 from section 0 which only contains 0 rows before the update
导致的崩溃
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[cell setData:dc.attachments[indexPath.row] andReload:^{
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
}
我们通过reloadRowsAtIndexPaths进行更新某个或者某几个Cell的时候,在tableView内部先删除该Cell,再进行重新创建,如果我们在更新Cell的时候如果该Cell是不存在的就会Crash,attempt to delete row 10 from section 0 which only contains 0 rows before the update(试图删除不存在的Cell)
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
如何解决这个问题呢
1、通过使用reloadData进行完全重新加载;
2、判断该Cell是否存在,存在再进行reloadRowsAtIndexPaths,这样就可以避免Crash
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell) {
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
-》因为此处是datasource中的data变化了。
-》所以不应该调用reloadRowsAtIndexPaths,而应该直接用reloadData???
-》但是不会导致效率很低吗?
有点看懂了:
此处是:
对于tableView的datasource的数组:
conversationItemList
最开始conversationItemList是空的,count是0
此处之前已经调用了:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("ConversationViewController numberOfRowsInSection")
return conversationItemList.count
}
所以当时是numberOfRowsInSection返回的是0
而此处虽然是已经添加数据了:
if conversationItemList.count == 0 {
conversationItemList.append(newConversationItem)
}
else {
conversationItemList.insert(newConversationItem, atIndex: newInsertItemIdx)
}
但是此时tableView并不知道你的数据源变化了
-》所以此时调用reloadRowsAtIndexPaths,发现:
section 0中,并没有数据
而reload需要
先删除delete
再添加add
所以此时delete不存在的row的话,就报错了。
-》所以,此处应该是先调用reloadData
-》让系统知道数据变化了。
iphone – Crash on reloadRowsAtIndexPath but not on reloadData – Stack Overflow
中的解释,也和我猜的一样: