我正在尝试使用UICollectionView模仿UITableView布局。
layout.itemSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 44.0f);
我注册了可重复使用的单元格类。
[self.collectionView registerClass:[SampleCell class]
forCellWithReuseIdentifier:NSStringFromClass([SampleCell class])];
注意:SampleClass
只是UICollectionViewCell
的子类,不包含任何内容。
并符合数据源:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 28;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([SampleCell class])
forIndexPath:indexPath];
return cell;
}
我发现SampleCell
没有被重用。为了验证它,我们可以简单地在UICollectionView
中记录子视图的数量。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"number of subviews in collection view is: %li", (long)self.collectionView.subviews.count);
}
滚动后,我得到了这个日志:
集合视图中的子视图数量为:30
集合视图中的子视图数量为:30
集合视图中的子视图数量为:30
集合视图中的子视图数量为:30
请注意,有30个子视图(其中2个是滚动视图指示器)。
这意味着显示的所有28个项目都没有从超级视图中删除不可见的单元格。为什么会这样?
为了简化您的工作,我在Github上提供了一个示例项目。 https://github.com/edwardanthony/UICollectionViewBug
我还使用内存图层次结构调试器检查了内存分配,并且分配了28次。
答案 0 :(得分:3)
我确实可以工作,只是由于更积极的缓存而保留了更多的内存。如果您尝试将项目数从28更改为100,则在滚动时会看到它停留在33个子视图中。
尝试将以下代码添加到您的SampleCell
类中,您将看到它被调用,但可能与您期望的不太一样。
- (void)prepareForReuse {
[super prepareForReuse];
NSLog(@"prepareForReuse called");
}
UICollectionView
的缓存方案比UITableView
(或至少以前的缓存方案)更高级,这就是您看到自己要做什么的原因。根据文档,它说默认情况下启用单元格预取:
UICollectionView提供了两种预取技术,可用于 提高响应速度:
单元格预取会在 他们需要的时间。当集合视图需要较大的视图时 同时显示的单元数-例如,网格中的新单元格行 布局-要求的单元早于所需的时间 显示。因此,单元格渲染分布在多个布局中 通过,从而获得更流畅的滚动体验。细胞预取 默认情况下启用。
数据预取提供了一种机制 系统会在通知您有关收集视图的数据要求 提前要求细胞。如果以下内容有用, 您的单元格依赖昂贵的数据加载过程,例如 网络请求。分配符合以下条件的对象 UICollectionViewDataSourcePrefetching协议 prefetchDataSource属性以接收有关何时进行的通知 预取单元格数据。
您可以通过将以下行添加到示例中的setupCollectionView
函数来关闭单元格预取:
self.collectionView.prefetchingEnabled = NO;
这样做将使您的示例按预期工作。在我的情况下,子视图数将降至18。
答案 1 :(得分:1)
我怀疑对子视图进行计数不会反映单元格的重用。子视图可能包含多个对同一单元的引用。要计算使用的单元格数量,您可以记录UICollectionViewCell子类初始化的次数。只需重写它的init方法,然后在其中放置打印语句即可。
要注意的另一件事(对不起,如果很明显),如果所有单元格都在屏幕上可见,则不会发生重用。当单元在滚动过程中离开屏幕时,就会发生单元重用。