Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get iCloud with MagicalRecord (Core Data) up and running?

I was struggling all the last days in order to enable iCloud support for the data I'm managing with MagicalRecord framework.

I did everything regarding provisioning profile, and all the setup in xCode. In code instead of calling

[MagicalRecord setupAutoMigratingCoreDataStack];

I'm calling

[MagicalRecord setupCoreDataStackWithiCloudContainer:@"AppIDFromiTunesConnect.com.companyName.myAppName" localStoreNamed:@"whatever"];

I try to simulate syncing by triggering iCloud Synchronisation on iPhone Simulator. But nothing seems to happen. I can't see anything on developer.iCloud.com.

Question: anyone has got iCloud with MagicalRecord up and running? Would you please explain how to get it done?

like image 570
boweidmann Avatar asked Apr 08 '15 08:04

boweidmann


1 Answers

OK guys, I think I got it working.

UPDATE Initially it worked for me but I had some very strange effects and the fact that if you log out from iCloud the ubiquity container gets deleted made me think about alternative solution. Now I use Ensembles library and am mostly very satisfied with it. END UPDATE

I just pimped my own test app I wrote 2 years ago, that had no CoreData nor iCloud and it seems to work nice. It syncs the database across my iPhone and iPhone Simulator. The one little thing that drives me nuts is that I still don't see anything on https://developer.icloud.com ..

Now I'm going to do the same for my distributed app. Here is exactly what I did:

  1. The nice thing about all that stuff is that you almost don't have to do nothing on the Developer Portal (like create and download provisioning profile, even creating App ID is not necessary) - XCode 6.3.2 does all this for you; if you know the order, of course. So first, go to your target's Settings -> Capabilities, and enable iCloud. Xcode does the job of adding Entitlements file, creating App ID on the developer portal and creating iCloud Container. Uncheck "Key-Value Storage" and check "iCloud Documents".

Enabling iCloud in XCode

  1. I assume you are using MagicalRecord and you setup your Core Data stack as following:

[MagicalRecord setupAutoMigratingCoreDataStack];

In this case MagicalRecord creates a local store which name you can get by calling [MagicalRecord defaultStoreName]. You will need to state this one in the iCloud setup call. So the code I have right now in AppDelegate.m is:

NSString *defaultStoreName = [MagicalRecord defaultStoreName];
[MagicalRecord setupCoreDataStackWithiCloudContainer:@"Container ID from Developer Portal (as on image)"
                                      contentNameKey:@"DataStorage" // It seems like you can write whatever you want here
                                     localStoreNamed:defaultStoreName // Unless not specifically named earlier
                             cloudStorePathComponent:@"stuff"]; // Seems like you can write whatever stuff you want. 

This method worked for me. The other, shorter iCloud setup calling method (without ContentNameKey) was throwing no exceptions, but didn't work properly. I guess, you just have to state ContentNameKey.

Here is where you get container ID on Developer Portal. I know, it seems like a very detailed instructions, but I wish it was so clear to me that "iCloudContainer" string in the function above is actually iCloudContainerID and should be retrieved from Developer Portal. Container ID

  1. Go to device Settings -> iCloud -> iCloud Drive and enable it. Login to iCloud with your account. This is crucial for the whole thing to work.

iCloud Settings on the Device

  1. Now try to run the app on the simulator at least. If you've got no "iCloud not enabled" message in the logs, you're on the half-way.

  2. Register the object that is responsible for all Core Data actions to listen to the NotificationCenter on following events: NSPersistentStoreCoordinatorStoresWillChangeNotification NSPersistentStoreCoordinatorStoresDidChangeNotification NSPersistentStoreDidImportUbiquitousContentChangesNotification

like this:

[[NSNotificationCenter defaultCenter] addObserver:self
           selector:@selector(storesWillChange:)
               name:NSPersistentStoreCoordinatorStoresWillChangeNotification
             object:nil];

and handle the changes properly.

The hard job is still yet to be done and now it depends on your project and I can not give you any advice individually.

For me the problems were:

  • how to react on changes in the remote store
  • how to merge different data and avoid duplicates
  • how to avoid complete data loss if iCloud container is empty

But I hope to find all the answers to my questions in the official Apple Manual to iCloud.

I'm happy to having avoided a couple of days of headache for you! Please write a comment if this solution worked for your project!


like image 140
boweidmann Avatar answered Oct 24 '22 01:10

boweidmann