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

UICollectionView数据更新后Cell未同步更新问题求助

问题解决:UICollectionView切换星标后原Cell状态未更新

核心问题原因

  1. Object的Hashable实现不完整:当前仅用name判断对象相等和计算哈希值,isStarredObject变化时,DiffableDataSource无法识别对象已更新,因此不会刷新对应Cell。
  2. Cell未在数据更新时同步按钮状态:object属性赋值后仅更新标签,未调用updateButton同步星标状态。
  3. 快照刷新逻辑冗余:手动处理差异的逻辑存在疏漏,未确保所有对象的星标状态被正确同步到快照。

解决方案及代码修改

1. 修复Object的Hashable实现

将isStarredObject纳入相等判断和哈希计算,确保状态变化能被DiffableDataSource识别:

extension Object: Hashable {
    static func == (lhs: Object, rhs: Object) -> Bool {
        return lhs.name == rhs.name && lhs.isStarredObject == rhs.isStarredObject
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(isStarredObject)
    }
}

2. 完善Cell的object属性didSet方法

每次赋值object后立即同步按钮状态:

var object: Object? {
    didSet {
        if let object = object {
            self.label.text = object.name
            self.updateButton() // 新增:同步按钮状态
        }
    }
}

3. 简化refreshSnapshot逻辑

直接生成排序后的数组,利用DiffableDataSource自动处理差异:

func refreshSnapshot() {
    guard let dataSource = dataSource else { return }
    
    // 生成排序后的数组:星标对象在前,其余按原顺序
    let starred = objects.filter { $0.isStarredObject }
    let unstarred = objects.filter { !$0.isStarredObject }
    let sortedObjects = starred + unstarred
    
    var snapshot = NSDiffableDataSourceSnapshot<Int, Object>()
    snapshot.appendSections([0])
    snapshot.appendItems(sortedObjects)
    dataSource.apply(snapshot, animatingDifferences: true)
}

4. 优化Cell的updateButton方法

移除不必要的delegate判断,仅依赖object状态:

func updateButton() {
    guard let object = object else {
        print("No object assigned to cell")
        return
    }
    
    if object.isStarredObject {
        let newImage = UIImage(systemName: "star.fill", withConfiguration: imageConfig)
        self.button.setImage(newImage, for: .normal)
        self.button.isEnabled = false
    } else {
        let newImage = UIImage(systemName: "star", withConfiguration: imageConfig)
        self.button.setImage(newImage, for: .normal)
        self.button.isEnabled = true
    }
}

5. 移除自定义的applyDifferences扩展

DiffableDataSource会自动计算并应用快照差异,无需手动处理,可删除该扩展:

// 移除以下扩展
// extension NSDiffableDataSourceSectionSnapshot {
//     mutating func applyDifferences(newItems: [ItemIdentifierType]) {
//         ...
//     }
// }

验证效果

修改后,点击新的空心星Cell时:

  • 原星标对象的isStarredObject被设为false
  • 新对象的isStarredObject被设为true
  • 快照刷新时,DiffableDataSource识别到对象状态变化,自动刷新所有受影响的Cell
  • 排序逻辑正常,星标对象始终排在首位

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:57:00