问题描述
在处理一个新项目时,我们的团队决定使用 UICollectionViewDiffableDataSource
来处理我们的集合视图。它工作正常,但我们通过带有消息 Invalid parameter not satisfying: initialSnapshot.numberOfSections == initialSections.count
的在线工具记录了(很少)崩溃。我们似乎无法在本地重现这一点。
崩溃发生在我们用新数据更新数据源时,特别是在 dataSource.apply(snapshot)
。我们不确定这会如何发生,因为数据总是以相同的方式创建。
具体来说,处理这个视图的单元决定放弃创建截面模型,而是决定使用 Int
作为截面标识符,因为他们不想使用截面,只想显示项目。这是我以前从未见过的一件事,但 Int
满足标识符的要求,因此代码确实可以正确编译。
代码如下:
集合视图和数据源创建
这些变量位于以编程方式创建的 UIView 的类中。
var collectionView = UICollectionView(frame: .zero,collectionViewLayout: createCollectionViewLayout())
lazy var dataSource = UICollectionViewDiffableDataSource<Int,URL>(collectionView: collectionView,cellProvider: provideCell(_:indexPath:item:))
更新数据源
func updateUI() {
var snapshot = dataSource.snapshot()
snapshot.deleteallItems()
snapshot.appendSections([0])
if let urls = viewmodel?.imageUrls {
snapshot.appendItems(urls)
}
dataSource.apply(snapshot)
}
在我测试过的所有(生产)案例中,viewmodel?.imageUrls
在第一次调用时为空,然后在第二次调用和之后的所有调用中包含项目。项目的数量通常不会改变。
我曾考虑不使用 dataSource.snapshot()
而是创建一个新的,这样我也不必每次都调用 deleteallItems()
。但是,当我无法确定这是否真的解决了问题时,我不想仅仅将其作为解决方案。
有没有人遇到过这样的问题?使用 Int
作为部分标识符是否正确?崩溃的其他原因可能是什么?
解决方法
我的猜测是您只删除了项目,并且每次在快照中添加了一个附加部分,这会导致错误。 因此,如果您的 Snapshot 已经有一个“0”部分,您就不需要每次都添加一个新的。
在我的项目中,我每次都会创建一个新快照:
var snapshot = NSDiffableDataSourceSnapshot<Int,URL>()
snapshot.appendSections([0])
if let urls = viewModel?.imageUrls {
snapshot.appendItems(urls,toSection: 0)
}
customDataSource.apply(snapshot,animatingDifferences: animate)
WWDC 视频中使用了相同的方法。