如何在 iOS 11 上使用拖放移动多个 UITableView 行?

bru*_*lla 5 drag-and-drop uitableview ios

在 iOS 11 上,通过拖放将一个 UITableView 行移动到另一个索引路径非常容易。但是我找不到通过拖放移动多行的方法。我已经实现了所有必需的委托方法,但 UITableView 视图仍然没有为多行放置打开间隙并且tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)从未被调用。

这是我对UITableViewDropDelegateand 的实现UITableViewDragDelegate

func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let itemProvider = NSItemProvider(item: nil, typeIdentifier: nil)
    let dragItem = UIDragItem(itemProvider: itemProvider)

    return [dragItem]
}

func tableView(_ tableView: UITableView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
    let itemProvider = NSItemProvider(item: nil, typeIdentifier: nil)
    let dragItem = UIDragItem(itemProvider: itemProvider)

    return [dragItem]
}

func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool {
    return true
}

func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
    return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}

func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

启用拖放并设置代理。

tableView.dragDelegate = self
tableView.dropDelegate = self
tableView.dragInteractionEnabled = true
Run Code Online (Sandbox Code Playgroud)

小智 0

我可以通过一些技巧让它工作。诀窍是记住行选择,但不实际选择行。这是我在 didSelectRow 委托回调中所做的事情:

        let cell = tableView.cellForRow(at: indexPath)
        tableView.deselectRow(at: indexPath, animated: true)
        guard let imageView = cell?.accessoryView as? UIImageView else { return }
        if isSelected(indexPath: indexPath) {
            imageView.image = UIImage(systemName: "circle")
            removeSelected(indexPath: indexPath)
        } else {
            imageView.image = UIImage(systemName: "checkmark.circle.fill")
            selectedItems.append(indexPath)
        }
Run Code Online (Sandbox Code Playgroud)

selectedItems 是一个具有一些辅助方法的 IndexPaths 全局数组。

现在在 itemsForBeginning 调用中,我有以下代码:

    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    let itemProvider = NSItemProvider()
    
    var dragItems: [UIDragItem] = []
    if isSelected(indexPath: indexPath) == false {
        selectedItems.append(indexPath)
    }
    for item in selectedItems {
        let dragItem = UIDragItem(itemProvider: itemProvider)
        dragItem.localObject = item
        dragItems.append(dragItem)
    }
    return dragItems
}
Run Code Online (Sandbox Code Playgroud)

在 PerformDropWith 中,这是我所拥有的:

func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
    guard let draggedItems = coordinator.session.localDragSession?.items else { return }
    guard let destinationPath = coordinator.destinationIndexPath else { return }

    selectedItems = []
    for draggedItem in draggedItems {
        guard let item = draggedItem.localObject as? IndexPath  else { continue }
        // do whatever you want to do
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都按预期进行。唯一烦人的部分是,拖动操作正确显示计数,但仅对启动拖动的行进行动画处理,而不是对所有行进行动画处理。