ios - UICollectionView 不重用单元格

标签 ios objective-c uicollectionview uikit uicollectionviewcell

我正在尝试使用 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 中 subview 的数量。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"number of subviews in collection view is: %li", (long)self.collectionView.subviews.count);
}

滚动后,我得到了这个日志:

number of subviews in collection view is: 30

number of subviews in collection view is: 30

number of subviews in collection view is: 30

number of subviews in collection view is: 30

请注意,有 30 个 subview (其中 2 个是 ScrollView 指示器)。

这意味着所有 28 个项目都会显示,而不会从 super View 中删除不可见的单元格。为什么会出现这种情况?

为了让您更轻松,我在 Github 上提供了一个示例项目。 https://github.com/edwardanthony/UICollectionViewBug

更新:

我还使用内存图层次结构调试器检查了内存分配,它被分配了 28 次。

最佳答案

我确实工作了,只是由于更积极的缓存而在内存中保留了更多一点。如果您尝试将项目数量从 28 更改为 100,您会发现滚动时 subview 仍为 33 个。

尝试将以下代码添加到您的 SampleCell 类中,您将看到它被调用,但可能并不完全符合您的预期。

- (void)prepareForReuse {
    [super prepareForReuse];

    NSLog(@"prepareForReuse called");
}

UICollectionView 具有比 UITableView 更高级的缓存方案(或者至少像以前一样),这就是您看到自己所做的事情的原因。根据文档,它说默认情况下启用单元格预取:

UICollectionView provides two prefetching techniques you can use to improve responsiveness:

  • Cell prefetching prepares cells in advance of the time they are required. When a collection view requires a large number of cells simultaneously—for example, a new row of cells in grid layout—the cells are requested earlier than the time required for display. Cell rendering is therefore spread across multiple layout passes, resulting in a smoother scrolling experience. Cell prefetching is enabled by default.

  • Data prefetching provides a mechanism whereby you are notified of the data requirements of a collection view in advance of the requests for cells. This is useful if the content of your cells relies on an expensive data loading process, such as a network request. Assign an object that conforms to the UICollectionViewDataSourcePrefetching protocol to the prefetchDataSource property to receive notifications of when to prefetch data for cells.

  • 您可以通过将此行添加到示例中的 setupCollectionView 函数来关闭单元格预取:

    self.collectionView.prefetchingEnabled = NO;
    

    这样做将使您的示例按您的预期工作。在我的例子中, subview 计数将下降到 18。

    关于ios - UICollectionView 不重用单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56962221/

    相关文章:

    objective-c - 为什么属性(property)会基本上消失? Obj-C, cocoa

    objective-c - 'applicationDidBecomeActive' 之后调用了什么方法?

    swift - 类型 'UICollectionView' 的值没有成员 'beginUpdates' - Swift 3 问题

    ios - 在后台线程上加载 SpriteKit 场景会导致应用程序因内存问题而崩溃

    ios - 无法访问 iOS SQLite 数据库 : sqlite3_prepare_v2 and 'no such table' sqlite3_errmsg

    ios - 我可以通过 iOS Multipeer Connectivity 发送多大的消息?

    ios - 如何从外部 UICollectionView 更改 UICollectionView 单元格背景颜色

    iOS Swift "isSourceTypeAvailable"错误

    iphone - 视频混音器API?

    ios - 异步加载图像,单元格中的图像错误