Konstantin
Konstantin

Reputation: 307

Update Rows after .Delete in TableView

Good day!

I have a TableViewController with EditingStyle:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {
        machine.formulas.remove(at: indexPath.row)
        machine.saveFormulas()
        tableView.deleteRows(at: [indexPath], with: .fade)
        tableView.reloadData()

    } 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
    }
}

Each cell has a label with row number. If i .reloadData() as in the code above it breaks the .deleteRows() animation. I tried different variations, with beginUpdates() and .reloadRows(), nothing gave the required result. I think there is a simple solution for that, but I can't figure it out.

EDIT:

Edited code so the item is removed from array at first then from tableView.

EXAMPLE:

enter image description here

If you delete row #5, how do you .reloadData() so everything is in order. I mean there won't be 1-2-3-4-6-7-8-9-10. And how do you reload it without breaking .Delete animation?

Upvotes: 2

Views: 5613

Answers (4)

Michael
Michael

Reputation: 809

Try to delete the item from the array, delete the row, then reload the TableView after using a completion handler:

So create this method (Swift 5):

func deleteRow(atIndexPath indexPath: IndexPath, completion: () -> Void) {
    self.dataArray.remove(at: indexPath.row)
    tableView.deleteRows(at: [indexPath], with: .automatic)
    completion()
}

And then call it like this wherever you need it:

func clearDataItem(atIndexPath indexPath: IndexPath) {
    deleteRow(atIndexPath: indexPath) {
        tableView.reloadData()
    }
}

Upvotes: 0

Bhavin Kansagara
Bhavin Kansagara

Reputation: 2916

Simply remove from the dataSource and Delete the row can do, No need to reload it.

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {
    machine.formulas.remove(at: indexPath.row)
    machine.saveFormulas()
    tableView.deleteRows(at: [indexPath], with: .fade)
    self.perform(#selector(reloadTable), with: nil, afterDelay: 2)

    } 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
    }
}

@objc func reloadTable() {
    self.tableView.reloadData()
}

Try and share results.

EDIT:

You should update your cellForRow method to set the value based on indexPath and not from the numbersArray

because, initially numberArray has all 10 values. 1,2,3,4,5,6,7,8,9,10 Now if you remove one row from 4rth row, then that specific value is being removed from the array and keeping 9 items i.e 1,2,3,5,6,7,8,9,10 and will see them in cells. Instead you should update your cellForRow to show indexPath.row + 1 for it.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.textLabel?.text = "\(indexPath.row + 1)"
    return cell
}

Hope it clears.

Upvotes: 0

Mehdi Ijadnazar
Mehdi Ijadnazar

Reputation: 4961

just remove tableView.reloadData() from your code, It is not needed.
Your overridden method should be

override func tableView(_ tableView: UITableView, commit editingStyle: 
    UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {    
        if editingStyle == .delete {
            machine.formulas.remove(at: indexPath.row)
            machine.saveFormulas()
            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
        }
    }

Upvotes: 2

Midhun
Midhun

Reputation: 2187

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

if editingStyle == .delete {
    machine.formulas.remove(at: indexPath.row)
    machine.saveFormulas()
    tableView.deleteRows(at: [indexPath], with: .fade)
    self.perform(#selector(reloadTable), with: nil, afterDelay: 2)

} 

}

@objc func reloadTable() {
      DispatchQueue.main.async { //please do all interface updates in main thread only
      self.tableView.reloadData()

} }

Upvotes: 0

Related Questions