5

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

数据被检索、解析并插入/更新到我的核心数据中。

在保存我的核心数据上下文后,我有时会遇到错误......请注意,我没有为此使用多个线程,就像我说的那样,它似乎并不总是发生。

我真的要疯了。看来这家伙有类似的问题,但我仍然无法用他的解决方案修复我的问题: CoreData 错误让我发疯...... CoreData:严重的应用程序错误。从 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 的代表想要更新该单元格并删除它的情况......因为谓词现在不对应于这个对象......这听起来很可能......

4

1 回答 1

10

我想我可能已经发现了错误,因为我更改了它,所以我没有遇到问题,所以我假设它没问题。

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

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;

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

感谢您的任何兴趣。

于 2012-08-01T18:04:00.300 回答