`UICollectionViewLayout` 如何访问不可见单元格的数据?

Posted

技术标签:

【中文标题】`UICollectionViewLayout` 如何访问不可见单元格的数据?【英文标题】:How can `UICollectionViewLayout` access data for invisible cells? 【发布时间】:2014-04-25 17:12:37 【问题描述】:

我想从数据源获取所有数据——包括可见的不可见的单元格——以便计算可见单元格的属性。 collectionView:cellForItemAtIndexPath: 不起作用,因为它为不可见的单元格返回 nil。如UICollectionView API中所述:

返回值

对应索引路径的单元格对象,如果单元格不可见或indexPath超出范围,则为nil

关于如何在不破坏 MVC 约束的情况下获取底层数据(例如,在布局中存储对数据的引用)的任何想法?

【问题讨论】:

也许你可以扩展这个问题?从布局的角度来看,prepareLayout方法中,能不能不查询collectionView.dataSource的numberOfSections /numberOfItemsInSection,并相应地应用UICollectionViewLayoutAttributes? 是的,我可以访问每个部分的部分和项目数。但我正在尝试访问不可见单元格的内容,因为它们的内容会影响可见单元格的框架。 【参考方案1】:

我面临的主要问题是我需要来自底层数据源的信息来设置可见和不可见单元格的属性以及补充视图。 UICollectionViewDelegate 协议要求单元在布局属性已设置后出列,即使实现类(通常UICollectionViewController 可以访问数据源)。

委托对象可以扩展以提供附加信息的Collection View Programming Guide hints。使用UICollectionViewDelegateFlowLayout 作为reference,我创建了一个新协议,该协议声明了我需要的数据的方法。然后我的UICollectionViewController 子类通过实现这些方法来符合该协议,而无需任何布局操作(如出列视图单元格)。

我的协议如下所示:

@protocol MyCollectionViewDelegateLayout <UICollectionViewDelegate>
- (CGSize)sizeForCellAtIndexPath:(NSIndexPath *)indexPath;
- (CGSize)sizeForHeaderAtIndexPath:(NSIndexPath *)indexPath;
@end

我的集合视图控制器具有以下结构:

@interface MyCollectionViewController : UICollectionViewController
    <MyCollectionViewDelegateLayout>
...
@end

@implementation MyCollectionViewController
...
- (CGSize)sizeForCellAtIndexPath:(NSIndexPath *)indexPath

    // Make calculations based on data at index path.
    return CGSizeMake(width, height);

- (CGSize)sizeForHeaderAtIndexPath:(NSIndexPath *)indexPath;

    // Make calculations based on data at index path.
    return CGSizeMake(width, height);

在我的UICollectionViewLayout 子类的prepareLayout 方法中,我调用这些方法来预先计算必要的属性:

@implementation MyCollectionViewLayout
...
- (void)prepareLayout

    ...
    // Iterate over sections and rows...
    id dataSource = self.collectionView.dataSource;
    if ([dataSource respondsToSelector:@selector(sizeForCellAtIndexPath:)]) 
        CGSize size = [dataSource sizeForCellAtIndexPath:indexPath];
     else 
        // Use default values or calculate size another way
    
    ...

...

使用扩展的数据源协议允许代码维护 MVC 关注点分离。在这里,布局类仍然对底层数据一无所知,但能够使用它来定义属性。相反,控制器类没有布置任何东西,而只是根据基础数据提供大小提示。

【讨论】:

这正是我想要的。谢谢!

以上是关于`UICollectionViewLayout` 如何访问不可见单元格的数据?的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewLayout 教程

我应该继承啥 UICollectionViewLayout 或 UICollectionViewFlowLayout

使用缓存的 UICollectionViewLayoutAttributes 子类化 UICollectionViewLayout

UICollectionViewLayout - 2 列中的 3 个单元格

为啥将 UICollectionViewLayout 分配给 UICollectionView 后 UICollectionViewCells 不再可见?

自定义 UICollectionViewLayout 不同的单元格大小