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
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.