NSFetchedResultsController委托异常

时间:2012-07-31 17:18:16

标签: cocoa-touch uitableview core-data nsfetchedresultscontroller

我有一个应用程序,它使用表格视图显示我的核心数据的项目列表。我正在使用远程api,我在下拉表视图后更新了我的内容 - 这会触发对API的调用。

检索,解析数据并将其插入/更新到我的核心数据中。

有时在保存我的核心数据上下文后出错...请注意,我没有使用多个线程,就像我说它似乎并不总是发生。< / p>

我真的很生气。看起来这个人有类似的问题,但我仍然无法用他的解决方案修复我的问题: CoreData error driving me crazy... CoreData: Serious application error. An exception caught from delegate of NSFetchedResultsController

以下是完整错误:

2012-07-31 14:14:47.332 MyApp[2893:11303] 
*** Assertion failure in -[_UITableViewUpdateSupport _setupAnimationsForNewlyInsertedCells], 
/SourceCache/UIKit_Sim/UIKit-1914.84/UITableViewSupport.m:1133
2012-07-31 14:14:47.332 MyApp[2893:11303] CoreData: error: Serious application error.  
An exception was caught from the delegate of NSFetchedResultsController during a call to -
controllerDidChangeContent:.  
Attempt to create two animations for cell with userInfo (null)

更新

我的抓取请求有一个谓词。为了似乎删除先前从API下载的对象以及新JSON结果中缺少的对象。我正在设置一个hideFromUser标志,这个保存在我的核心数据中。

如果此标志为YES,则它不会出现在表格视图中。但是,如果没关系,那就确实如此。如果有任何改变,我也在更新该托管对象的信息。是否有可能我有一个先前设置为隐藏的对象...现在设置为显示,并且它还有一些新数据,这是否可能触发“单元格应该更新”和“单元格应该插入”?

更多我认为它似乎不太相关。

以下是我更新数据的方式:

1)我将相应类型的所有相关对象设置为“隐藏表单用户”(NSPredicate确保它们不会在表视图中显示)。

2)我从JSON数据中获得了一个NSArray。

3)循环每个项目,我的createABookOfClass:withJSON:方法查询一本书的核心数据(使用json字典中的ID),如果找不到它,它会创建一个新的。注意:此时将隐藏“隐藏用户标志”。

4)完成所有工作后,我保存。

[[DPLocalStore getInstance] hideFlagItemsOfType:NSStringFromClass([MyFavouriteBook class])];

NSArray * itemsJSON = [data mutableObjectFromJSONData];

[itemsJSON enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {     
    [[DPLocalStore getInstance] createABookOfClass:[MyFavouriteBook class]
                                          withJSON:obj];
}];

NSError *error = nil;
BOOL didsave = [[DPLocalStore getInstance] save:&error];

可能正在发生的事情是包含对象A的单元格已更新,它的更新:隐藏标志已更改。因此,我进入NSFetchedResultsController的委托想要更新该单元格的情况,并将其删除...因为谓词现在不对应于此对象......这听起来很可能......

1 个答案:

答案 0 :(得分:10)

我想我可能发现了错误,因为我改变了它我没有遇到过这个问题,所以我假设它没问题。

在我controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:的实现中,我在NSFetchedResultsChangeMove的switch语句中有这个:

case NSFetchedResultsChangeMove:
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                     withRowAnimation:UITableViewRowAnimationFade];

    // Reloading the section inserts a new row and ensures that titles are updated appropriately.
    [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section]
             withRowAnimation:UITableViewRowAnimationFade];
    break;

由于它在较旧的项目中使用(我不是其中的一部分),我认为整个controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:实现都没问题,因为这实际上更像是一个模板,而不是你将做任何自定义的事情。

因此,在我在Apple开发者网站上再次阅读之前,我并没有太多关注它。我注意到,如果是NSFetchedResultsChangeMove,您必须删除一个单元格,并将单元格插入新路径。然而,我没有真正意识到实施 - 删除单元格并重新加载该部分!

实际上,我应该现在拥有以下内容:

case NSFetchedResultsChangeMove:
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                     withRowAnimation:UITableViewRowAnimationFade];
    [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                     withRowAnimation:UITableViewRowAnimationFade];
    break;

就像我说的那样,自那以后我没有遇到任何问题。很想知道任何内部工作将对此负责 - 例外是“尝试为单元格创建两个动画”。

感谢您的任何兴趣。