ios - performBatchUpdates 上的 UICollectionView 性能问题

标签 ios performance ios6 uicollectionview

我们正在尝试设置具有自定义布局的 UICollectionView。每个 CollectionViewCell 的内容都是一张图片。总的来说,将有几千张图像,并且在某个特定时间大约有 140-150 张是可见的。在一个 Action 事件中,所有单元格的位置和大小可能都会重新组织。目标是为当前使用 performBatchUpdates 方法的所有移动事件设置动画。这会导致在一切动画化之前出现巨大的延迟时间。

到目前为止,我们发现在内部为每个单元格(总共几千个)调用了 layoutAttributesForItemAtIndexPath 方法。此外,cellForItemAtIndexPath 方法会被调用以获取比屏幕上实际显示的更多的单元格。

有没有可能提高动画的性能?


默认的 UICollectionViewFlowLayout 不能真正提供我们想要在应用程序中实现的那种设计。这是我们的一些代码:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
RPDataModel *dm = [RPDataModel sharedInstance]; //Singleton holding some global information
NSArray *plistArray = dm.plistArray; //Array containing the contents of the cells
NSDictionary *dic = plistArray[[indexPath item]];
RPCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
cell.label.text = [NSString stringWithFormat:@"%@",dic[@"name"]];
cell.layer.borderColor = nil;
cell.layer.borderWidth = 0.0f;
[cell loadAndSetImageInBackgroundWithLocalFilePath:dic[@"path"]]; //custom method realizing asynchronous loading of the image inside of each cell
return cell;
}

layoutAttributesForElementsInRect 遍历所有元素,为矩形内的所有元素设置 layoutAttributes。 for 语句在第一个单元格超过矩形右下角定义的边界时中断:

-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray* attributes = [NSMutableArray array];
RPDataModel *dm = [RPDataModel sharedInstance];
for (int i = 0; i < dm.cellCount; i++) {
    CGRect cellRect = [self.rp getCell:i]; //self.rp = custom object offering methods to get information about cells; the getCell method returns the rect of a single cell
    if (CGRectIntersectsRect(rect, cellRect)) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[dm.relevanceArray[i][@"product"] intValue] inSection:0];
        UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        attribute.size = cellRect.size;
        attribute.center = CGPointMake(cellRect.origin.x + attribute.size.width / 2, cellRect.origin.y + attribute.size.height / 2);
        [attributes addObject:attribute];
    } else if (cellRect.origin.x > rect.origin.x + rect.size.width && cellRect.origin.y > rect.origin.y + rect.size.height) {
        break;
    }
}
return attributes;
}

在布局更改时,无论 layoutAttributesForElementsInRect 中定义的单元格数量是否受限,结果都几乎相同。如果不受限制,系统要么获取其中所有单元格的布局属性,要么如果它受到限制,它会为所有缺失的单元格调用 layoutAttributesForElementAtIndexPath 方法。总的来说,每个单元格的属性都以某种方式被使用。

-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
RPDataModel *dm = [RPDataModel sharedInstance];
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGRect cellRect = [self.rp getCell:[dm.indexDictionary[@(indexPath.item)] intValue]];
attribute.size = cellRect.size;
attribute.center = CGPointMake(cellRect.origin.x + attribute.size.width / 2, cellRect.origin.y + attribute.size.height / 2);
return attribute;
}    

最佳答案

在没有看到代码的情况下,我猜测您的 layoutAttributesForElementsInRect 方法正在遍历您集合中的所有项目,这反过来又导致其他方法被过度调用。 layoutAttributesForElementsInRect 给你一个提示 - 也就是说,它传递给你的 CGRect - 关于你需要为哪些项目调用 layoutAttributesForItemAtIndexPath ,根据屏幕上的内容。

所以这可能是性能问题的一部分 - 也就是说,调整您的自定义布局,使其能够智能地判断正在更新的项目。

其他问题一般与动画性能有关。需要注意的一件事是是否正在进行任何类型的合成 - 确保您的图像是不透明的。另一件事是,如果您在图像上使用阴影,那么动画效果可能会很昂贵。提高阴影动画性能的一种方法是在调整图像大小时设置 shadowPath 值 - 如果您确实有阴影,请告诉我并发布一些用于执行此操作的代码。

关于ios - performBatchUpdates 上的 UICollectionView 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12563997/

相关文章:

ios - 如何在Objective-C中使用发件人属性

python - numpy 数组上的余数函数 (%) 运行时间远长于手动余数计算

c# - xbox 性能陷阱

ios - 有焦点时突出显示 ios 文本框的简单方法?

iphone - 计算给定宽度和字体大小的行数

cordova - 新的 ios6 架构错误 : file is universal (3 slices) but does not contain a(n) arm7vs slice

ios - 从后台返回后 UIView 动画被阻止 ios8 (Rubymotion)

ios - 临时分发在 iOS7 中被破坏

ios - Objective-C 将 NSURL 传递给另一个 View Controller

Java Flight Recorder 未报告所有 GC 事件