How to delete some elements from UITableViewController with CoreData?

Viewed 15

So i can add some city from API and when i try to delete some city from UITableViewController then all cities are deleted. Can someone help me please where i made mistake. I gave an example of the code below

//this is my delete func from CoreData
 func deleteCity() {

        let fetchRequest: NSFetchRequest<Cities> = Cities.fetchRequest()

        if let cities = try? context.fetch(fetchRequest) {
            for city in cities {
                context.delete(city)
            }
        }

        do {
            try context.save()
        } catch let error as NSError {
            print(error.localizedDescription)
        }
    }
    //this is how i create cities array 
    func fetch() -> [Weather] {

        let fetchRequest: NSFetchRequest<Cities> = Cities.fetchRequest()
        
        do {
            let cities = try context.fetch(fetchRequest)
            return cities.map({Weather(name: $0.cityName ?? "", temp: $0.cityTemp)})
        } catch  {
            return []
        }
    }

    //and this how i try to delete city from UITableViewController
 
  override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let actionDel = UIContextualAction(style: .destructive, title: "Delete") { _, _, completionHandler in
            self.cityTemps.remove(at: indexPath.row)
            self.coreDataManaer.deleteCity()
            DispatchQueue.main.async {
                tableView.reloadData()
            }
        }
        let actions = UISwipeActionsConfiguration(actions: [actionDel])
        return actions
    }

1 Answers

Your deleteCity() function actually deletes all cities. Here's why:

First your fetch request fetches all cities, since there's no predicate:

let fetchRequest: NSFetchRequest<Cities> = Cities.fetchRequest()

Then your loop goes through the results of the fetch and deletes every city it finds-- which is all of them.

if let cities = try? context.fetch(fetchRequest) {
    for city in cities {
        context.delete(city)
    }
}

It sounds like you want to delete only the city that the person swipes on, which is the city at indexPath in the last function above. You could change your fetch request, but you probably don't need to do that. In your data source methods (for example your tableView(_:cellForRowAt:) function) you already have a list of the cities you're showing, probably in an array. To delete a single city then, you'd do something like

  1. Get the correct city from that array
  2. Delete that city from the managed object context.
Related