如何在不干扰动画的情况下更新UICollectionView补充视图?
解决方案
要在不干扰UICollectionView动画的前提下更新footer文本,最符合Apple性能规范的方式是直接获取当前显示的footer视图并更新其内容配置,无需重新加载数据或修改数据源快照。
核心思路
footer视图的内容配置只会在初始化或复用时读取footerText,直接修改footerText不会触发视图更新。我们可以主动获取当前可视的footer视图,直接更新它的contentConfiguration——这种方式不会触发任何集合视图动画,性能最优。同时,对于不可视的footer,当它滚动到可视区域时,复用机制会自动读取最新的footerText完成配置。
修改代码
将原代码中的footerText属性改为带didSet的实现,在属性变更时更新footer视图:
var footerText = "Initial footer text" { didSet { // 获取对应section的footer视图 guard let footer = collectionView.supplementaryView( forElementKind: UICollectionView.elementKindSectionFooter, at: IndexPath(row: 0, section: Section.first.rawValue) ) as? UICollectionViewListCell else { return } // 更新footer的内容配置 var contentConfig = footer.contentConfiguration as? UIListContentConfiguration ?? UIListContentConfiguration.cell() contentConfig.text = footerText footer.contentConfiguration = contentConfig } }
为什么之前的方案不行
- 重新配置
supplementaryViewProvider:仅替换了视图提供者,但不会触发已有footer视图的更新,文本不会变化。 - 重新应用快照:会触发集合视图的全局刷新逻辑,可能干扰正在进行的动画,且完全没必要——因为数据源的section/item没有任何变化。
- 调用
reconfigureItems:该API针对的是cell,对supplementary view无效,还会带来不必要的刷新开销。
多section场景适配
如果你的集合View包含多个section,只需遍历所有section的indexPath,依次获取并更新对应footer视图即可:
var footerText = "Initial footer text" { didSet { Section.allCases.forEach { section in let indexPath = IndexPath(row: 0, section: section.rawValue) guard let footer = collectionView.supplementaryView( forElementKind: UICollectionView.elementKindSectionFooter, at: indexPath ) as? UICollectionViewListCell else { return } var contentConfig = footer.contentConfiguration as? UIListContentConfiguration ?? UIListContentConfiguration.cell() contentConfig.text = footerText footer.contentConfiguration = contentConfig } } }
内容的提问来源于stack exchange,提问作者Filippo
相关产品推荐
相关产品推荐

