保留对 UICollectionView 标头的引用

Posted

技术标签:

【中文标题】保留对 UICollectionView 标头的引用【英文标题】:Keep a reference to UICollectionView header 【发布时间】:2020-07-07 04:30:16 【问题描述】:

我需要存储一个视图以用作 UICollectionView 标头。我不希望它循环出内存,因为它需要保留其状态/数据等。

使用表格视图,您只需执行tableView.tableHeaderView = view

这是我正在尝试的:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView 

        switch kind 
        case MagazineLayout.SupplementaryViewKind.sectionHeader:
            if let t = headerView  //headerView is an instance var
                return t
             else 
                let view = collectionView.dequeueReusableSupplementaryView(ofKind: MagazineLayout.SupplementaryViewKind.sectionHeader, withReuseIdentifier: "MyHeaderView", for: indexPath) as! MyHeaderView
                view.titleLabel.text = "test"
                view.switch.addAction(for: .valueChanged,  [weak self] in
                    self?.switchValueChanged()
                )
                headerView = view
                return view
            
        ...
    

我不想在每次用户滚动它然后再返回时重新创建它,所以我试图存储对它的引用。这虽然行不​​通。很难解释,但它显示的视图被切断并且开关没有响应。如果我注释掉“if”部分并每次只创建一个新部分,它看起来正确但状态丢失(即开关关闭)这样做的最佳方法是什么?

【问题讨论】:

它不会在用户每次滚动然后返回时重新创建。您只需要更改文本,重新添加切换操作。但是对于您的问题,如果您想继续参考它,我认为您不应该调用collectionView.dequeueReusableSupplementaryView,而是将其替换为MyHeaderView.init 这不太行。你会得到一个错误 - was not retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: or is nil 哦,我明白了。但是您的实现不起作用,因为 when user scrolls and then go back,标头被标记为可重用,被 prepareForReuse 方法等调用... 【参考方案1】:

由于您保留引用并且在它滚动出视图时不让它释放,所以完全删除registerdequeuing。对我来说效果很好,方法如下:

let view = MyHeaderView()
override func viewDidLoad() 
    super.viewDidLoad()
    view.titleLabel.text = "test"
    view.switch.addAction(for: .valueChanged,  [weak self] in
        self?.switchValueChanged()
    )

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView 
    switch kind 
    case MagazineLayout.SupplementaryViewKind.sectionHeader:
        return view
        //...
    

【讨论】:

不幸的是我得到了这个:*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath (MagazineLayoutSupplementaryViewKindSectionHeader,<NSIndexPath: 0x600002aa6180> length = 2, path = 0 - 0) was not retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath 所以它似乎在强迫你使用dequeueReusableSupplementaryViewOfKind

以上是关于保留对 UICollectionView 标头的引用的主要内容,如果未能解决你的问题,请参考以下文章

快速滚动后在 UICollectionView 中保留按钮内容

无法使 UICollectionView 标头工作

Swift UICollectionView 标头未正确显示

在 UICollectionView 中使用 reloadData 时如何从重新加载中排除标头

UICollectionView 标头重复每一行

向浮动 UICollectionView 标头添加阴影