2

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

-(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 - 我需要做一些更自定义的事情吗?

4

2 回答 2

5

performBatchUpdates:completion:在只有约 100 个元素的集合视图中将主线程锁定几秒钟时遇到了同样的问题。

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

话虽如此,我不知道为什么会发生这种情况。通过查看我们分析的运行的堆栈跟踪,很多时间都花在了 上-[UIViewCollectionViewUpdate _computeGaps],这反过来又调用-[NSArray sortedArrayUsingSelector:]了数百甚至数千次(以及CFSortIndexes__CFSimpleMergeSort...)。通过仅使用一个整数值作为我们单元格的高度,sortedArrayUsingSelector调用不到 10 次,整个过程在几分之一秒内完成。

于 2015-07-15T13:23:24.180 回答
0

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

  1. TLIndexPathTools作为NSFetchedResultsController. 它提供了一个TLIndexPathController非常相似的类,NSFetchedResultsController除了它也适用于普通数组并且它可以对过滤进行动画排序(不像NSFetchedResultsController. 有许多示例项目,包括一个Core Data项目。
  2. VCollectionViewGridLayout作为UICollectionViewFlowLayout. 它是一个统一的垂直滚动网格,因此不如 灵活UICollectionViewFlowLayout,但在大多数情况下,动画通常要好得多,它会使用粘性标题(如UITableView标题)。有几个示例项目可让您在两者之间切换UICollectionViewFlowLayoutVCollectionViewGridLayout查看改进。

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

于 2013-07-02T17:32:43.237 回答