断言失败 - [UICollectionView _endItemAnimations]崩溃

时间:2014-12-24 06:22:42

标签: ios objective-c core-data uicollectionview nsfetchedresultscontroller

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

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

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

  

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

1 个答案:

答案 0 :(得分:0)

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

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

  • 使用performBlockAndWait代替。只有在保存完成后才会更新表视图。用户的结果与保存主线程非常相似。

  • 在没有阻止操作的情况下使用NSFetchedResultsControllerDelegate。遵循Xcode提供的获取结果控制器模板。这可能比仅保存主线程更慢,因为UI将获得多次更新。