7

我们正在尝试使用自定义布局设置 UICollectionView。每个 CollectionViewCell 的内容将是一个图像。总体而言,将有数千张图像,并且在某个特定时间可以看到大约 140-150 张图像。在一个动作事件上,所有单元格的位置和大小都可能重新组织。目标是为当前使用 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;
}    
4

2 回答 2

4

Without seeing code, my guess is that your layoutAttributesForElementsInRect method is iterating through all of the items in your collection, and that is, in turn, what is causing the other methods to get over-called. layoutAttributesForElementsInRect is giving you a hint - that is, the CGRect it is passing to you - about which items you need to call layoutAttributesForItemAtIndexPath for, in terms of what is on the screen.

So that may be part of the performance issue - that is, tuning your custom layout so it is being smart about which items it is updating.

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

于 2012-09-24T23:03:39.053 回答
0

这似乎是由于尝试将单元格添加到具有标题视图但其中没有单元格的部分所致。

该错误消息非常无用,并且需要花费几个小时的努力才能找到它。

于 2013-01-15T23:59:23.670 回答