Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect animation when reordering tableview with new iOS 11 APIs

I'm using the new drag and drop APIs on iOS 11 to reorder cells in a tableview inside the same app.

Here's my implementation for UITableViewDragDelegate and UITableViewDropDelegate:

extension TasksViewController: UITableViewDragDelegate {
    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        let string = tasks[indexPath.row]
        guard let data = string.data(using: .utf8) else { return [] }
        let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: kUTTypePlainText as String)
        let item = UIDragItem(itemProvider: itemProvider)
        item.localObject = string

        return [item]
    }
}

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

    func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {

        if session.localDragSession != nil { // Drag originated from the same app.
            return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        }

        return UITableViewDropProposal(operation: .cancel, intent: .unspecified)
    }

    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
        guard let destinationIndexPath = coordinator.destinationIndexPath,
            let dragItem = coordinator.items.first?.dragItem,
            let task = dragItem.localObject as? String,
            let sourceIndexPath = coordinator.items.first?.sourceIndexPath else {
                return
        }

        tableView.performBatchUpdates({
            self.tasks.remove(at: sourceIndexPath.row)
            self.tasks.insert(task, at: destinationIndexPath.row)

            tableView.deleteRows(at: [sourceIndexPath], with: .none)
            tableView.insertRows(at: [destinationIndexPath], with: .none)
        })

        coordinator.drop(dragItem, toRowAt: destinationIndexPath)
    }
}

This works fine, but has a weird glitch. When the last cell is being dragged, as soon as it's dropped, it appears at the bottom of the tableview for a split second then disappears.

enter image description here

What am I missing here?

like image 995
Hesham Avatar asked Oct 06 '17 12:10

Hesham


1 Answers

Just change table deletion animation to .automatic, like so:

tableView.deleteRows(at: [sourceIndexPath], with: .automatic)

After that there won't be that weird animation.

like image 195
Dan Karbayev Avatar answered Oct 15 '22 21:10

Dan Karbayev