Using File.applicationStorageDirectory across versions - ios

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.

Related

CloudKit: iCloud schema scheduled deploy (Using Seam3)

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.

Modify CoreData twice during development

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.

How to manage versions of Data Model Schema versions

I am having an app on app store. I have to update model version after every 2 months on average due to updates.
I have 7 versions right now and they will definitely increase in future.
I have some questions:
How I can efficiently manage this
Can I delete my older version?
How many versions I can add?
How I can efficiently manage this
I recommend naming the model versions based on the release they are associated with. It helps to keep things straight.
Can I delete my older version?
Yes but not recommended. If someone is still using an older version of your app they will fail to migrate if the source is not there.
How many versions I can add?
Unlimited. However you should only have a version for each production release where data structure has changed. If you have intermediate versions that only exist for development, I would recommend removing them as they don't impact the user.
Lastly, make sure you have a unit test that migrates from every old version to the current version. Core Data is not temporal and will not go from 1 to 2 to 3. It only understands source and destination. Can your app currently migrate from 1 to 10? If not, you need to address that.
How I can efficiently manage this
Continue to increase versions when you add changes to model.
Can I delete my older version?
Yes you can. Just open data model in finder and delete version, re-add data model to project. Also make sure you handle NSPersistentStore creation fail (if merge is unsuccessful).
How many versions I can add?
As many as you need.

Forcing or "encouraging" iCloud to upload changes to a file

I have a Mac and iOS application that is sharing data using iCloud, via a single "shoebox" file.
Most of the time, changes are properly synchronized in an efficient and prompt manner. However, every once in a while (particularly, right now) changes that I make on one device simply sit there.
I have made changes on my Mac to the shared data file, and the data has been saved to disk. However, I don't know whether it's the system's failure to upload the data to iCloud, or the iOS device's failure to check for the new data, but I'm twiddling my thumbs.
The 5KB file below is the one that should be changing. No matter how many changes I make in the Mac app, every once in a while during testing, iCloud will just stop syncing changes. If I walk away for 20 minutes and come back, it might start up again.
Further: If I run the Mac application in Xcode and keep an eye on the same file, even though I make changes to the file and can confirm that the file on disk (in the Finder/Terminal) is actually changing, the iCloud panel in Xcode does not pick up these changes very quickly either:
Note the same 5KB file has changed on my local filesystem on my Mac (at 9:01), but iCloud just isn't picking it up. There are actual content changes in this file, not just a modification date change.
So, I would like to find a way to either:
Trigger the sync programmatically, or even using Xcode. I know that the iCloud sync can be triggered using the simulator, but this only works when testing on iOS, and I much prefer to do my testing on the actual hardware anyway. Or,
Determine who (or what) is "at fault" for the data not being shared. I have followed the iCloud documents from the beginning, ensuring that I'm using coordinated writes to save changes, etc. It's just a very intermittent thing where iCloud will doze off, and makes testing very frustrating.
I don't think you can trigger synchronization of selected files, but you can use this tool "brctl" to see what is going on under the hood (or diagnose) (on OSX), to diagnose what it might be about.
commant line command:
$ brctl
for example use it like this
brctl log --wait --shorten
or
brctl diagnose
I realized when you migrate any store to your existing iCloud store, the iCloud store adds those data and forces sync to the version in the iCloud. So I migrate an empty store to my existing iCloud store, and I forced the sync!

Backup/restore sqlite file for Core data with Dropbox

I'd like to implement a backup and restore feature in a sql-backed Core Data app. I can successfully backup and restore .sqlite file via dropbox, but I have one question about this approach.
If, in the future, my data model changed there are 2 possibles case that will happen.
User backup in newer version and restore it in the older version of my app. From my understanding that will cause some schema error.
User backup in older version and restore it in the newer one. I think this one will work just fine because it should migrate as normal case.
If this assumption are right, what should I do to handle the problem that may occur from the first case?
When I make backup I create it as zip file containing plist file with stored version of backup in it. When I do restore I check that version and if backup is newer than current version I deny restore. It doesn't make sense to restore backup in older app version.
As long as You have necessary models it will work properly.

Resources