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