hgwhittle
hgwhittle

Reputation: 9426

NSManagedObject changes not reflected in WatchKit Extension

I'm building an Apple Watch app with a shared Core Data context between the iPhone target and the Watch's target via App Group. WatchCoreDataProxy below is an custom framework that handles Core Data functions, referring to the App Group as a bridge between the two targets. I update the context in the iPhone app and save, then post a Darwin notification to the Watch which fetches the updated NSManagedObjects from the same context. Most everything is working well except for one quirk:

The NSManagedObject I'm fetching in the Watch (let's call it Parent) contains a one-to-many relationship with another NSManagedObject (let's call it Child). I'm fetching Parent from within the Watch target with the assumption that it's properties have been saved to Core Data and reflect the most recent values.

The properties of Parent always reflect the updated values when fetched from the Watch. However the Child relationship object does not. What's really weird is that the changes to Child persist on the iPhone app side of things, but not in the Watch. My code to fetch the object from the Watch looks like this:

let entityDesc = NSEntityDescription.entityForName("Parent", inManagedObjectContext: WatchCoreDataProxy.sharedInstance.managedObjectContext!)
let request: NSFetchRequest = NSFetchRequest()
request.entity = entityDesc

let predicate = NSPredicate(format: "loadedOnWatch == 1")
request.predicate = predicate

var error: NSError?
let array = WatchCoreDataProxy.sharedInstance.managedObjectContext!.executeFetchRequest(request, error: &error)! as NSArray

let parent: Parent = array[0] as! Parent
self.parentID = parent.objectID
self.parentTitleLabel.setText(parent.name)   //reflects changes successfully

self.childArray = parent.children.sortedArrayUsingDescriptors([NSSortDescriptor(key: "position", ascending: true)]) as NSArray
let firstChild = self.intervalArray.objectAtIndex(0) as! Child

let title = firstChild.title
self.childTitleLabel.setText(title)    //does not reflect changes

I've tried Core Data's refreshObject:mergeChanges: method with no luck. Why does the Watch target not reflect the changes made to Child in the same managed object context?

UPDATE

I found out by re-writing the above code that fetching the NSManagedObjects separately through two different NSFetchRequests, and then refreshing the objects yields the correct values. Here's the updated code:

// Parent fetch
let parentEntityDesc = NSEntityDescription.entityForName("Parent", inManagedObjectContext: WatchCoreDataProxy.sharedInstance.managedObjectContext!)
let parentRequest: NSFetchRequest = NSFetchRequest()
parentRequest.entity = parentEntityDesc

let parentPredicate = NSPredicate(format: "loadedOnWatch == 1")
parentRequest.predicate = parentPredicate

var parentError: NSError?
let array = WatchCoreDataProxy.sharedInstance.managedObjectContext!.executeFetchRequest(parentRequest, error: &parentError)! as NSArray

let parent: Parent = array[0] as! Parent
self.parentTitleLabel.setText(parent.name)

// Child fetch
let childEntityDesc = NSEntityDescription.entityForName("Child", inManagedObjectContext: WatchCoreDataProxy.sharedInstance.managedObjectContext!)
let childRequest: NSFetchRequest = NSFetchRequest()
childRequest.entity = childEntityDesc

let childPredicate = NSPredicate(format: "parent = %@", parent)
childRequest.predicate = childPredicate

let sort = NSSortDescriptor(key: "position", ascending: true)
childRequest.sortDescriptors = [sort]

var error: NSError?
self.childArray = WatchCoreDataProxy.sharedInstance.managedObjectContext!.executeFetchRequest(childRequest, error: &error)! as NSArray
let firstChild = self.childArray[0] as! Child
WatchCoreDataProxy.sharedInstance.managedObjectContext?.refreshObject(firstChild, mergeChanges: true)

let childTitle = firstChild.title
self.childTitleLabel.setText(childTitle)

So why would fetching the NSManagedObjects this way yield the correct values as opposed to relying on the Parent's relationship?

Upvotes: 0

Views: 243

Answers (1)

Pavel Smejkal
Pavel Smejkal

Reputation: 3599

It depends on how your NSManagedContext's are structured. It's not enough to save changes to "some" NSManagedObject context in your iPhone app, because in the WatchKit Extension, there is actually different context (it's completely different app in different app container).

So you have to update the changes into Persistence Coordinator which actually saves them into a file in the app group container or into iCloud.

Upvotes: 3

Related Questions