Apple Watch is all the hype right now. With its release next week, app developers are hastily assembling their WatchKit app (myself included). One core concept that is paramount in building a great WatchKit app is the idea of sharing persistent data between the actual iOS app and WatchKit app. Specifically how do I get a shared storage unit that can be shared across both my iOS and WatchKit app?
The model here that I demonstrate is the iOS app can Read and Write to persistent storage. The WatchKit app can only Read to persistent storage. I also will be showing a technique specific to MagicalRecord which is just a higher-level wrapper around CoreData.
As the Apple Watch is ancillary to your iOS app, I am assuming you already have your iOS app setup already integrated with MagicalRecord presumably through CocoaPods.
The higher level overview is as followed:
Step 1
Create Watch App Target
Setup CocoaPods with MagicalRecord for the WatchKit extension
target '(Target Name)' do
pod 'MagicalRecord'
end
In my case, my (Target Name) is ‘WatchkitTutorial WatchKit Extension’
pod install
Step 2
Add a shared App Group container
The purpose of this step is to have entitlements to allow shared authorized access to a container for both the iOS and WatchKit app. This will authorize the use of a shared Database.
At this point, this tells your iOS and WatchKit app that they are allowed to communicate with each other.
Step 3
Update location of the Persistent Data Store to point to the App Group container
Now that both apps have access to the shared container, let’s make sure that MagicalRecord points to this new shared location.
In your iOS app, in your AppDelegate didFinishLaunchingWithOptions, add in this code In your WatchKit app, in your first InterfaceController willActivate, add in this code
NSFileManager *fm = [NSFileManager defaultManager];
NSString *appGroupName = @"group.com.watchkittutorial.watch";
NSURL *groupContainerURL = [fm containerURLForSecurityApplicationGroupIdentifier:appGroupName];
NSString* dbPath = [groupContainerURL path];
dbPath = [dbPath stringByAppendingPathComponent:@"ModelWatchKit.sqlite"];
NSURL* dbURL = [NSURL fileURLWithPath:dbPath];
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:(id)dbURL];
Step 4
Create Framework that wraps all Core Data access code as to keep your code DRY I actually will not go into this. I added this since I saw many blog posts go into depth with this step as their tutorial was WatchKit + Core Data, not WatchKit + MagicalRecord + Core Data. I have found it unnecessary since the idea with this step is that Core Data functionality out of the box is quite low-level so we would want to abstract these low-level tools into one that is higher level while also wrapping our custom data model into something higher-level. With this logic of just using Core Data, we can, therefore, create a Core Data Framework that is specific to our app and can share the same higher-level persistent operations in one easy to use Framework. With MagicalRecord, the low-level things about Core Data have already been wrapped with as MagicalRecord does sit on top of Core Data. In the context of my app, I did not have to abstract MagicalRecord a level up to wrap around my data models therefore I do not need a Framework (your use-case may vary!)
Step 5
With Step 4 explain, you are actually all set! If you’ve done it right, both apps will have access to a common database.
I’m @steventsooo on Twitter. I would love to hear what you think!