Swift 4下NSCollectionView分区拖放功能失效求助
解决NSCollectionView添加分区后拖放重排序失效的断言问题
嘿,我之前在做NSCollectionView分区拖放的时候也踩过这个坑,给你拆解下问题根源和解决办法:
首先先把你遇到的错误信息贴出来,方便对照:
2018-05-04 16:06:26.310605-0700 Sections[95751:18347288] *** Assertion failure in -[NSCollectionView itemAtIndex:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1561.40.112/Binding.subproj/NSCollectionView.m:2284
问题根源
你原来的拖放代码是基于无分区的NSCollectionView写的,用的是全局整数索引来获取item(比如itemAtIndex:方法)。但当你添加分区后,NSCollectionView的索引体系变成了NSIndexPath(包含section和item两个维度),此时再调用itemAtIndex:就会因为索引不匹配触发断言——这个方法在分区模式下根本不适用,它无法理解全局索引对应的分区位置。
具体解决步骤
- 替换所有
itemAtIndex:的调用,改用item(at: IndexPath)方法。比如原来的let item = collectionView.itemAtIndex(globalIndex),要先构建正确的IndexPath(指定section和item),再获取item:let targetIndexPath = IndexPath(item: targetItemIndex, section: targetSectionIndex) guard let item = collectionView.item(at: targetIndexPath) as? YourCollectionViewItem else { return } - 更新拖放相关的数据源代理方法。NSCollectionView的拖放代理方法在分区模式下会使用
IndexPath而非全局索引,比如:- 原来的
collectionView:pasteboardWriterForItemAtIndex:要改成collectionView:pasteboardWriterForItemAt:(参数是IndexPath) - 处理放置的
collectionView:acceptDrop:indexPath:dropOperation:也要基于传入的IndexPath来操作数据和更新UI
- 原来的
- 确保分区相关的数据源方法正确实现:
numberOfSections(in:)返回你实际的分区数量collectionView:numberOfItemsInSection:返回对应分区的item数量
这两个方法是collectionView正确管理索引的基础,返回错误的数值也会导致索引越界触发断言。
- 调整数据结构适配分区。如果之前用的是单个数据源数组,现在要改成数组的数组(每个子数组对应一个分区),或者给模型对象添加分区标识,让数据源能准确区分不同分区的内容。
额外提醒
拖放过程中还要注意:当计算目标放置位置时,要确保从粘贴板获取的数据能正确映射到目标分区的IndexPath,避免出现超出分区item数量的索引,这也是触发断言的常见场景。
内容的提问来源于stack exchange,提问作者Bob N.
相关产品推荐
相关产品推荐

