I use Seam3 framework to sync application data with iCloud.
I am working on new release and my CoreData schema was changed. So I changed iCloud schema accordingly. But I'm nervous about deploying it to production. When I tested sync, I have found that sync itself works properly, but is not able to finish successfully when new schema is deployed in CloudKit Development environment and app still uses old schema.
So to avoid any issues (or minimize prossible impact) - I need to deploy schema to production environment with application release in the AppStore. I can see that I can setup scheduled deploy in iTunesConnect, but did not see such option in CloudKit Dashboard.
I have also checked Apple Doc and did not found any solution for this. What is the best solution for this issue? To schedule deployment in iTunesConnect and log into CloudKitDashboard and promote schema to Prod in the same time when app should be published? But could there be any gaps between my action and real promotion to prod?
Apple doesn't provide any tools to coordinate schema roll out with an app release. I'm not familiar with Seam3, but I can see why the old version would fail attempting to sync with a new schema it doesn't understand. I see two courses of action here:
First option: you'd release a version of the old app that tolerates the new schema or gives a notice that an update is required when the new schema is detected. Then publish the new schema. Then release the new version of the app. If you haven't branched your code (so that you can release fixes to both versions), or if your new schema makes changes to the same records used by the old schema (as opposed to just adding new record types), then this could be very difficult.
Second option: Roll out the new schema in a new container. You can create as many containers as you like (although you can't never delete them). So the old app uses the original, probably default, container with the original schema. All of the new additions in the new container will effectively be invisible to the original version of the app and should therefore not confuse Seam3. Then, the new app uses the new schema in a different container. The new app can easily read data from the old container then write it to the new container, if you need to migrate data.
I prefer the second option because users of the old app will continue to operate fine, even if they never update. This could happen to users still using older hardware, say an iphone5, that can no longer update to the latest IOS but have the older version of your app installed. This approach also gives you the option to migrate data, since the new app can read from the old container and write to the new container. Finally, you can roll out the new schema in the new container ahead of the release of the new app so it's ready the minute your new version goes live, without interfering with the old version.
Related
Right now I use versioning to make any changes in a database. But it brings some problems. For example it's hard to merge a feature branch with a new db version into a master/dev where somebody also added a new version.
So my question:
Is it safe to change db in a single xcdatamodel without adding new versions? I tried so and it works but everywhere on the internet I see warnings that you must not do that.
iOS9+.
I found this: https://stackoverflow.com/a/37264096/5328417 but it's without a proof
As #pbasdf noted, since iOS 9 you can do a lightweight migration without adding any new model version. Source model (previous model version) is cached to store and used as a last ditch effort during lightweight migration.
I am using this feature in my own apps successfully. Although I was not able to find this documented. Just that WWDC video (18'15 Model Caching) mentioned. This is exactly the reason why Core Data is so mysterious sometimes..
If your app is in development stage then you may use one model without versioning.
But if it is release on the App Store then you have to create the versions when you make changes (such as adding a new attribute, adding a new entity, renames attributes etc.). Otherwise, Core Data won't perform lightweight migration.
I've gt a question to ask. Currently my production CoreData version is 1.0. Then , since i've gt a new class/property to add, i've increased version to 1.1 and released this version for tester.
Now, I need to add another property to CoreData.
1) So, should I create a new model version or I can straight away modify current CoreData(v1.1).
Note that the build with v1.1 CoreData hasn't been released to production yet..just to tester.
2) If need to add new version (v1.2) to accommodate the new property, will it have any affect when i released it to production build?
3) If can straight away modify, will current development version that tester has installed crash when they update to new version that has the new property added?
You can modify v1.1, but then tester will have to delete the app, as the app may not be able to open the coredata or have inconsistencies. To avoid this, tester will have to delete the app,and he might miss issues(if any) due to this structure change, to catch only in production. So you should be changing the version.
It wont cause any issues, if the versioning and migration is done properly.
Yes, there could be inconsistencies and instances where the app won't be able to open the coredata.
In order to avoid CoreData versioning for testing purpose you can modify the current CoreData version and tell your tester to delete the previous build before installing new one.
Otherwise you have to perform migration every time you change the DB schema in order to avoid inconsistency.
You can do the versioning before sending it to the production environment.
Hi I'm wondering if there is any method that is called when an app is updated similar to androids onUpgrade(). I'm using a SQLite database in my app and the schema has changed a lot in the new version.
If the old version is on the phone and I run the new version through Xcode. It will not work as the old tables do not correspond. The app syncs to the server so I am not worried about the users data. So I could drop all the tables on update.
There is no API to indicate an upgrade. You need to determine this yourself. There are many possible approaches.
What I do in my sqlite-based app is I have a meta-data table in the database. This contains a schema version number. I check this against a hardcoded version number I put in the code. If they are different then I know the database needs to be updated. I provide sql scripts in my app that can update any prior schema version to the current version. I simply run the script that matches the version shown in the database.
This approach allows me to deal with users that haven't upgraded in a while and the schema may need to go through multiple revisions.
I am using File.applicationStorageDirectory to store user data, specifically purchased items from iOS store.
I noticed that when users upgrade their version the data is lost and users need to restore their purchases (on ios items) , is it a bug on my side or is the File.applicationStorageDirectory not the correct place to store that kind of data.
Thanks!
applicationStorageDirectory is also known as the "temporary files" of the system. Regardless of the platform (desktop or mobile) or OS, when something drastic is done (such as installing a new version of the system), those temporary files are (generally) wiped out in the process.
Furthermore, uninstalling your application and reinstalling it (or, indeed, updating it) may (in some cases, dunno about iOS) delete those temporary files, or simply create a NEW directory for them, ignoring the old one.
Third, some cache-cleaning apps will also wipe out this data.
So, to answer your question, yes, you're going to want to store things you want to persist despite major changes, such as in-app purchases, in a new, dedicated folder in the userDirectory or the documentsDirectory.
I use Core Data. During development when I add a new model version, I need to clean my project in xcode before I build it, so that a migration to the new model version takes place.
So when my users update their app is their app "cleaned" as well before the first start?
Or do I need to force migration in another way?
To be more precise: When I just build my new app version (with a new core data model version) in xcode and run it on the device it crashes whenever I try to access new properties of my managed objects (since it did not migrate the sqlite DB to the new model).
Yes, in the way you understand "cleaned", the apps of your users are put into an executable state. All data stored in Core Data's persistent store will be migrated to the new store and will be available as before.
In fact, that is the whole point of Apple's migration scheme. As pointed out by FR, read the documentation.