这也许是NSFetchedResultsController的一个bug,maybe....
出错场景:
1、当我在输入框输入一长段文字,点击发送按钮,随即将消息保存至数据库。
2、数据库的变化激活NSFetchedResultsController,随即回调一系列的方法来更新tableview
3、问题是,我insert一条数据到数据库,但是NSFetchedResultsController的回调中没有insertion,只有update
4、导致tableview endupdates时报错 uitableview _endcellanimationswithcontext
分析:
1、输入信息多了才会出现这个bug
2、数据库保存成功,信息成功存到了sqlite文件
3、再次进入tableview可以正常显示刚才没有显示的那一条信息
解决方案:
输入信息的长度我们不能限制,所以NSFetchedResultsController不给我们回调insertion是无法避免了
所以在出现上述bug后,采用reloaddata来弥补。
具体做法:
判断是否出现了上述bug
<span style="font-size:14px;"> case NSFetchedResultsChangeUpdate:{
NSInteger row = [_conversationTableView numberOfRowsInSection:0];
if(row <= indexPath.row) {
//没有NSFetchedResultsChangeInsert返回
//tableview的row 和 数据库中数据的row 不一致
//因为tableview 没有 insert,所以row <= indexPath.row 就是出现bug
//弥补措施
[tableview reloadData];
}
<span style="white-space: pre;"> </span>}</span>
reloadData不要放在beginUpdates 和 beginUpdates之间
我的代码:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
DDLogInfo(@"ConversationController ---- willchange row of table :%ld",(long)[self tableView:_conversationTableView numberOfRowsInSection:0]);
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type) {
case NSFetchedResultsChangeInsert:
[_conversationTableView beginUpdates];
[_conversationTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[_conversationTableView endUpdates];
break;
case NSFetchedResultsChangeDelete:
[_conversationTableView beginUpdates];
[_conversationTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[_conversationTableView endUpdates];
break;
case NSFetchedResultsChangeUpdate:{
NSInteger row = [_conversationTableView numberOfRowsInSection:0];
if(row <= indexPath.row){
[_conversationTableView reloadData];
//发送文字过长,fetchresultcontroller没有对tableview insert,所以在此处通过row的对比判断是否发生了上述bug
break;
}
[_conversationTableView beginUpdates];
[_conversationTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[_conversationTableView endUpdates];
break;
}
case NSFetchedResultsChangeMove:
[_conversationTableView beginUpdates];
[_conversationTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[_conversationTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[_conversationTableView endUpdates];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
}