0
votes

I want to stop all my background save and update in CoreData when i click my logout button so that i can safely delete all the data related to current user deleted. My code to delete the CoreData objects are

  static func logoutAction(){
    SVProgressHUD.show()
    let deviceToken = kSharedUserDefaults.getDeviceToken()
    self.perform(#selector(deletecoreData), with: self, afterDelay: 3)

    print("Reset All data in userddefaults.")
    kSharedUserDefaults.setDeviceToken(token: deviceToken)
    SVProgressHUD.dismiss()
    kSharedAppDelegate.configureLoginViewController()

}

static func deletecoreData(){
    for str in ["JobStatusTransition","JobImages","CustomField","Attribute","Booking","Job","Notification","Person","Status"]{
        deleteObjEntity(entity: str)
    }
    if let bundle = Bundle.main.bundleIdentifier {
        UserDefaults.standard.removePersistentDomain(forName: bundle)
    }
}
   static func deleteObjEntity(entity:String){
    let moc = CoreDataHelper.sharedInstance.bgManagedObjectContext
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)

    let result = try? moc.fetch(fetchRequest)
    let resultData = result

    for object in resultData! {
        moc.delete(object as! NSManagedObject)
    }

    do {
        try moc.save()
        print("saved!")
    } catch let error as NSError  {
        print("Could not save \(error), \(error.userInfo)")
    } catch {

    }
}

currently it is crashing when there is any background save into db these are my errors

CoreData: error: Mutating a managed object 0x1951ade0 (0x19558580) after it has been removed from its context. 2017-06-06 16:37:32.448 WheelTech[2242:256244] CoreData: error: Mutating a managed object 0x1951ade0 (0x19558580) after it has been removed from its context. 2017-06-06 16:37:32.465 WheelTech[2242:256244] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'booking' between objects in different contexts (source = (entity: Job; id: 0x1951ade0 ; * First throw call stack: (0x24eb391b 0x2464ee17 0x269a2475 0x269a0fb1 0xa7c00 0xa8338 0x11bb38 0x26a0d4b7 0x1f72493 0x1f6ade1 0x1f73ecf 0x1f737cf 0x24be5b29 0x24be5718) libc++abi.dylib: terminating with uncaught exception of type NSException

1
What does the crash log say? how are you creating bgManagedObjectContext are you accessing it from the correct thread?Jon Rose

1 Answers

0
votes

"attempt to establish a relationship between objects in different contexts" is a serious problem which points to deep problems in how you are dealing with threading and core-data in your app. I would recommend watching this: https://vimeo.com/89370886 which explains how a properly setup core data stack should look. The basic idea is that you want ALL you changes to core-data to be done in a serial queue. Each operation creates it own context, fetches the objects it needs, modifies them, saves the context and then discards it. You NEVER pass managedObjects into or out of the operation.

This setup is from before NSPersistentContainer, but NSPersistentContainer is basically the same setup under the hood so the lecture still has a huge amount of value. All write that are done using performBackgroundTask are in a private serial queue. To use it:

  • NEVER write to the viewContext
  • only write using performBackgroundTask.
  • Do not use any managedObjects or context from performBackgroundTask
  • Do not use any viewContext managedObject inside of performBackgroundTask - pass the objectID and refetch it inside the context.
  • don't use newBackgroundContext - it is useful only in very rare situations that you are unlikely to encounter.

Once you have a property setup stack your problems will go aways. You enqueue an operation to delete all objects. All future operation will fail on their fetches and do nothing.