UICollectionView非常慢的自定义布局

时间:2013-03-02 18:10:45

标签: objective-c cocoa-touch uicollectionview uicollectionviewlayout

我正在使用带有自定义布局的UICollectionView,该布局以网格格式布局单元格。可以有超过50行和50列。滚动在垂直和水平方向都会发生。目前,我正在prepareLayout中进行所有布局设置并将其存储在数组中:

- (void)prepareLayout {

     NSMutableArray *newLayoutInfo = [[NSMutableArray alloc] init];
     NSMutableArray *newLinearLayoutInfor = [[NSMutableArray alloc] init];

     NSInteger sectionCount = [self.collectionView numberOfSections];
     NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];

     self.heightForRows = [delegate collectionViewHeightForAllRows];

     self.totalWidthsForRows = [[NSMutableArray alloc] init];

     for (int i = 0; i < sectionCount; i++) {
       [self.totalWidthsForRows addObject:[NSNumber numberWithInt:0]];
     }
     for (NSInteger section = 0; section < sectionCount; section++) {
       NSMutableArray *cellLayoutInfo = [[NSMutableArray alloc] init];


       NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];

     for (NSInteger item = 0; item < itemCount; item++) {
        indexPath = [NSIndexPath indexPathForItem:item inSection:section];

        UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        itemAttributes.frame = [self frameForCellAtIndexPath:indexPath];

        [cellLayoutInfo addObject:itemAttributes];
        [newLinearLayoutInfor addObject:itemAttributes];
    }
    [newLayoutInfo addObject:cellLayoutInfo];
}
self.layoutInfo = newLayoutInfo;
self.linearLayoutInfo = newLinearLayoutInfor;
}

然后在layoutAttributesForElementsInRect我有:

- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *rows = [self.linearLayoutInfo filteredArrayUsingPredicate:[NSPredicate    predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *evaluatedObject, NSDictionary *bindings) {
    return CGRectIntersectsRect(rect, [evaluatedObject frame]);
}]];

这没关系,但是当我有超过50列和50行时,它是滞后和跳跃的。我现在的问题是我必须设置

-(BOOL)shouldInvalidateLayoutForBoundsChange {
       return YES;
} 

这使得每次边界变化时都会准备好整个布局,不用说,这会对性能产生巨大影响,而且几乎无法滚动。单元格只包含不透明背景的文本,所以没有问题。

我确信我做得不对,必须有更好的方法。感谢您的帮助。

3 个答案:

答案 0 :(得分:9)

在自定义流程布局中,我这样做,似乎有所帮助:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
    return !(CGSizeEqualToSize(newBounds.size, self.collectionView.frame.size));
}

答案 1 :(得分:5)

-(BOOL)shouldInvalidateLayoutForBoundsChange {
       return YES;
} 

每次滚动时布局都会prepareLayout(),这意味着准备中任何繁重的计算都会导致延迟练习,因此解决这个问题的一个可能方向是检查实际需要花费多少时间。一种可能性是内在的

for (NSInteger section = 0; section < sectionCount; section++)
{
   // generate attributes ...
}

为了生成布局的属性。每次滚动时,每次这种概括重新运行时,它对滚动的影响似乎是跳跃和笨拙的。所以为了解决这个问题,或者至少要弄清楚这不是真正的麻烦,我建议在这个布局算法中设置一个标志,比如说, isScrolling ,代表布局需要的情况准备。每次在prepareLayout()检查标记时,如果是,那么我们就知道不需要 for loop 来重新生成所有属性,自第一次初始化布局以来,alreay exsit。

答案 2 :(得分:0)

好的 - 我现在明白了。以下是我的建议:创建3个集合视图...一个用于列标题(每个单元格是列标题),一个用于行标题(每个单元格= 1行标题)和一个集合视图。然后,当用户更改任何集合视图的滚动位置时,根据需要更新其他2个集合视图的滚动位置。

enter image description here