-[UICollectionView _endItemAnimations] 崩溃中的断言失败

Posted

技术标签:

【中文标题】-[UICollectionView _endItemAnimations] 崩溃中的断言失败【英文标题】:Assertion failure in -[UICollectionView _endItemAnimations] crash 【发布时间】:2014-12-24 06:22:41 【问题描述】:

我在我的应用程序中使用核心数据来存储下载的数据。当应用程序下载数据时,我会将这些数据保存在 privateQueueContext (NSPrivateQueueConcurrencyType)

核心数据保存完成后,我应该更新 UI。为此,我定义了 NSFetchedResultsController 委托方法。正如我所料,当核心数据发生变化时,会调用这些委托方法。

didChangeObject 方法中,我正在插入新单元格,但是当核心数据中插入许多对象时会导致崩溃并给出以下错误消息

*** -[UICollectionView _endItemAnimations] 中的断言失败 CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了异常。无效更新:第 0 节中的项目数无效。更新后现有节中包含的项目数 (379) 必须等于更新前该节中包含的项目数 (325),加上或减去数字从该部分插入或删除的项目数(52 个插入,0 个删除)加上或减去移入或移出该部分的项目数(0 个移入,0 个移出)。与 userInfo (null)

我假设数据源在完成新的单元格插入动画之前发生了变化。

我希望很多人都会遇到同样的问题,并且堆栈溢出中有很多类似的问题,但没有一个答案对我来说是正确的。有人可以帮我解决这个问题吗?

在核心数据中插入新对象

for (NSDictionary *obj in books)
    Book *book = [Book insertInManagedObjectContext:context];
    book.udid = [obj objectForKey:@“id”]  


[context performBlock:^
   NSError *error = nil;
   if ([context save:&error]) 
        NSLog(@“success”);
                   
];

获取结果控制器委托

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
   self.blockOperation = [NSBlockOperation new];
  

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath 
   __weak UICollectionView *collectionView = self.collectionView;
   switch(type) 
      case NSFetchedResultsChangeInsert:
           [self.blockOperation addExecutionBlock:^
            [collectionView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForItem:newIndexPath.item + 1 inSection:newIndexPath.section]]];
           ];
           break;
      
      default:
        break;
   


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
    [self.collectionView performBatchUpdates:^
    [self.blockOperation start];
     completion:nil];
  

【问题讨论】:

您能否包含完整的错误文本?通常在您包含的行之后会有额外的信息。 @jrturton 感谢您的回复 *** 断言失败 -[UICollectionView _endItemAnimations], /SourceCache/UIKit_Sim/UIKit-3318.16.14/UICollectionView.m:3917 CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了异常。无效更新:第 0 节中的项目数无效。更新后现有节中包含的项目数 (379) 必须等于更新前该节中包含的项目数 (325),加上或减去数字从该部分插入或删除的项目数(52 个插入,0 个删除)加上或减去移入或移出该部分的项目数(0 个移入,0 个移出)。与 userInfo (null) 【参考方案1】:

您的performBlock 保存时间过长。你可以

只需保存在主线程上。应该花一秒钟的时间来保存 500 本书,并且由于 UI 中没有发生任何严重的事情(用户正在等待),因此无需在一个块中执行此操作。

请改用performBlockAndWait。只有在保存完成后,表格视图才会更新。用户的结果与在主线程上保存非常相似。

使用NSFetchedResultsControllerDelegate 而不使用阻止操作。遵循 Xcode 提供的 fetched results controller 模板。这可能会比只保存在主线程上要慢,因为 UI 会获得多次更新。

【讨论】:

以上是关于-[UICollectionView _endItemAnimations] 崩溃中的断言失败的主要内容,如果未能解决你的问题,请参考以下文章

在MySQL中尝试Forward Engineering时出错1064

英语高手请进

简易先进先出队列-自用

函数参数

多重背包

合租房合同模板