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

2

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?

Mathes answered 8/4, 2015 at 8:27 Comment(5)
Have you tried to login in to your iCloud account on iPhone Simulator (in settings menu)?Chemotaxis
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'tMathes
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?Deicer
Do you know how to setup auto migrating core data stack with icloud container?Carsick
@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.Mathes
M
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!


Mathes answered 12/6, 2015 at 12:35 Comment(3)
hello @Mathes 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"];Carhart
@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 oneMathes
thanks @boweidmann. I already planned to not use MagicalRecord for iCloud.Carhart
D
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.
Deicer answered 21/4, 2015 at 2:34 Comment(3)
Hi Beau Young, thanks for answering, I'm going to test it out later. Do you have it working well?Mathes
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 realm.ioDeicer
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.Mathes

© 2022 - 2024 — McMap. All rights reserved.