You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 16中UICollectionView调用beginInteractiveMovementForItem崩溃求替代方案

iOS 16 下 UICollectionView 拖拽崩溃的替代方案及临时修复

问题复现

调用collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)时触发崩溃,报错信息:

attempt to insert nil object from objects[0]' terminating with uncaught exception of type NSException

临时修复与替代方案

方案1:前置校验+iOS16专属拖拽API替代

在调用方法前先校验目标Cell的有效性,同时针对iOS16改用系统现代拖拽API发起交互:

if #available(iOS 16.0, *) {
    guard let targetCell = collectionView.cellForItem(at: selectedIndexPath) else {
        return
    }
    let dragItems = collectionView.dragItems(for: selectedIndexPath)
    collectionView.beginInteractiveDrag(with: dragItems, at: targetCell.center, in: collectionView)
} else {
    collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
}

方案2:排查数据源与布局合法性

  • 确保collectionView(_:canMoveItemAt:)方法返回true,且拖拽过程中数据源不会返回nil数据
  • 检查自定义UICollectionViewLayout的配置,iOS16对布局属性的合法性校验更严格,避免存在无效布局参数

方案3:重构为现代拖拽排序流程

完全基于UICollectionViewDragDelegate和UICollectionViewDropDelegate实现拖拽排序,这是Apple推荐的兼容性更好的方案:

  1. 实现拖拽数据源方法:
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let dataItem = yourDataSource[indexPath.item]
    let itemProvider = NSItemProvider(object: dataItem.uniqueIdentifier as NSString)
    let dragItem = UIDragItem(itemProvider: itemProvider)
    dragItem.localObject = dataItem
    return [dragItem]
}
  1. 实现拖拽接收与排序逻辑:
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
    guard let destIndexPath = coordinator.destinationIndexPath else { return }
    guard coordinator.proposal.operation == .move,
          let sourceItem = coordinator.items.first?.dragItem.localObject as? YourDataType,
          let sourceIndexPath = collectionView.indexPath(forItem: sourceItem) else {
        return
    }
    
    // 更新数据源
    yourDataSource.remove(at: sourceIndexPath.item)
    yourDataSource.insert(sourceItem, at: destIndexPath.item)
    
    // 批量更新UI
    collectionView.performBatchUpdates({
        collectionView.moveItem(at: sourceIndexPath, to: destIndexPath)
    })
}
  1. 开启拖拽交互:
collectionView.dragDelegate = self
collectionView.dropDelegate = self
collectionView.dragInteractionEnabled = true

注意事项

  • iOS16中beginInteractiveMovementForItem的崩溃属于系统API已知问题,后续版本可能修复,建议关注系统更新
  • 使用现代拖拽API时,需确保数据源与UI更新逻辑严格同步,避免数据不一致问题

内容的提问来源于stack exchange,提问作者Mousa AminSharifi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 08:50:27