0

I have a dictionary that I have made called places and I made each cell in the tableViewController show each parts of the dictionary. I know the function to delete the rows in the controller, but when I run the app and do the action of deleting nothing happens.

// This is my entire TableViewController. I have another ViewController that appends the dictionary.
var places = [Dictionary<String,String>()]

var activePlace = -1

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        if UserDefaults.standard.object(forKey: "places") != nil { //checks if the list is not empty

            places = UserDefaults.standard.object(forKey: "places") as! [Dictionary<String, String>]
        }


        if places.count == 1 {

            places.remove(at: 0)

            places.append(["name":"Ex. Eiffel Tower", "lat": "48.858324", "lon": "2.294764"])

        }

    }

    // MARK: - Table view data source

    override func tableView(_ tableView: UITableView, canEditRowAt 
    indexPath: IndexPath) -> Bool {
        return true
    }

    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 places.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        DispatchQueue.main.async {

            self.tableView.reloadData()

        }

        cell.textLabel?.text = places[indexPath.row]["name"]

        return cell
    }

    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {

        activePlace = indexPath.row

        return indexPath

    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "newPlace" {

            activePlace = -1

        }

    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == .delete {

            tableView.deleteRows(at: [indexPath], with: .bottom)

            places.remove(at: indexPath.row)

            UserDefaults.standard.setValue(places, forKey: "places")

        }

    }

I am expecting that when I make the action of swiping to the left that it would delete the row and the contents of the cell from the tableView. Then it would also delete from the dictionary.

4 Answers4

1

Solved:

DispatchQueue.main.async was creating an endless loop of constantly reloading the data. By removing that the two functions of editing were allowed to run. I was able to perform the deleting action.

0

It's very complicate to delete table view cell sometimes. Your code is correct but you just need to remove a line. Instead of calling tableview.deleteRows you just delete the item of your dictionary and reload the table view. Enable the table rows to editable using canEditRowAt function....

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {

        places.remove(at: indexPath.row)

        UserDefaults.standard.setValue(places, forKey: "places")

        tableView.reloadData()
    }

}
Abhishek
  • 329
  • 3
  • 12
  • That did not work for me, and the problems seems to be that it refuses to do that part of my code. The function does not run and therefore I cannot do the action of swiping to the left. – Ishaan Sathaye Jul 16 '19 at 05:27
  • Wait did you add - func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true } which enables the table rows to editable. – Abhishek Jul 16 '19 at 05:38
  • Yes I did and it still does not allow me to edit the row and delete it. I have update my code above to show my entire TableViewController. – Ishaan Sathaye Jul 16 '19 at 05:52
0

Move deleteRows(at:with:) after remove(at:) in tableView(_: commit: forRowAt:) method, i.e.

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        places.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .bottom) //here...
        UserDefaults.standard.setValue(places, forKey: "places")
    }
}
PGDev
  • 23,751
  • 6
  • 34
  • 88
0

The main issue is the wrong declaration of the data source array. The pair of parentheses must be behind the brackets

var places = [Dictionary<String,String>]()

In the method tableView(_:commit:forRowAt:the order is wrong. First remove the row from the data source array then delete the row.

Two Don'ts

  • Do not use setValue:forKey with UserDefaults to save a single value.
  • Do not declare the data source array outside of the class.

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {
        places.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .bottom)
        UserDefaults.standard.set(places, forKey: "places")

    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361