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
相关产品推荐
相关产品推荐

