Swift UITableView拖拽排序:使用拖拽代理是否真的如此简单?
嘿,你的感觉完全没错!用UITableViewDragDelegate和UITableViewDropDelegate实现行拖拽移动,确实比传统的编辑模式要简洁很多,核心操作就是你说的那几步,但还是有几个容易忽略的细节要点,得提一下避免踩坑:
核心操作确实足够简单,但这些细节要留意
必须实现的两个核心方法
你没看错,只要搞定这两个方法就能跑通基础的拖拽逻辑:tableView(_:itemsForBeginning:at:):负责把要拖拽的行数据包装成UIDragItem返回,这是拖拽的起点tableView(_:performDropWith:):处理拖拽结束后的逻辑,这一步是核心中的核心,必须同步更新你的数据源
数据源一致性是重中之重
很多人刚开始用的时候会犯这个错:只更新了tableView的UI,忘了同步修改数据源数组。比如在performDropWith里,你需要先拿到拖拽的目标索引,然后在数据源里移除原位置的元素、插入到目标位置,最后调用tableView.moveRow(at:to:)来更新UI,这样拖拽结束后数据和显示才不会脱节。可选的优化让体验更丝滑
如果想要更定制化的拖拽体验,还可以实现这些可选方法:tableView(_:dragPreviewParametersForRowAt:):自定义拖拽时的预览视图,默认是cell的快照,你可以改成更精致的样式tableView(_:dropSessionDidUpdate:withDestinationIndexPath:):控制拖拽过程中的视觉反馈,比如限制某些位置不能放下,或者调整目标索引的计算逻辑
系统版本兼容性
别忘了,UITableView的Drag&Drop是iOS 11及以上才支持的。如果你的App需要兼容iOS 10或更低版本,得保留传统的setEditing(true, animated: true)作为降级方案。
举个极简的代码示例
// 设置代理和属性(在viewDidLoad里) tableView.dragDelegate = self tableView.dropDelegate = self tableView.dragInteractionEnabled = true // 实现DragDelegate方法 func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { let dataItem = yourDataSourceArray[indexPath.row] // 这里假设你的数据类型遵循NSItemProviderWriting协议 let itemProvider = NSItemProvider(object: dataItem as NSItemProviderWriting) let dragItem = UIDragItem(itemProvider: itemProvider) return [dragItem] } // 实现DropDelegate方法 func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { guard let destinationIndexPath = coordinator.destinationIndexPath else { return } guard let draggedItem = coordinator.items.first else { return } // 加载拖拽的数据 draggedItem.dragItem.itemProvider.loadObject(ofClass: YourDataType.self) { [weak self] (object, error) in guard let self = self, let data = object as? YourDataType else { return } DispatchQueue.main.async { // 找到数据源中的原位置 guard let sourceIndexPath = draggedItem.sourceIndexPath else { return } // 更新数据源 self.yourDataSourceArray.remove(at: sourceIndexPath.row) self.yourDataSourceArray.insert(data, at: destinationIndexPath.row) // 更新tableView UI tableView.moveRow(at: sourceIndexPath, to: destinationIndexPath) coordinator.drop(draggedItem.dragItem, toRowAt: destinationIndexPath) } } }
总的来说,基础的行拖拽确实只要你说的那几步就能实现,但上面这些细节能让你的拖拽功能更稳定、体验更好。
内容的提问来源于stack exchange,提问作者big
相关产品推荐
相关产品推荐

