'UITableView drag and drop a cell onto another cell?

I have a UITableView with a Drag and Drop delegate set up. I am able to drag cells between other cells in the UITableView but it does not seem like there is a delegate method for what happens if I drag a cell on top of another cell, in which case I want to combine the two cells (kind of like dragging around apps in iOS). I couldn't seem to find a delegate method that is called when a cell is placed on top of another cell. What's the best way to do detect when a cell has been 'dropped' ontop of another cell? Thanks



Solution 1:[1]

EDIT: I don't know why the undervote, but I have this code working in an app merging cells one in other. I was going to upload a video to show what is doing, but now I will not hurry up, sorry.

there is no delegate method for it, I did it in an application with some work around. I did it like this. Create a UITableViewController with the basic setup in Swift:

import UIKit

class TableViewController: UITableViewController {
    
    var fruitsArray = ["Apple", "Banana", "Mango", "Guava", "PineApple", "Watermelon", "Grapes", "GroundNut", "Muskmelon", "Orange", "Cherry"]

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem
        
        // Setup tableview
        tableView.isEditing = true
        
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return fruitsArray.count
    }

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        // Configure the cell...
        cell.textLabel?.text = fruitsArray[indexPath.row]

        return cell
    }

    
    // Override to support conditional editing of the table view.
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }
    

    
    // Override to support editing the table view.
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            // Delete the row from the data source
            tableView.deleteRows(at: [indexPath], with: .fade)
        } else if editingStyle == .insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }

    
    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

        if fromIndexPath.row != to.row {
            let sourceString = fruitsArray[fromIndexPath.row];
            let destinationString = fruitsArray[to.row];
            let mergeString = String("\(destinationString), \(sourceString)")

            fruitsArray[to.row] = mergeString //replaceObjectAtIndex:destinationIndexPath.row withObject:destinationString];
            fruitsArray.remove(at: fromIndexPath.row)

            tableView.reloadData()
        }
    }

    
    // Override to support conditional rearranging of the table view.
    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the item to be re-orderable.
        return true
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

With this code you will be able to merge the content of the cells if the draped cell is dropped over other cell. The problem is how to difference between drag & drop a cell, or merge two cells. You will need to add some logic to this or make the user select what to do with a selector, I mean, before edit the cell the user can choose to move or merge a cell, so you will know what to do.

Other option is add custom drag button, or add long press on the cell, etc... to determine if you are dragging or merging.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1