S'pht'Kr
S'pht'Kr

Reputation: 2839

Correct way to share data between app and Today widget when using Core Data + iCloud sync

I have an app with a Today widget extension. I need the app, widget, and other instances of the app and widget on other devices to all share data, so I'm using iCloud Core Data integration. At first, I had the app and widget (within a single device) sharing the same Core Data store (sqlite) in a shared container directory. Now I've enabled iCloud syncing, and that's working between devices, but now I'm getting inconsistent data shown between the app and the widget on the same device (?!?). The problem could be with my widget GUI update cycle or Notification Center subscriptions, which I'm still troubleshooting, but while I do that:

What is the "right" solution for sharing data from Core Data between an app and a widget (or two apps I suppose) on the same device when you're using Core Data + iCloud? Should they share a single physical store, or should they each have their own store? Are there gotchas to either if both approaches are valid?

Upvotes: 3

Views: 1346

Answers (1)

Drew McCormack
Drew McCormack

Reputation: 3592

The first question you should consider is whether you really need to share the whole Core Data store with your extension. If it is possible just to share a little data, perhaps via a plist, it will make things quite a bit simpler.

Assuming this is not an option, and you really do need the whole store, you have two options:

  1. Share a single store in the shared container
  2. Adopt a Core Data sync solution, and have separate stores for your main app and extension.

It is possible to share a single store between two separate processes, but there are some gotchas. If one process saves, any NSManagedObjectContext in the second process will not register the changes, which will mean the data will not update in the UI, and could also lead to a failed save later.

To get around this, you would have to find a way to pass the object ids of the changed objects from one process to the other, so that the receiving process can refresh objects and re-fetch the latest data.

The second option would involve two separate stores, and a means of transferring changes. If you go with iCloud + Core Data, iCloud is the transfer mechanism, which is a bit overkill given that your processes are both on the same device.

I believe Apple have even warned against using this solution on iOS, because if an iOS app goes to the background, it is possible it will be stopped while a file coordinator has a lock on a file, and that can cause deadlocks in the other process.

iCloud + Core Data is not the only sync solution. A better solution in this case may be the Ensembles framework, which I develop. The reason I say that is that it has the option to sync via local files, rather than requiring a cloud service. You could setup separate stores for your extension and main app, and have Ensembles use the shared container for transferring change sets. No cloud involvement, and no file coordination issues.

Upvotes: 3

Related Questions