swift - 在 NSCollectionViewDiffableDataSource 中附加部分
问题描述
我正在尝试使用和创建一个NSCollectionView
具有动态数量的部分。NSCollectionViewDiffableDataSource
NSCollectionViewCompositionalLayout
集合视图用于显示搜索结果,部分的数量取决于找到的结果的类型和数量。每个部分使用不同的布局显示其内容类型。
数据源被声明为NSCollectionViewDiffableDataSource<String, SearchResult>
where SearchResult
is a class implementation Hashable
using UUID()
。结果为零的部分不是空的,而是在集合视图中不存在。
当显示我的视图控制器时,我清除现有的搜索结果:
func clearSearchResults(animate: Bool) {
let snapshot = NSDiffableDataSourceSnapshot<String, SearchResult>()
dataSource.apply(snapshot, animatingDifferences: animate)
}
执行搜索时,我尝试为找到的每种类型的结果在集合视图中添加一个部分:
// Code that performs the search
var snapshot = NSDiffableDataSourceSnapshot<String, SearchResult>()
// If I append more than one section an exception is thrown in apply():
// snapshot.appendSections([ViewController.trackSection, ViewController.albumSection])
snapshot.appendSections([ViewController.trackSection])
snapshot.appendItems(tracks, toSection: ViewController.trackSection)
// This also causes an exception in apply():
// snapshot.appendSections([ViewController.albumSection])
// snapshot.appendItems(albums, toSection: ViewController.albumSection)
dataSource.apply(snapshot, animatingDifferences: true)
堆栈跟踪是:
2019-11-10 13:34:29.883728-0600 DiffableTest[64931:1820050] [General] An uncaught exception was raised
2019-11-10 13:34:29.883813-0600 DiffableTest[64931:1820050] [General] -[NSCollectionView insertSections:] Section index 1 out of bounds
2019-11-10 13:34:29.883937-0600 DiffableTest[64931:1820050] [General] (
0 CoreFoundation 0x00007fff33a98f53 __exceptionPreprocess + 250
1 libobjc.A.dylib 0x00007fff69b5e835 objc_exception_throw + 48
2 CoreFoundation 0x00007fff33a98da9 +[NSException raise:format:] + 189
3 UIFoundation 0x00007fff6469fd5b -[_NSCollectionViewCore insertSections:] + 267
4 UIFoundation 0x00007fff6465dd5e -[_NSDiffableDataSourceViewUpdater _performNSCollectionViewInsertUpdate:] + 222
5 UIFoundation 0x00007fff6465db33 -[_NSDiffableDataSourceViewUpdater _performViewUpdates:] + 594
6 AppKit 0x00007fff3156d8e8 __58-[NSCollectionView performBatchUpdates:completionHandler:]_block_invoke + 21
7 UIFoundation 0x00007fff646aabe5 -[_NSCollectionViewCore _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 323
8 UIFoundation 0x00007fff646aaa7f -[_NSCollectionViewCore _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 90
9 UIFoundation 0x00007fff646aaa02 -[_NSCollectionViewCore _performBatchUpdates:completion:invalidationContext:] + 74
10 UIFoundation 0x00007fff646aa957 -[_NSCollectionViewCore performBatchUpdates:completion:] + 53
11 AppKit 0x00007fff3156d7f4 -[NSCollectionView performBatchUpdates:completionHandler:] + 282
12 UIFoundation 0x00007fff6465d2ee -[_NSDiffableDataSourceViewUpdater _performUpdateWithCollectionViewUpdateItems:dataSourceSnapshotter:updateHandler:completion:] + 528
13 UIFoundation 0x00007fff646c72a2 -[__NSDiffableDataSource _commitNewDataSource:withViewUpdates:completion:] + 265
14 UIFoundation 0x00007fff646c1cb9 __66-[__NSDiffableDataSource applyDifferencesFromSnapshot:completion:]_block_invoke.259 + 190
15 UIFoundation 0x00007fff646c1fd2 __66-[__NSDiffableDataSource applyDifferencesFromSnapshot:completion:]_block_invoke.284 + 170
16 libdispatch.dylib 0x000000010039e78f _dispatch_client_callout + 8
17 libdispatch.dylib 0x00000001003af4cb _dispatch_lane_barrier_sync_invoke_and_complete + 135
18 UIFoundation 0x00007fff646c172d -[__NSDiffableDataSource applyDifferencesFromSnapshot:completion:] + 842
19 UIFoundation 0x00007fff64765417 +[_NSUIAnimator performWithAnimation:] + 90
20 UIFoundation 0x00007fff646c2939 -[__NSDiffableDataSource applyDifferencesFromSnapshot:animatingDifferences:completion:] + 158
21 libswiftAppKit.dylib 0x00007fff6a2f6bb3 $s6AppKit34NSCollectionViewDiffableDataSourceC5apply_20animatingDifferences10completionyAA010NSDiffablefG8SnapshotVyxq_G_SbyycSgtF + 211
22 DiffableTest 0x0000000100005c73 $s12DiffableTest14ViewControllerC13performSearchyyyXlSgF + 3059
我是否以某种方式滥用 API?
有关示例项目,请参阅https://github.com/sbooth/DiffableTest 。
解决方案
我发现有时需要调用apply(_:animatingDifferences:)
两次,一次是在appendSection(_:)
使用动画调用之后false
,一次是在调用之后appendItems(_:)
。
例如:
extension AnimalsViewController {
enum Section {
case main
}
private func makeDataSource() -> UITableViewDiffableDataSource<Section, String> {
UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, name in
let cell = tableView
.dequeueReusableCell(withIdentifier: CellIdentifier.animalCell.rawValue,
for: indexPath)
cell.textLabel?.text = name
return cell
}
}
private func update() {
activityIndicator.stopAnimating()
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.main])
dataSource.apply(snapshot, animatingDifferences: false)
snapshot.appendItems(viewModel.animalNames)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
推荐阅读
- bash - shell case 模式 [...] 不允许的字符
- javascript - 在特定时间更改 HTML 元素
- reactjs - 是否可以不使用 nextjs 中的 next-redux-wrapper for Redux?Context+useReducer 是否足以用于 NextJS 应用程序中的状态管理器?
- junit - 模拟一个自动装配的对象并从该对象调用一个方法
- javascript - 在更改事件上添加 CSS 类
- node.js - 如何获取 hubspot 中联系人的联系方式?
- c# - 如何使用 ReactiveUI 设置动态填充的 TabControl?
- python - 为什么使用 while 循环的斐波那契函数比 else 更快:return fib(n-1) + fib(n-2)?
- google-apps-script - AdWordsApp.report 失败但未显示错误
- typescript - 在 IonicSelect 上按 Tab 事件焦点不起作用