You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UICollectionView.CellRegistration无法访问更新后数据源值如何解决

问题原因&解决方案

核心问题点

  • 调用顺序错误:viewDidLoad 中先执行 displayEvents() 再初始化 collectionViewDataSource,此时数据源为 nil,第一次快照应用完全无效,数据源初始化后也没有关联任何数据。
  • 未主动触发数据刷新:fetchEvents 拉取到最新数据后,你没有在它的完成回调里调用 displayEvents() 刷新快照,Diffable 数据源感知不到数据变化,一直持有旧的 Item 列表。
  • (可选但必须优化)Event 作为 Diffable 数据源的 Item 类型,默认自动合成的 Hashable 和 Equatable 会用所有属性参与判断,当只有 streamState 变化时可能导致 Diff 逻辑异常,也会增加不必要的计算开销。
  • (如果是代码拼写问题)你在 displayEvents 中写的 eventDataSource.Events 是错误的,EventDataSource 中存储数组的属性名是小写的 events,如果实际代码也是大写会拿不到正确的数组。
  • 多余的刷新操作:displayEvents 中不需要调用 collectionView.reloadData(),Diffable 数据源应用快照后会自动处理刷新逻辑,额外调用反而可能引发渲染异常。

修复代码

1. 修正 Event 的 Hashable 实现

struct Event: Codable, Hashable {
    let id: String
    let name: String
    let streamState: String

    static func == (lhs: Event, rhs: Event) -> Bool {
        lhs.id == rhs.id
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

2. 修正 viewDidLoad 执行顺序

override func viewDidLoad() {
    super.viewDidLoad()
    // 先初始化数据源
    configureDataSource()
    // 拉取数据完成后再刷新列表
    eventDataSource.fetchEvents { [weak self] in
        self?.displayEvents()
    }
}

3. 修正 displayEvents 实现

func displayEvents() {
    // 每次刷新新建快照即可,不需要全局持有
    var snapshot = NSDiffableDataSourceSnapshot<Section, Event>()
    snapshot.appendSections([.list])
    // 修正属性名拼写
    snapshot.appendItems(eventDataSource.events)
    collectionViewDataSource?.apply(snapshot, animatingDifferences: false)
}

注意事项

后续你每次调用 fetchEvents 拉取新数据,都需要在它的完成回调中调用 displayEvents 刷新快照,Diffable 数据源才会更新 Item 列表,触发 Cell 重新渲染。

内容的提问来源于stack exchange,提问作者Yuuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 15:15:02