应用 NSDiffableDataSourceSnapshot 是否损坏?

问题描述 投票:0回答:3

我在将

NSDiffableDataSourceSnapshot
应用于
UICollectionViewDiffableDataSource
时遇到问题。想象一下这种情况:我有两个项目,我想删除第二个项目,并且我想重新加载该部分中的所有其他项目。

我这样做:

var snapshot = oldSnapshot
if let item = getterForItemToDelete() {
    snapshot.deleteItems([item])
}
snapshot.reloadItems(otherItems)

但是随后在数据源应用程序的单元格提供程序中崩溃,因为它尝试获取我不再有数据的项目标识符的单元格,因此我必须返回

nil

let dataSource = MyDataSource(collectionView: collectionView) { [weak self] collectionView, indexPath, identifier in
    guard let viewModel = self?.viewModel.item(for: identifier) else { return nil }
    ...
}

奇怪的是,当我尝试调试它并在应用快照时打印我的项目时,它会打印一项:

(lldb) print snapshot.itemIdentifiers(inSection: .mySection)
([App.MyItemIdentifier]) $R0 = 1 value {
  [0] = item (item = "id")
}

但是,在此之后,在手机提供商中我立即得知我有两件物品,但我没有

(lldb) print self?.dataSource.snapshot().itemIdentifiers(inSection: .mySection)
([App.MyItemIdentifier]) $R1 = 2 values {
  [0] = item (item = "ckufpa58100041ps6gmiu5zl6")
  [1] = item (item = "ckufpa58100051ps69yrgaspv")
}

更奇怪的是,当我有 3 个项目并且我想删除其中一个并重新加载其他项目时,不会发生这种情况。

解决我的问题的一个解决方法是在单元提供程序中返回空单元而不是

nil

let dataSource = MyDataSource(collectionView: collectionView) { [weak self] collectionView, indexPath, identifier in
    guard let viewModel = self?.viewModel.item(for: identifier) else { 
        return collectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", for: indexPath)
    }
    ...
}

最后一件奇怪的事情是,当我执行此操作然后查看“查看层次结构”调试器时,只有一个单元格,因此似乎空单元格被删除了。

有人知道我可能做错了什么还是这只是预期的行为?因为我在文档中没有发现任何提及为某种优化、动画或其他内容提供单元格的内容。

swift uicollectionview uicollectionviewdiffabledatasource nsdiffabledatasourcesnapshot
3个回答
0
投票

您不应该从快照中删除项目。将它们从阵列中删除。使用更新后的数组再次创建数据源,并使用这个新创建的数据源调用快照。 CollectionView 将自动更新新数据。更简单地说,更改数组,然后再次 applySnapshot() 。


0
投票

我在尝试修复我正在开发的应用程序上的类似错误时偶然发现了这个问题。

var snapshot = oldSnapshot
if let item = getterForItemToDelete() {
    snapshot.deleteItems([item])
}
dataSource?.apply(snapshot, animatingDifferences: true) { [weak self] in
    self?.collectionView.setNeedsLayout()
}

我不确定为什么,但是

NSDiffableDataSourceSnapshot
不会在删除时自动触发它引用的 collectionView/tableView 的布局更新,因此在完成快照更新后,您可以告诉您的 collectionView/tableView 重新加载其布局它就像一个魅力。


0
投票

尝试使用

applySnapshotUsingReloadData

© www.soinside.com 2019 - 2024. All rights reserved.