ioscore-datanspersistentstoreios-app-group

Update Core Data Stack into applicationWillEnterForeground


I’ve shared the same .sqilte between two apps with App groups.

When I add a recording in App A and open App B (first launch), app B retrieve correctly data.

I would like synchronize data when I add a recording in App A and app B (already launched in backrgound), app B could retrieve data when It comes back into foreground.

This's why when App B comes back into foreground, I update Core Data Sack into applicationWillEnterForeground. Which way is correct ?

let directory = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.sl.sharedData");

        let url = directory?.URLByAppendingPathComponent("sharedData.sqlite")
        let store = self.persistentStoreCoordinator?.persistentStoreForURL(url!)
        var error : NSError?
        if false == self.persistentStoreCoordinator?.removePersistentStore(store!, error: &error)
        {
            println("error = \(error!.localizedDescription)")
            return
        }
        let options = [
            NSMigratePersistentStoresAutomaticallyOption: true,
            NSInferMappingModelAutomaticallyOption: true,
            // Adding the journalling mode recommended by apple
            NSSQLitePragmasOption: ["journal_mode": "DELETE"]
        ]
        var failureReason = "There was an error creating or loading the application's saved data."
        if self.persistentStoreCoordinator?.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error) == nil {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason
            dict[NSUnderlyingErrorKey] = error
            error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(error), \(error!.userInfo)")
            abort()
        }
        _persistentStoreCoordinator = nil
        _managedObjectContext = nil
        let rootViewController = self.window!.rootViewController as ViewController
        rootViewController.context = self.managedObjectContext

Unfortunately, it doesn't work as I want. The retrieved data are dubbed each time, when I enter in applicationWillEnterForeground. Which way is correct ?

// Edit 2014/04/17 : Attempt with Mundi's solution

I have tried with NSManagedObjectContextObjectsDidChangeNotification

   func applicationWillEnterForeground(application: UIApplication) {

        NSNotificationCenter.defaultCenter().addObserver(
            self,
            selector: "mergeContextChangesForNotification:",
            name: NSManagedObjectContextObjectsDidChangeNotification,
            object: managedObjectContext)

        let rootViewController = self.window!.rootViewController as ViewController
        rootViewController.context = managedObjectContext
        }
    }

func mergeContextChangesForNotification(notification : NSNotification){
        let otherContext: NSManagedObjectContext = notification.object as NSManagedObjectContext

        if((otherContext != managedObjectContext) && (otherContext.persistentStoreCoordinator == managedObjectContext.persistentStoreCoordinator)){

            managedObjectContext.performBlockAndWait{ () -> Void in

                self.managedObjectContext.mergeChangesFromContextDidSaveNotification(notification)
            }
        }
    }

mergeContextChangesForNotification has been called but I have never entered in this condition : if otherContext != managedObjectContext) && (otherContext.persistentStoreCoordinator == managedObjectContext.persistentStoreCoordinator


Solution

  • You should not set up your persistent store coordinator again if the app is already active. The standard lazy initialization used in the Xcode template is sufficient and preferable.

    Instead, you might want to listen to the NSManagedObjectContextObjectsDidChangeNotification and update your UI as appropriate.