Core Data with WatchKit and iOS App
Asked Answered
X

2

6

This question has already been asked, but has received no answers.

My iOS app and my WatchKit extension share an App Group in which a Core Data store persists. The Core Data model (simplified) is a Person object that has an attribute for Age. Both the app and extension can change the age at will.

If the value for a person changes on the watch, the app does not reflect it unless I close and rerun the app. Same going the opposite direction.

If I try to change the age on the watch to 20, and change the age on the phone to 30, then I get an error having to do with merge conflicts, because I am not using the most up-to-date version of the NSManagedObject on one of the devices (whichever I change the age on last).

How can I make the two work together without any issues?

Xylem answered 2/3, 2015 at 4:28 Comment(2)
Have you tried to subscribe to NSManagedObjectContextObjectsDidChangeNotification?Grammalogue
@Grammalogue I tried doing that, but the notification is only ever called on the device I made the most recent change on. This could be a limitation of the simulator though. I'd like to see if this solution would work, but I can't because there is no watch yet...Xylem
P
3

Since notifications won't be picked up between the different processes, you need to use Darwin notifications instead. You could easily use the openParentApplication:reply: method to send updates from the Watch Extension to the iOS App, but Apple does not have a way to send events from the iOS App to the Watch Extension.

What I would suggest is for you to use MMWormhole (or you own implementation of Darwin notifications) to send a Darwin notification when the Core Data object has been updated. Here is an article detailing how the library works.

If you update a Core Data object in the Watch Extension, then send a Darwin notification (or pass a message) to the iOS App telling the app that it needs to refresh the Core Data object. The same approach can be used going the other direction, from the iOS App to the Watch Extension.

Additionally, if you objects are really simple, then CoreData could be overkill. You could use MMWormhole to simply cache a light-weight dictionary that gets used on both ends. I've been using this approach for a few weeks now and it works flawlessly in both directions.

Perla answered 3/3, 2015 at 3:19 Comment(0)
M
1

This is happening because you are using different managed object context's that can't communicate via notifications. So posting a notification like NSManagedObjectContextObjectsDidChangeNotification won't work because NSNotificationCenter won't post the notification from your iOS app to the extension as they are both different processes running in different memory spaces. I ran into the same thing in my app. You need to refresh the object before using it. Basically, you are doing a manual fault. For performance, you probably want some way of know when to do this and when not to do it. You can refresh the object by passing it to [NSManagedObjectContext refreshObject: mergeChanges:].

Miscible answered 2/3, 2015 at 16:1 Comment(5)
I tried to refresh the object right before making further changes to it, but the app still crashes when I try to save.Xylem
When it crashes are there any error messages in the console?Miscible
Unresolved error Optional(Error Domain=NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)"Xylem
As per #9891529 make sure you are doing all core data operations on the main thread or that you are using the managed data context for the thread you are in.Miscible
I am already calling it on the main thread, so that doesn't seem to be an issue.Xylem

© 2022 - 2024 — McMap. All rights reserved.