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

使用NSDiffableDataSourceSectionSnapshot时点击cell更新section counter不生效如何解决

问题核心原因

1. 值类型修改未同步到本地数据源

TestParent是结构体(值类型),你从DiffableDataSource快照中取出的section是值拷贝,修改局部section.counter不会同步到你自己维护的parents数据源数组,同时修改后的实例和快照中原有section的Hash值不同,reloadSections无法匹配到目标section,不会触发刷新。

2. Section标识的Hash计算包含可变属性

默认自动合成的Hashable实现会把counter这类可变属性纳入Hash计算,同一个逻辑section修改counter后会被DiffableDataSource判定为不同section,无法正确识别更新。

解决方案

第一步:修改TestParent的Hash规则,仅用唯一标识匹配

struct TestParent: Hashable {
    // 新增唯一标识,区分不同section
    let id = UUID()
    var title = String()
    var counter = 0
    var children = [TestChildren]()

    // 仅用id判断是否为同一个section
    static func == (lhs: TestParent, rhs: TestParent) -> Bool {
        lhs.id == rhs.id
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

第二步:修改点击事件逻辑,先更新本地数据源再刷新

如果你的sectionHeader配置是直接从parents数组按索引读取counter值,用简化版代码即可:

fileprivate func check(indexPath: IndexPath) {
    guard let children = self.dataSource?.itemIdentifier(for: indexPath) as? TestChildren else { return }
    guard let oldSection = self.dataSource?.snapshot().sectionIdentifier(containingItem: children) as? TestParent else { return }
    // 找到本地数据源中对应的parent,更新counter
    guard let targetIndex = parents.firstIndex(where: { $0.id == oldSection.id }) else { return }
    parents[targetIndex].counter += 1

    // 直接刷新对应section
    var mainSnapshot = dataSource?.snapshot()
    mainSnapshot?.reloadSections([oldSection])
    dataSource?.apply(mainSnapshot!, animatingDifferences: false)
}

如果你需要快照中存储的section实例本身包含最新的counter值,用完整更新逻辑:

fileprivate func check(indexPath: IndexPath) {
    guard let children = self.dataSource?.itemIdentifier(for: indexPath) as? TestChildren else { return }
    guard let oldSection = self.dataSource?.snapshot().sectionIdentifier(containingItem: children) as? TestParent else { return }
    guard let targetIndex = parents.firstIndex(where: { $0.id == oldSection.id }) else { return }
    parents[targetIndex].counter += 1
    let updatedSection = parents[targetIndex]

    // 替换快照中的旧section实例
    var mainSnapshot = dataSource?.snapshot()
    mainSnapshot?.insertSections([updatedSection], afterSection: oldSection)
    mainSnapshot?.deleteSections([oldSection])
    dataSource?.apply(mainSnapshot!, animatingDifferences: false)
    // 重新应用该section的子项快照
    dataSource?.apply(parentSnapshot(updatedSection), to: updatedSection)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:09:04