14

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?

Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
boweidmann
  • 3,312
  • 2
  • 20
  • 27
  • 1
    Have you tried to login in to your iCloud account on iPhone Simulator (in settings menu)? – ninjaproger Apr 14 '15 at 18:41
  • I have a bunch of code that tells me in the console whether iCloud is enabled. So I get error message if iCloud is not set properly outside of the MagicalRecord framework. Now I have no errors, hence everything should work but it doesn't – boweidmann Apr 17 '15 at 10:09
  • We need more information. What do you mean by "all the xcode setup", and "everything regarding provisioning profile"? Furthermore what do you mean by "nothing seems to happen"? So far it's a fairly broad question, and we need more details into what you're actually experiencing. Is there any network activity? – Beau Nouvelle Apr 21 '15 at 02:38
  • Do you know how to setup auto migrating core data stack with icloud container? – Bartłomiej Semańczyk Apr 10 '16 at 14:06
  • @BartłomiejSemańczyk if you follow both functions to their roots you will see that both are adding sqlite store passing "automigration options", so I bet **they both** create an auto migrating core data stack with iCloud container. – boweidmann Apr 10 '16 at 15:45

2 Answers2

7

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!


boweidmann
  • 3,312
  • 2
  • 20
  • 27
  • hello @boweidmann do I need to write both the line on Appdelegate? [MagicalRecord setupCoreDataStackWithStoreNamed:@"db.sqlite"]; [MagicalRecord setupCoreDataStackWithiCloudContainer:@"iCloud.com.name.app" contentNameKey:@"BackupContent" localStoreNamed:@"db.sqlite" cloudStorePathComponent:@"ContentPath"]; – Chirag Lukhi May 18 '20 at 12:21
  • @iChirag I don't recommend using MagicalRecord cause it's old and not being supported anymore. But to your question - no, you should call just the iCloud setup method, the second one – boweidmann May 19 '20 at 12:42
  • thanks @boweidmann. I already planned to not use MagicalRecord for iCloud. – Chirag Lukhi May 20 '20 at 10:52
0

What you have done above is correct however a few things to check.

  • Make sure you have your provisioning profile set up correctly.
  • Check your profile string for any spelling mistakes.
  • Ensure you have downloaded and installed your new provisioning profile.
  • Check your local store name for spelling mistakes.
Beau Nouvelle
  • 6,962
  • 3
  • 39
  • 54
  • Hi Beau Young, thanks for answering, I'm going to test it out later. Do you have it working well? – boweidmann Apr 22 '15 at 06:43
  • I did then pulled it out and decided to do it the hard way and use Core Data directly. Soon I'll be rewriting and moving into this https://realm.io – Beau Nouvelle May 04 '15 at 04:14
  • thanks @Beau Young for suggesting realm.io, sounds like a great library and completely free. However, I didn't find anywhere the syncing functionality, that would be a killer feature for this cross-plattform database. – boweidmann Jun 12 '15 at 12:38