NSFetchedResultsController 与 UITableView 的问题

出错关键字:

An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:
Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)

出错场景:

聊天界面,点击输入文字,点击发送按钮(注:此问题为偶显,不容易重现导致此问题不易跟踪)

结果:程序没有crash,但是发送的消息没有展示在tableview上面,pop到联系人列表界面,再次进入消息界面,刚才发送的消息正常显示


我的用法

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
	// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
 [_conversationTableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [_conversationTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                          withRowAnimation:UITableViewRowAnimationFade];
        break;
        case NSFetchedResultsChangeDelete:
        [_conversationTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                      withRowAnimation:UITableViewRowAnimationTop];
        break; case NSFetchedResultsChangeUpdate:{ [_conversationTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        }
        case NSFetchedResultsChangeMove:
        [_conversationTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                      withRowAnimation:UITableViewRowAnimationFade];
        [_conversationTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                      withRowAnimation:UITableViewRowAnimationFade];
        break;
    }
}

 
 
 
 
 
 
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
	// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [_conversationTableView endUpdates];
}

分析:
1、重新进入聊天界面,消息正常展示,说明数据库中的数据是正确的
2、重新进入界面,会触发reloaddata方法,所以消息都展示出来了
3、确定所有tableview 的 insert 、delete、update、move都是在main thread,所以不是线程问题,而且线程问题不会报错
4、到底是什么原因呢

排错:
按住option键,单击  beginUpdates, 查看description
Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously. This group of methods must conclude with an invocation of endUpdates. These method pairs can be nested. If you do not make the insertion, deletion, and selection calls inside this block, table attributes such as row count might become invalid. You should not call reloadData within the group; if you call this method within the group, you will need to perform any animations yourself.

理解一下:类似以下操作应该在 beginUpdates和  endUpdates 之间
[_conversationTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[_conversationTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[_conversationTableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
 
 
review下自己的代码,发现确实有不少reloadRows操作没有在 beginUpdates 和  endUpdates  之间,因为用了fetchresultcontroller,所以不用自己在其他地方做reload、insert、delete等操作,只需要修改数据库之后save就好了。接下来对tableview的操作都会在
- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath;
当中执行。

----over----

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值