Save my app data through phone restore - iOS Swift - ios

What technology is available for me to save app data (Core Data) so that when a user switched phones and has a fresh phone they still have my app information?
I have heard people say cloudKit, however that seems overkill, I don't want the functionality to handoff between devices. I simply want the app data to be backed up when the user has iCloud backup enabled for the app.
If the answer is iCloud, what steps must I follow to enable such behavior? I have seen links to cloudKit tutorials, however all of them cover an extensive amount of material and work, and what I want to achieve seems simple enough. (As stated before I do not want handoff between devices, I have no need for it.).
Thank you for the suggestions
Edit: I have gone into "capabilities" and switched on iCloud. Now in my iPhone settings under iCloud backup my app appears. However does simply switching on iCloud capabilities persist your app data to iCloud Drive or backup?
Ex: Go to Settings -> Account -> iCloud -> Scroll down to iCloud Drive and ensure it is checked. My app shows there, but I haven't included any code to implement this (I simply flipped the switch in capabilities)
So from my current understanding I create Core Data as normal, however I add a listener for an changes/updates/deletes/creation of the persistentStore and upload/update iCloud via document storage when this happens? I was under the impression that iCloud was being depreciated and that only cloudKit will remain?
Edit 3:
iCloud = Depreciated, therefore the one and only solution available is cloudKit.
How does one implement cloudKit to interact correctly with Core Data?
What comes to mind is the following:
- Enable cloudKit
Listen to all changes to persistent Store and reflect these changes in CloudKit (somehow)
On app start check to see if CloudKit matches core data (somehow)
if they are not the same then download cloudKit data and save to core data (somehow)
Please clarify if this is not the correct route to proceed down

What technology is available for me to save app data (Core Data) so that when a user switched phones and has a fresh phone they still have my app information?
There isn't any such problem. I've upgraded devices many times and nothing has ever been lost. When I got a new iPhone last year, and when I got a new iPad this year, all my apps on the new device simply showed up with the same settings and data as before on the old device.
That's the because the user who gets a new device backs up from the old device and restores to the new device. That's what I always do and it just works. You cannot reliably work around a user who is too stupid to know to do that, so I recommend not even thinking about it.

Related

Failing to receive NSUbiquitousKeyValueStoreInitialSyncChange

I have a iPhone/iPad App written in Objective-C.
My App shares data between multiple devices via the iCloud using the Key-Value Storage data model. This logic has all worked now for literally years.
Yesterday, I cleared my App from my iPhone A, I reinstalled the App onto iPhone A and then I enabled iCloud Sharing on iPhone A.
After enabling iCloud data, as expected, a full copy of my most recent data downloaded onto iPhone A from the iCloud. Everything looked good.
But later, when I modified the data on iPhone A and attempted to share it with the other devices via iCloud, I got an error message.
The error message warned me that until I had received an InitialSyncChange notification from iCloud, it was unwise for me to propagate the data on iPhone A through the iCloud and onto my other devices.
Long ago, when I wrote this iCloud code, I had set it up so that it would refuse to send data out to the iCloud unless it had previously set a flag indicating that it had seen an incoming InitialSyncChange notification.
But what puzzled me here was that I had seen a copy of my most recent shared data downloaded onto iPhone A from the iCloud after I had enabled iCloud sharing.
When I looked into this and repeated the situation several times, I discovered that when the initial copies of my shared iCloud data were arriving on iPhone A, they were arriving with StoreServerChange notifications and not with InitialSyncChange notifications.
I have no idea why this has changed. Has anyone else seen something similar?
I have an obvious and easy fix for the problem but, in truth, I really hate applying fixes when I don't fully understand why things have changed.
My fix, if you are curious, would be to change how I set the flag that records if I've seen an incoming InitialSyncChange notification.
Now I will set it when I've seen either a InitialSyncChange notification or StoreServerChange notification.
Either notification 'proves' that I've got a valid copy of the shared data. And if as the flag is not set, then the existing logic prevents the App from sending out bogus data and messing with the valid shared data.
Any thoughts or trouble-shooting advice would be appreciated.

How to export Core Data sqlite to iCloud and import back for new devices

I'm developing core data based app and want to implement iCloud so that user can recover data from iCloud if he lost device and bought new one.
I enabled iCloud capability and iCloud documents(I'm currently using NSPersistentContainer, I don't want to use NSPersistentCloudKitContainer yet)
I know iOS 13 provides way to sync Core Data with iCloud but I think that doesn't seem to be ready for production app yet(Migration doesn't work well)
So I want to back up core data to iCloud every 24 horus to iCloud and when user installs app in new device we can check if iCloud has existing sqlite file and restore it if there is any.
Could anyone please suggest good solution?
Thanks.

Apple Watch and Core Data iCloud Syncing

I've been wrestling with this problem for a while now and can't seem to find anything on the topic. There are plenty of example on how to use Core Data with Apple Watch, but none that have iCloud support, so I'm hoping someone can shed some light on this subject.
I have an app that uses Core Data and the NSPersistentStoreUbiquitousContentNameKey option when creating the persistent store to make it sync to iCloud and between devices. This works great between iPhone and iPad. However, Apple Watch syncing is spotty at best. Sometimes it works, sometimes not and when it does an initial sync it doesn't seem to sync anything after that.
The reason as I see it is, even though the Watch app is an extension of the iPhone app, because it uses NSPersistentStoreUbiquitousContentNameKey it created a database under another folder instead of using the same one as the iPhone.
Path for the database for the iPhone
iPhone:
PFUbiquitySetupContainerIdentifierKey: 8B652C84-62E1-4FFF-B822-13C90C19DC5F
file:///Users/Aaron/Library/Developer/CoreSimulator/Devices/
6E2EE13A-3148-4693-A92F-7B23C709CF78/data/Containers/Shared/AppGroup/
B7DEE2C6-D345-460C-884D-74C011BF98BA/CoreDataUbiquitySupport/
nobody~simA7716E1E-6B21-5DAA-AF81-CAF6AE77A985/iCloudDATA/
8B652C84-62E1-4FFF-B822-13C90C19DC5F/store/appname)
Path for the database for the Apple Watch
Watch:
PFUbiquitySetupContainerIdentifierKey: 44220421-4F7C-46AC-B3D7-6ABEDA62C77B
file:///Users/Aaron/Library/Developer/CoreSimulator/Devices/
6E2EE13A-3148-4693-A92F-7B23C709CF78/data/Containers/Shared/AppGroup/
B7DEE2C6-D345-460C-884D-74C011BF98BA/CoreDataUbiquitySupport/
nobody~simA7716E1E-6B21-5DAA-AF81-CAF6AE77A985/iCloudDATA/
44220421-4F7C-46AC-B3D7-6ABEDA62C77B/store/appname)
Notice that the tile paths are exactly the same with exception to the PFUbiquitySetupContainerIdentifierKey that is in the paths, each device has their own.
If I remove the store option PFUbiquitySetupContainerIdentifierKey, it works fine, but then the devices won't sync with each other.
I was wondering if anyone else has had this problem or any possible solution to it, or am I just doing it all wrong?
Thanks in advance!
EDIT: After contacting Apple dev support, it seems this is a known issue with Core Data & iCloud syncing when the code for that is in an extension. I had to move all my data handling back to the main bundle for it to work again.
Link to known issue thread: https://devforums.apple.com/message/1051015#1051015

Do files in NSDocumentDirectory transfer when user upgrades iPhone

I have an app that saves user entered information to the NSDocumentDirectory. On issue that people are having is when they upgrade their iPhone to iPhone 5, the information in their old NSDocumentsDirectory are not being transferred over, even when they select the app to be transferred over.
Users end up loosing all their entered data when they upgrade.
When users upgrade the app on the same phone they do not lose their data. It only happens when they upgrade to a new iPhone.
What is the way to correctly save User data and make sure it is transferred over when the phone is upgraded?
Data is only transferred to a new device if they choose to do a full backup of the old device and then choose to restore that full backup to their new device. Simply transferring apps results in fresh installs of the apps with no data.
This has always been a major problem with iTunes (and now iCloud backups). There is no way to backup a single app and its data and there is no way to restore a single app and its data. Only the app can be restored but no data unless a full device restore is done.
All of my apps have their own built-in features for backing up and restoring its own data. This allows users to easily transfer data between devices or deal with them messing up their own data by mistake.

Questions concerning iCloud + core data

I have an app on the app store, that uses coredata as storage. I wan't to update the app with iCloud synchronization as new feature. Following apple`s sample code, I managed to have my core data storage synchronize between devices.
However, I'm experiencing problems when either iCloud synchronization is turned off/on in the app on only one of the devices, or when the app is deleted from the device and the reinstalled. In both cases, data is not synchronized back to the device, although it is available just fine on a second device (which was not disabled/reinstalled).
I also found that all storage is effectively erased completely, when I delete the app from all devices, and then reinstall. Althrough I get a couple of merge notifications in the console (even some without errors), I can't see no data in the local storage of the device.
Browsing the mobile documents folders on my mac still reveals lots of transaction logs in the icloud storage of my app.
Even deleting the app from all devices and starting from scratch wont sort things out. I will end up in a situation where data is either only synced to one device, or not synced at all.
I wonder if there is anything I can do about this inconsistent state that is created when only one device is temporarily iCloud disabled, or the app is deleted from ONE device?
As for my code, its an 1:1 copy of the recipces example from apple.
Daniel Pasco talked about using Core Data and iCloud together at NSConference 2012. Some notes from that blog post:
launching with -com.apple.coredata.ubiquity.logLevel 3 to get a spamfest in the message log saying what Core Data and iCloud are doing.
The conclusion from this talk appears to be that using Core Data and iCloud are really not ready for each other at this stage.
He posted an updated Core Data Recipes project on Github which may or may not fix your problem.
Apple makes it seem easy, but there are a number of nuances with regard to correctly seeding iCloud with data, and what happens afterwards when iCloud support is toggled on and off on different devices.
I implemented a sample project that demonstrates a straightforward way to add iCloud support to Library-style CoreData apps. It's called iCloudStoreManager and it's available on github.
I'm still testing it before I add iCloud support to one of my own production apps. It's working, but I see unexpected errors and delays when an iPad 3 is in the mix. It works, but with long delays.
I've also tested with iPhone 4, iPhone 4S, and the original iPad, and any mix of those devices works well in my experience.

Resources