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

如何在UITableViewDiffableDataSource下搭配DropCoordinator实现下落动画

UITableView拖拽功能搭配Diffable Data Source的下落动画异常问题

在iOS 11中,苹果为UITableView引入了原生拖拽功能,为常见的拖拽交互提供了特定动画。只要你返回了正确的UIDropProposal,就能轻松实现UITableView内重排序下落的动画效果,示例代码如下:

func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
  // usual code to handle drop, get dragItem, etc
  // ....

  // update the dataModel to reflect the change
  self?.model.updateDataSourceForDrag(from: sourceIndexPath, to: destinationIndexPath)

 // perform the drop animation with the drop coordinator
 coordinator.drop(dragItem, toRowAt: destinationIndexPath)
}

这一实现可以流畅地将被拖拽的元素动画插入到UITableView中hover时对应的间隙位置。

到了iOS 13+版本,开发者开始普遍使用diffable data source,但苹果官方文档中没有任何关于dropCoordinator搭配snapshot使用的参考资料,官方指南、教程、WWDC视频都没有更新说明如何组合使用这两套API。

在拖拽操作过程中,drop controller可以正确「管理」UITableView,移动各个cell留出间隙展示拖拽cell的下落位置,但调用coordinator.drop(dragItem, toRowAt: destinationIndexPath)时不会触发实际的下落动画。

目前使用的临时解决方案是手动更新并应用snapshot:

DispatchQueue.main.async {
  var snapshot = self?.dataSource.snapshot()
  if destinationIndexPath.row > sourceIndexPath.row {
     snapshot?.moveItem((self?.dataSource.itemIdentifier(for: sourceIndexPath))!, afterItem: (self?.dataSource.itemIdentifier(for: destinationIndexPath))!)
  } else {
     snapshot?.moveItem((self?.dataSource.itemIdentifier(for: sourceIndexPath))!, beforeItem: (self?.dataSource.itemIdentifier(for: destinationIndexPath))!)
  }
  self?.dataSource.apply(snapshot!, animatingDifferences: false)
}

该方案有一定效果,但无法和drop controller的动画打通。拖拽过程中可以看到预留下落间隙的动画,但一旦松手释放,cell会从原始indexPath的位置开始动画移动,而非从拖拽元素的当前位置开始移动,效果非常生硬。

既然dropCoordinator可以调整UITableView实现拖拽过程的动画,按理说也应该可以实现下落动画,但目前找不到对应的实现方式。

如果没有更合理的解决方案,只能将代码回滚到旧版的UITableViewDataSource方法实现。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:36:03