Search code examples
uitableviewcore-dataswift3nsmanagedobjectnsmanagedobjectcontext

Cannot convert value of type String to expected argument type NSManagedObject


I'm working on a Core Data project and I got a complier error for deleting item from a TableViewController:

Cannot convert value of type String to expected argument type NSManagedObject

Here's the code:

var listArr:[String] = []

override func viewDidLoad() {
    super.viewDidLoad()
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName:"Entity")
    request.returnsObjectsAsFaults = false

    do {
        let results = try context.fetch(request)

        if results.count > 0 {
            for result in results as! [NSManagedObject] {
                if let listName = result.value(forKey: "listName") {
                    listArr.append(listName as! String)
                }
            }
        }
    } catch {
        // Handle error
        print(error)
    }
}

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

    // Configure the cell...

    cell.textLabel?.text = listArr[indexPath.row]

    return cell
}

// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // Delete the row from the data source
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext

        context.delete(listArr[indexPath.row]) //The error is here
        listArr.remove(at: indexPath.row)

    }

    self.tableView.reloadData()
}

What do I need to change?


Solution

  • The delete() method that you're calling takes an NSManagedObject as its sole argument. You're passing in an element from your listArr array, which is an array of strings.

    It seems obvious to say it, but if you want to delete a managed object, you need to tell Core Data which one to delete. It doesn't know what to do with a string.

    I'm guessing (since you didn't say) that your listArr is made up of strings which are stored in Core Data as a property of an entity. You're fetching data somewhere and saving only the strings. That's fine as long as your data store is read-only, at least in this part of the app. You can display the strings but you can't go back and update Core Data, because you don't have the necessary information.

    If that's true, what you should do is use an array of managed objects instead of an array of strings. When you need the string value, get it from one of the managed objects. When you need to delete an entry, delete that managed object.