iCloud and lightweight migration - ios

I've a published app synchronizing a Core Data with iCloud.
I need to update the model adding two attributes and then populate these new fields.
I've tested lightweight migration locally and works fine, I can see the old data migrated into the new model scheme.
When I activate iCloud, old data saved in the ubiquity container doesn't sync with the new model schema.
What is the expected behavior?
Should I be able to sync data both on old and new model versions?
How can I achieve it and test this situation?
I've read:
CoreData versioning
and
Understanding Core Data iCloud Store Migration When Testing an iOS App Update
but, actually, I'm very confused.

What's supposed to happen is that iCloud data only syncs between devices that are using the same version of the data model. If you upgrade the app on one device but not on a second device, they won't sync changes until the second device also updates to the new model version.
If that's not what you're seeing, please add more details about the problem you're seeing.

Related

Lightweight CoreData Migration with CloudKit

Does Core Data handle simple data-model additions like a new attribute w/out any further "help" from me? In my case, I have an app that uses Core Data for varius things related to a users profile. I have an existing data-model entity called Profile that I want to add 2 new attributes to:
hasPublished: Boolean
lastDetail: String
So, does this cover my case? I'm not re-naming anything, just adding.
One more caveat, I'm using a NSPersistentCloudKitContainer as info can be shared across the users devices.
Yes it can handle, but there is some little work from your side.
You need to create new version of Core Data model.
Call initializeCloudKitSchema() so changes are uploaded to CloudKit.
Don't forget to deploy changes to production from CloudKit dashboard.
Remove initializeCloudKitSchema() when deploying your app to AppStore.

Apple's Cloudkit Migration

This may be too simple of a question for SO, but for those that have used both Cloudkit/Core Data, do you have to migrate data in Cloudkit similar to Core Data if you make any changes to the database itself?
For example, if you adjust your Core Data model at all, you have to go through a migration process in order to make sure the App still works appropriately. Is Cloudkit the same way?
From my understanding there is no migration process necessary (judging when I make changes and run them in the simulator just fine), but I want to confirm before I upload to the App Store. Thanks for any help!
This is covered in detail in the Deploying the Schema section of the CloudKit Quick Start.
The quick summary is that you do need to push changes to production using the CloudKit Dashboard. But keep in mind that you can only make limited schema changes so plan ahead well. You can add new fields. You can add new record types. You can't delete anything.
Keep in mind that users of your app will be using old versions as well as new versions. The latest version of the app will of course know about any new additions to the schema. Old versions of the app won't know about the new fields and record types.

Core Data store empty after app update - but data model hasn't changed

I am developing an update for an app that uses Core Data to persist data.
I use Magical Record to make dealing with Core Data easier.
This update doesn't involve any changes to the data model.
Yet, when I install the new update on a device, the existing data is deleted, and the app opens with an empty data store. There are no warnings or error message about data migration issues logged. The app also doesn't crash and shouldDeleteStoreOnModelMismatch is set to NO before the Core Data stack is set up ([MagicalRecord setShouldDeleteStoreOnModelMismatch:NO];).
There are no subsequent Core Data issues (new data is persisted fine).
The main changes made to the app in this update are:
Converted the app to ARC
Converted the app to use CocoaPods for external libraries
Updated the MagicalRecord library from v1.8.3 to v2.1
In my App Delegate I set up the Core Data stack using:
[MagicalRecord setupAutoMigratingCoreDataStack];
Does anyone have any idea what can be causing this?
When you have an empty store, generally it means your migration model isn't step up properly, or your model schema identifiers don't match the version identifiers for the data store.
Make sure you keep both versions of your core data model (before and after). This is how core data matches up the store with your model, and also how to know which version is the newest version.
After deletion of the store, you need to specify that you want to replace the store with a new one automatically, as so.
[MagicalRecord shouldAutoCreateDefaultPersistentStoreCoordinator];
[MagicalRecord setShouldDeleteStoreOnModelMismatch:YES];
[MagicalRecord setupAutoMigratingCoreDataStack];

iCloud, Core Data, migration and model mapping

As said in the Apple documentation
Schema migration using mapping models is not supported (lightweight
migration is supported).
I was wondering about options we have in case we need to deal with iCloud fonctionnality and mapping model migration... I know that I will need to change my Core Data model in the future to add functionalities to my application (and not only in a lightweight way). The thing is that I can't say now which new entities will be needed and which relationships with previous model entities will be set.
I was thinking about a sequence like that:
1 - Launching my app doing the mapping migration of my Core Data Model
2 - Letting it synchronized with iCloud
This will work if iCloud contains transaction log files adapted to the new Model. In case of old transaction log files (means adapted to the old Model) it will failed.
To avoid that I was thinking about doing:
1 - Launching my app letting it synchronized with iCloud
2 - Doing the mapping migration of my Core Data Model
3 - Removing old iCloud data updating it with the new one
This will not work if iCloud already contains updated transaction log files (means adapted to the new Model).
What I need is a way to check if transaction logs in iCloud are compatible with my current Core Data Model. Is there a way to do this ?
Thanks.
I would not recommend using Core Data with iCloud in a production app.
Its not stable enough. There is no simple way of checking if the app is en/disabled in the iCloud settings. And not to mention the problems that can arise if the user turns the iCloud support off after having it enabled.
Migrations are another issue. Lightweight migration works fairly well. But in order to make a mapping model migration work, you need to clean out/evict content from the existing iCloud "ubiquity folder", create a new one (with a new name) and change the value associated with NSPersistentStoreUbiquitousContentURLKey. And, you need to make sure that all clients do the same. Its complex but doable. Not sure if its worth it though...
Regarding the version compatibility issue, I've not yet tried it, but an idea would be to somehow get the store metadata from an iCloud transaction log and through the "compatibleWithStoreMetadata" method on ManagedObjectModel check if the version matches:
// Get current model
NSManagedObjectModel *myModel = [self managedObjectModel];
// Check compatibility
BOOL isCompatible = [myModel isConfiguration:nil compatibleWithStoreMetadata: metadataFromTransactionLogEntry];

Updating an ios app that uses coredata with a version without

We are planning to update an iOS app that currently uses coredata with a complete rebuild that isn't using coredata. If the schema is not present in the update bundle will it crash on existing users devices?
This is hard to test but I'm guessing as the schema is associated with the app it will need to be present even if it isn't going to be used.
Anyone had experience with doing something like this?
The data model (what I'm assuming you're calling the schema) is only needed in app if you're building a Core Data stack. It can be removed if you're not building one.
You're app should still be using Core Data for the time being though. You're going to want to build the Core Data stack to use it to read in the user's existing data for migration. So if that's the case, don't go deleting it from the app yet.

Resources