Objective c UICollectionView在PerformBatchUpdate上锁定主线程约10秒

Objective c UICollectionView在PerformBatchUpdate上锁定主线程约10秒,objective-c,uicollectionview,nsfetchedresultscontroller,uicollectionviewlayout,Objective C,Uicollectionview,Nsfetchedresultscontroller,Uicollectionviewlayout,我有一个包含300个单元格的collectionview,由NSFetchedResultsController驱动。每隔一段时间,所有对象都会更新,因此我会收到委托消息,告诉我是这样的,我让集合视图像处理tableview一样处理更新。不幸的是,每次发生这种情况时,它都会将主线程锁定几秒钟。。。我不知道为什么。这是我的密码: -(void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [se

我有一个包含300个单元格的collectionview,由NSFetchedResultsController驱动。每隔一段时间,所有对象都会更新,因此我会收到委托消息,告诉我是这样的,我让集合视图像处理tableview一样处理更新。不幸的是,每次发生这种情况时,它都会将主线程锁定几秒钟。。。我不知道为什么。这是我的密码:

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{

    [self.cascadeViewController.collectionView performBatchUpdates:^{

    NSLog(@"performingBatchUpdates");

    for (NSDictionary *change in self.changes) {

        [change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) {

            NSFetchedResultsChangeType type = [key unsignedIntegerValue];

            if (type == NSFetchedResultsChangeInsert) {

                [self.cascadeViewController.collectionView insertItemsAtIndexPaths:@[obj]];

            } else if (type == NSFetchedResultsChangeDelete) {

                [self.cascadeViewController.collectionView deleteItemsAtIndexPaths:@[obj]];

            } else if (type == NSFetchedResultsChangeUpdate) {

                [self.cascadeViewController.collectionView reloadItemsAtIndexPaths:@[obj]];

            } else if (type == NSFetchedResultsChangeMove) {

                [self.cascadeViewController.collectionView moveItemAtIndexPath:obj[0] toIndexPath:obj[1]];

            }

        }];
    }

    NSLog(@"performingBatchUpdates end");

} completion:^(BOOL finished) {

    NSLog(@"completion");

    // TODO: implement
    //    [self configureMessageAndFooterView];

}];

NSLog(@"end of method");

[self.changes removeAllObjects];

}

这是怎么回事?在我的应用程序的实际执行过程中,所有300个对象都不会一次更新,但这已经足够让我担心了。我正在使用一个股票UICollectionViewFlowLayout-我需要做一些更自定义的事情吗?

我隐约记得以前看到过这样的行为,但我没有解决NSFetchedResultsController+
UICollectionViewFlowLayout
组合的方法,因为我们由于许多问题而停止使用这两个类。你可以考虑看看我们开源的替代品:

  • 作为
    NSFetchedResultsController
    的替代品。它提供了一个
    TLIndexPathController
    类,该类与
    nsfetchedresultscoontroller
    非常相似,只是它也适用于普通数组,并且可以进行动画排序和筛选(与
    nsfetchedresultscoontroller
    不同)。有许多示例项目,包括一个
  • 作为
    UICollectionViewFlowLayout
    的替代品。它是一个统一的垂直滚动网格,因此不如
    UICollectionViewFlowLayout
    灵活,但在大多数情况下,动画效果通常要好得多,它可以制作粘性标题(如
    UITableView
    标题)。有几个示例项目可以让您在
    UICollectionViewFlowLayout
    VCollectionViewGridLayout
    之间切换,以查看改进

  • 我们有一个iPad应用程序,它有一个网格状的集合视图,包含大约1000个项目,当我们的核心数据数据库在后台更新时,上面的内容为我们提供了出色的性能和流畅的动画。

    performbatchUpdate有同样的问题:完成:
    在一个只有~100个集合视图中锁定主线程几秒钟元素

    在这个问题上花费了太多的时间后,我找到了一个解决方案:确保单元格的大小(如
    -collectionView:layout:sizeFormiteIndeXPath:
    中返回的或通过布局的
    itemSize
    属性定义的)没有分数值。我通过对单元格的计算高度应用
    floor
    ,解决了性能问题


    尽管如此,我不知道为什么会发生这种情况。通过查看分析运行的堆栈跟踪,大量时间都花在了
    -[UIViewCollectionViewUpdate\u computeGaps]
    ,这反过来调用
    -[NSArray-sortedarray-usingselector:][/code>数百次甚至数千次(以及
    CFSortIndexes
    \uu CFSimpleMergeSort
    。)。只需使用单元格高度的整数值,
    sortedArrayUsingSelector
    调用不到10次,整个过程在几分之一秒内完成。

    您应该对其进行分析。我有-它在内部API调用上做了大量工作。它点击[UICollectionViewUpdate\U computeGaps]并且似乎对NSArray和indexPath比较进行了大量排序。似乎没有调用任何可以修改的委托方法或可以替换的UICollectionViewFlowLayout方法。您是否同时解决了问题?我在collectionview中遇到了同样的问题,有600个项锁定了主线程20秒!