Drag and Drop Table View cell in IOS 11 & swift 4

In IOS 11, UITableView added the some specialized API for drag and drop the tableView row from one tableView to other tableView. For Drag-Drop we need to implement delegates, UITableViewDragDelegate and UITableViewDropDelegate. UITableView and UICollectionView both have the drag and drop API (Protocols). For UICollectionView You can follow this tutorial.

These Delegates are completly independent, we can use any one delegate for drag and drop according to requirment. And both for Drag-Drop.

NOTE:- please note that Drag-Drop supported in both iPhone and iPad, On iPad use Drag-Drop between different apps, same app, and same screen, But in iPhone use Drag-Drop only on similar screen.


First create the base project

Create the base project with two tableView on same screen by the use of CollectionViewDataSource and CollectionViewDelegate methods. You can download the base project from here.

For Drag the table view Cell (UICollectionViewDragDelegate)

Now we start the Drag and drop Delegate for move the tableView row from on FirstTableView to SecondTableView. For get the call back of UITableViewDragDelegate we need to set .dragDelegate in viewDidLoad() method.

override func viewDidLoad() {
        self.topTableView.dragDelegate = self

For enabling the drag intraction we need to set the dragInteractionEnabled property of your table view. Enable this property in viewDidLoad method. The default value of this property is true on iPad and false on iPhone.

     self.topTableView.dragInteractionEnabled = true

In UITableViewDragDelegate have only one required method itemsForBeginning for support the drag item.

tableView(_:itemsForBeginning:at:) -> Provide items to begin a drag associated with a given indexPath. If an empty array is returned a drag session will not begin.

  • NSItemProvider
  • UIDragItem

NSItemProvider -> By the use of this class you can create the object of your data or file for conveying data or a file between processes during drag and drop.

UIDragItem -> A representation of an underlying data item being dragged from one location to another.

extension ViewController: UITableViewDragDelegate {
    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        let dragItem = self.dragItem(forPhotoAt: indexPath)
        return [dragItem]
    /// Helper method
    private func dragItem(forPhotoAt indexPath: IndexPath) -> UIDragItem {
        let imageName = self.arrayFirst[indexPath.row]
        let data = arrayFisrtProfileData[indexPath.row]
        let string = data.profileImageName
        let itemProvider = NSItemProvider(object: string as NSItemProviderWriting)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        dragItem.localObject = imageName
        return dragItem
  1. Create one or more NSItemProvider objects. Use the item providers to represent the data for your table’s rows.
  2. Wrap each item provider object in a UIDragItem object.
  3. Consider assigning a value to the localObject property of each drag item. This step is optional but makes it faster to drag and drop content within the same app.
  4. Return the drag items from your method.

tableView(_:itemsForAddingTo:at:point:) -> This methods is used for adding the item to an active drag session. When drag session is active and user want to add more rows that time table calls this methods. we are getting the point where we can touch for adding the item.
(Or we can say that for selecting multiple items we use this method)

tableView(_:dragPreviewParametersForRowAt:) -> This methods is used when we need to drag only specific location of item at the time of drag.

 func tableView(_ tableView: UITableView, dragPreviewParametersForRowAt indexPath: IndexPath) -> UIDragPreviewParameters? {
        return previewParameters(forItemAt:indexPath)
    /// Helper method
    private func previewParameters(forItemAt indexPath:IndexPath) -> UIDragPreviewParameters?     {
        let cell = self.topTableView.cellForRow(at: indexPath) as! TopTableViewCell
        let previewParameters = UIDragPreviewParameters()
        previewParameters.visiblePath = UIBezierPath(rect: cell.imageViewProfile.frame)
        return previewParameters

For Drop the table view Cell (UICollectionViewDropDelegate)

First we set the dropDelegate for getting the call back of UICollectionViewDropDelegate methods. we set this property in viewDidLoad() method.

    self.bottomTableView.dropDelegate = self

Same as dragDelgate, drop delegate also have one required method performDropWith for support the drop item.

tableView(_:performDropWith:) Use this method to integrate the dropped content into your table view. We getting the destinationIndePath and We retrieve the UIDragItem objects associated with the drag operation. By the use of these object we update the tableView Data source and table View itself.
We can insert placeholder rows for any data that you must load asynchronously.(We discuss this property in future blog)

extension ViewController: UITableViewDropDelegate {
    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
        let destinationIndexPath: IndexPath
        if let indexPath = coordinator.destinationIndexPath {
            destinationIndexPath = indexPath
        } else {
            let section = tableView.numberOfSections - 1
            let row = tableView.numberOfRows(inSection: section)
            destinationIndexPath = IndexPath(row: row, section: section)
        coordinator.session.loadObjects(ofClass: NSString.self) { items in
            guard let string = items as? [String] else { return }
            var indexPaths = [IndexPath]()
            for (index, value) in string.enumerated() {
                let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section)
                self.arraySecond.insert(value, at: indexPath.row)
            tableView.insertRows(at: indexPaths, with: .automatic)

Other optional DropDelegate

DropDelegate also have other methods for handle the drop in tableView. But these methods are optional.
tableView(_:canHandle:) -> This methods is used for handle the drop session. Asks your delegate whether it can accept the specified type of data.

 func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool {
        return session.canLoadObjects(ofClass: NSString.self)


DropDelagte have the optional method UITableViewDropProposal for handle the drop in table view. Drop proposal have the property for handle the drop when we lift the finger over the item and drop that item.
DropProposal have the operation enum, that determine how we resolved the drag and drop activity when the user drops a drag item. Means we need to drop that that item or not, and that item is compatible for tableView or not.

cancel This case is used when dont need to transfer the data or should be transferred, that time we cancel the drag.
forbidden although a move or copy operation is typically legitimate in this scenario, the drop activity is not allowed.
copy data represented by the drag items should be copied to the destination view.
move data represented by the drag items should be moved, not copied.

An example methods for UICollectionViewDropProposal

func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
        if session.localDragSession != nil {
            return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        } else {
            return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath)

You can download complete project from here.


Related Post

How to use Flutter most usable Widgets | Flutter t... We need some basic widgets for creating our first flutter app. Widgets describe what their view should look like given their current configuration and...
Introduction to JVM Introduction to JVM JVM stands for Java Virtual Machine. It works as an engine that derives the Java Code. The JVM does not understand Java ty...
Resignation Letter and Relieving Letter Resignation Letter Sample 1 Sender’s Name, Sender’s Address, Mobile Number, MailDate:ToThe Human Resource Department Company Name Company Addre...
Custom View by use of xib in swift Custom View by use of xib in swift We can create the custom and common view by the use of xib in swift 3.1 and XCode 8.3.2 . Custom views are common ...
Switch Case Statement Switch Case Statement The switch statement is a multi-way branch statement. It provides an easy way to dispatch execution to different parts of c...
Navigation Tab Bar in IOS | Swift tutorial Navigation Tab Bar in IOS | Swift tutorial Different Customizing techniques for Navigation bar with storyboard and code 1) Custom NavigationTabBar by ...

Write A Comment