How to incorporate iCloud into an existing Core Data app

WARNING (Jan 26, 2017) . Starting with iOS 10 iCloud Core Data was deprecated. That makes this post pretty useless.

Suppose, you have an app that uses Core Data but doesn’t include iCloud sync, and that app is already in the App Store. Now you want to add iCloud sync to this app. How would you go about it?

If you just add an option NSPersistentStoreUbiquitousContentNameKey to your persistent store, the data that was in that store previously will be lost. You don’t want that.

The way you go about it is you create a new persistent store with option NSPersistentStoreUbiquitousContentNameKey and migrate the data from the old store to the new one. This option is what makes the persistent store support iCloud sync, by the way. 

You only need to do this migration once. How do you know when to do it? The best way to find this out it is to use the existence of the old store as an indicator that will tell you if you need to do the migration. At the application start up you check if the old store’s file exists . If it exists, that means the migration hasn’t been performed yet. So, you trigger the migration process. After migration is done you delete the old store.

Enough of theory. Lets see some code. This is an example of Core Data Stack class before we incorporated iCloud:

I got this piece of code from Apple’s Core Data Programming Guide.

The first thing you do is you use another file for the new persistent store. Let’s call it DataModelWithICloud.sqlite. And you need to add an option NSPersistentStoreUbiquitousContentNameKey to that store. I also added a couple of other useful options. So, you just change the code a little bit starting from line 24 in the previous snippet. Thats what you get (only the changed part is shown):

If you noticed, I also changed “Error migrating store” to “Error adding store”. I don’t know why the word ‘migrating’ was there in the first place, since we a not migrating anything at this point. OK, maybe some migration actually takes place at this point, but it must be a migration from an old version of data model to a new one. Not the migration from an old persistent store to a new one, that we are about to arrange.

But before we go further let’s just make a quick fix to the Apple code. Add this variable declaration to the CoreDataStack:

We will be using the Documents directory quite often so it makes sense to use this variable instead of putting couple lines of code here and there. Now you can go back to the first snippet and delete lines 19 and 20. Then find this line

and substitute aplicationDocumentsDirectory for docURL. So, you get this:

Now add these methods to CoreDataStack class:

Basically, this is it. You should call migrateToICloudIfNeeded() method from your appDelegate’s application:didFinishLaunchingWithOptions method. Now, when the user updates the app, the migration to the new persistent store will take place and the old store will be removed. 

PS. There is one more method that may be useful to you. While debugging you might want to delete all data on all devices and even in the iCloud container. So, use this one:

Only make sure not to ship your app with this method.

That’s it. I hope this post was useful to you. If you have any questions leave a comment below.