CoreData: error: Mutating a managed object after it has been removed from it's context

Hello,

I'm learning CoreData but my Tutorial is about one year old so not everything is up to date and I don't understand where the problem is. My Project includes an TableViewController with an bar button item. Here is the code

CoreDataResource.swift:

import UIKit
import CoreData

class CoreDataResource {
//    /Document
    var documentDir : URL {
        let allUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return allUrls[0]
    }
   
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
   
    private var managedObjectModel: NSManagedObjectModel {
        guard let url = Bundle.main.url(forResource: "Listen", withExtension: "momd") else {
            fatalError("fix me: not found?")
        }
       
        guard let model = NSManagedObjectModel(contentsOf: url) else {
            fatalError("error in the model?")
        }
        return model
    }
   
    private var storeCoordinator: NSPersistentStoreCoordinator {
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
       
        let url = self.documentDir.appendingPathComponent("Listen.sqlite")
       
        do {
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
        } catch {
            print(error)
        }
        return coordinator
    }
   
    var managedContext: NSManagedObjectContext {
        let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
       
        context.persistentStoreCoordinator = self.storeCoordinator
       
        return context
       
    }
   
    func saveContext() {
        if managedContext.hasChanges {
            do {
                try managedContext.save()
            } catch {
                print(error)
            }
        }
    }
   
    func loadLists() -> [Liste] {
        let request: NSFetchRequest = Liste.fetchRequest()
       
        var listen = [Liste]()
       
        do{
            listen = try managedContext.fetch(request)
        } catch {
            print(error)
        }
       
        return listen
    }
   
    func newList(_ name: String) {
        let newList = NSEntityDescription.insertNewObject(forEntityName: "Liste", into: managedContext) as! Liste
       
        newList.name = name
        saveContext()
    }
}

ListTableViewController.swift:

import UIKit

class ListTableViewController: UITableViewController {
   
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
   
   
    var listen = [Liste]()

    override func viewDidLoad() {
        super.viewDidLoad()
       
        reloadList()


    }
    private func reloadList() {
        listen = appDelegate.coreDataResource.loadLists()
    }
   
    @IBAction func addDummyData(_ sender: Any) {
       
        appDelegate.coreDataResource.newList("Test entry")
       
        appDelegate.coreDataResource.saveContext()
       
        reloadList()
       
    }
   
    // MARK: - Table view data source
   
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       
        let cell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath)
       
        let liste = listen[indexPath.row]
        cell.textLabel?.text = liste.name
        return cell
    }

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

}



If I press in Simulator on the addDummyData button the following error occurs:

CoreData: error: Mutating a managed object 0x6000026b25c0 <x-coredata:///Liste/t8A4529E8-BD3B-4157-B3AF-E8B011B6C46E2> (0x6000005b6300) after it has been removed from its context.


I can't find the mistake. Please help me it's frustrating 😀

Replies

What tutorial are you following? Keep in mind that responses with full links in them end up in moderation so skip the introductory http part of the tutorial URL.


I don't see the problem in your code. I recommend setting a breakpoint on the first line of the addDummyData() function and the first lines of the newList and loadLists() functions. When you reach a breakpoint, step through the code line by line, and you will have an easier time finding the problem.


According to the following Stack Overflow question:


stackoverflow.com/questions/38159502/coredata-error-mutating-a-managed-object-after-it-has-been-removed-from-its-co


The t at the start of the string t8A4529E8-BD3B-4157-B3AF-E8B011B6C46E2 means the Liste object is new and has not been saved. That information might help you.

In


func newList(_ name: String)


you are already calling saveContext(), so there is no need to call


appDelegate.coreDataResource.saveContext()


inside the


  @IBAction func addDummyData(_ sender: Any)

thank you. It's true I don't have to call saveContext() again but this didn't fix the bug

your var definition recreates the managed object context each time it is called. try redefining it as follows to only create it the first time it is called:

lazy var storeCoordinator: NSPersistentStoreCoordinator = {
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
   
    let url = self.documentDir.appendingPathComponent("Listen.sqlite")
   
    do {
        try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
    } catch {
        print(error)
    }
    return coordinator
}()