Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 在NSCollectionViewDiffableDataSource中附加节_Swift_Macos_Cocoa_Nscollectionview - Fatal编程技术网

Swift 在NSCollectionViewDiffableDataSource中附加节

Swift 在NSCollectionViewDiffableDataSource中附加节,swift,macos,cocoa,nscollectionview,Swift,Macos,Cocoa,Nscollectionview,我正在尝试使用NSCollectionViewDiffableDataSource和nsCollectionViewCompositionLayout创建一个具有动态节数的NSCollectionView 集合视图用于显示搜索结果,节的数量取决于找到的结果的类型和数量。每个部分使用不同的布局显示其内容类型 数据源声明为NSCollectionViewDiffableDataSource,其中SearchResult是一个使用UUID()实现Hashable的类。结果为零的节不是空的,而是不存在于

我正在尝试使用
NSCollectionViewDiffableDataSource
nsCollectionViewCompositionLayout
创建一个具有动态节数的
NSCollectionView

集合视图用于显示搜索结果,节的数量取决于找到的结果的类型和数量。每个部分使用不同的布局显示其内容类型

数据源声明为
NSCollectionViewDiffableDataSource
,其中
SearchResult
是一个使用
UUID()
实现
Hashable
的类。结果为零的节不是空的,而是不存在于集合视图中

显示“我的视图控制器”时,我将清除现有搜索结果:

func清除搜索结果(动画:Bool){
let snapshot=NSDiffableDataSourceSnapshot()
应用(快照、动画差异:动画)
}
执行搜索时,我尝试为找到的每种类型的结果向集合视图添加一个部分:

//执行搜索的代码
var snapshot=NSDiffableDataSourceSnapshot()
//如果我附加了多个节,则在apply()中会引发异常:
//snapshot.AppendSection([ViewController.trackSection,ViewController.albumSection])
snapshot.AppendSection([ViewController.trackSection])
snapshot.appendItems(轨迹,toSection:ViewController.trackSection)
//这也会导致apply()中出现异常:
//snapshot.AppendSection([ViewController.albumSection])
//snapshot.appendItems(相册,toSection:ViewController.albumSection)
dataSource.apply(快照、动画差异: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


有关示例项目,请参见。

对我的部分进行一些简短测试后,当数据源使用动画应用快照时,似乎会引发节索引越界异常。如果在修改任何部分时禁用动画,则不会引发异常。(至少在我的基本测试中没有。)

以下代码似乎对我正常工作:

let outgoingSectionCount = dataSource.numberOfSections(in:collectionView)
let incomingSectionCount = snapshot.sectionIdentifiers.count

let shouldAnimate  = true
let canAnimate     = outgoingSectionCount == incomingSectionCount

dataSource.apply(snapshot, animatingDifferences:(shouldAnimate && canAnimate)
YMMV

跟进

正如您在上面的评论中所回避的那样,Apple DTS建议您在附加部分之后但在附加任何项目之前调用
dataSource.apply(…)
。成功插入节后,您应该能够插入项并再次调用
dataSource.apply(…)

我发现有时需要调用两次
apply(\uquo:animatingDifferences:)
,一次是在调用
appendSection(\uquo)
后调用animation
false
,一次是在调用
appendItems(\uquo:)
后调用

例如:

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)
    }
}
扩展AnimalsViewController{
枚举部分{
主箱
}
private func makeDataSource()->UITableViewDiffableDataSource{
UITableViewDiffableDataSource(tableView:tableView){tableView,indexPath,中的名称
让单元格=表格视图
.dequeueReusableCell(标识符为CellIdentifier.animalCell.rawValue,
for:indexath)
cell.textlab?.text=名称
返回单元
}
}
私有函数更新(){
activityIndicator.stopAnimating()
var snapshot=NSDiffableDataSourceSnapshot()
snapshot.appendSections([.main])
dataSource.apply(快照、动画差异:false)
snapshot.appendItems(viewModel.animalNames)
dataSource.apply(快照、动画差异:true)
}
}

似乎与
NSCollectionViewDiffableDataSource
相关的一些bug已经解决了macOS 11。在macOS 10.15中崩溃的动画中应用快照。*,在大多数情况下在macOS 11中似乎都有效。

我自己也遇到了这个令人烦恼的问题。唯一可靠的修复方法是在应用快照之前使布局无效

if snapshot.sectionIdentifiers.isEmpty {
    collectionView.collectionViewLayout.invalidateLayout()
}

dataSource.apply(snapshot, ...)

你有没有想过?您是使用纯Swift结构/类作为标识符,还是像示例代码中那样使用
NSObject
派生类?在macOS上使用纯Swift实体存在一些混乱,因为
NSCollectionViewDiffableDataSource
仅在10.15.1中引入(没有任何文档或发行说明)。使用基于引用的API对我来说是可行的,但我在10.15.3下使用纯Swift API时也会遇到异常情况。@kennyc我从来没有让事情像我想要的/预期的那样工作。我用的是纯Swift。从我收集的
NSCollectionView
中发现了附加节和移动项的错误。基本上在每次操作(步骤更新)之后调用
apply()
,并且始终至少有一个部分,就可以让事情顺利进行。感谢您的后续关注。我(再次)收到了一份关于DTS的报告,试图更好地理解
NSCollectionView
和可扩散的数据源。我可以使用基于
Reference
的API使其工作,这需要使用
NSObject
派生标识符,但尝试使用Swift类、结构或枚举总是导致抛出索引越界异常,即使我基本上使用WWDC的示例代码。这与Apple DTS建议的类似,但是iOS和macOS上的集合视图完全不同,所以如果iOS有相同的问题,那就太糟糕了。