iosuitableviewuikit

How can I use Drag and Drop to reorder a UITableView?


I know that drag and drop can be used to transfer data throughout and between apps. I'm not interested in that. All I want is to use drag and drop functionality to reorder a table view without transferring data. How do I do that?


Solution

  • If you are performing a drag on a single item locally, you can use tableView(_:moveRowAt:to:). In order to do this, you need to implement UITableViewDragDelegate.

    Setup

    Start by setting your delegates. Setting dragInteractionEnabled is required for iPhones.

    func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self
        tableView.dragDelegate = self
        tableView.dragInteractionEnabled = true
    }
    

    UITableViewDragDelegate

    Notice that the array is returning a single item. If you return more than one item, then the UITableViewDropDelegate methods will be used instead of tableView(_:moveRowAt:to:). You must set a local object.

    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        let dragItem = UIDragItem(itemProvider: NSItemProvider())
        dragItem.localObject = data[indexPath.row]
        return [ dragItem ]
    }
    

    Moving

    This is where the moving happens and is actually a part of UITableViewDelegate.

    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        // Update the model
        let mover = data.remove(at: sourceIndexPath.row)
        data.insert(mover, at: destinationIndexPath.row)
    }
    

    You can also use tableView(_:canMoveRow:at:) and tableView(_:targetIndexPathForMoveFromRowAt: toProposedIndexPath:) if needed.

    You can read more here...