Ios NSFetchedResultsController具有筛选NSPredicate的didChangeObject
我有一个由NSFetchedResultsController支持的UITableView,它显示用户已添加书签的项目。可以通过行中的按钮取消对项目的书签,这会导致问题。取消项目书签后,它应该会从表视图中消失,因为它不再匹配谓词,但由于更新更改了我的每个节的行数,我得到了此错误的一个变体: CoreData:错误:严重的应用程序错误。在调用-controllerDidChangeContent:期间,从委托NSFetchedResultsController捕获到异常。无效更新:无效 节0中的行数。更新后现有节中包含的行数(3) 必须等于更新之前该节中包含的行数(4),加上或减去 从该节插入或删除的行数(0插入,0删除)加上或减去 移入或移出该节的行数(0移入,0移出)。带userInfo(空) 下面是我非常简单的didChangeObject方法:Ios NSFetchedResultsController具有筛选NSPredicate的didChangeObject,ios,objective-c,uitableview,core-data,nsfetchedresultscontroller,Ios,Objective C,Uitableview,Core Data,Nsfetchedresultscontroller,我有一个由NSFetchedResultsController支持的UITableView,它显示用户已添加书签的项目。可以通过行中的按钮取消对项目的书签,这会导致问题。取消项目书签后,它应该会从表视图中消失,因为它不再匹配谓词,但由于更新更改了我的每个节的行数,我得到了此错误的一个变体: CoreData:错误:严重的应用程序错误。在调用-controllerDidChangeContent:期间,从委托NSFetchedResultsController捕获到异常。无效更新:无效 节0中的行
-(void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
[super controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
是否有某种方法可以指示NSFetchedResultsController不要忽略不匹配的计数?或者我需要完全不同的方法吗?您的
didChangeObject
委托方法看起来非常不完整,
特别是,它不检查发生了哪些事件(插入、删除或更新)
您可以在NSFetchedResultsControllerDelegate
协议中找到模板
记录。
该方法通常类似于此:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
您还应该实现controller:didChangeSection:atIndex:forChangeType:
委托方法
我不明白这是怎么回事
[super controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];
这是我的电话 马丁·R给出了很好的回答,但他忽略了一件重要的事情: 如果FetchControllerProtocol希望同时刷新许多行,它可能会崩溃 给出一个非常清晰的典型过程示例。使用beginUpdates和endUpdates方法围绕表更改是很重要的
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
如果有节,还应该实现节刷新
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeSection:(id)sectionInfo
atIndex:(nsInteger)ChangeType:(NSFetchedResultsChangeType)类型的节索引{
开关(类型){
案例NSFetchedResultsChangesInsert:
[self.tableView insertSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
打破
}
}
希望这有帮助谢谢Martin。我没有处理所有这些情况的原因是,
NSFetchedResultsChangeUpdate
是我的应用程序中触发的唯一更改类型。之所以调用super,是因为我实现此方法的类是类层次结构的一部分,但我同意这在某种程度上混淆了问题。我将更新帖子以使用您更标准的代码,因为问题仍然存在。@Dane:但是如果某个项目“未添加书签”,并且不再与谓词匹配,则将使用NSFetchedResultsChangeDelete
事件调用didChangeObject
。您真的应该实现完整的委托方法!啊,我明白了,这可能就是问题所在@Dane:您是否也实现了controller:didChangeSection:atIndex:forChangeType:
?