upload offline changes on cloud with CloudKit

CloudKit is the framework that powers iCloud on IOS I used this framework recently in a new project and i found it cool and easy to use but I had one issue and it's about offline mode when I have two devices A and B connected to the same ICloud account if A has no internet connection and made changes , how can I upload those changes to Cloud once A is connected to the Internet i looked too much about that and I found solutions like :


** using core data with cloud kit



** CKOperation with Long-Lived


about the first solution I think it's complicated to create coredata individually from cloud data and i read that it's recently kind of deprecated. For the second option I don't know if it's working or not but i included because I found this question with no details

How to fetch all long-lived operations on iOS

does anyone know how to handle offline operations ? and it the 3rd solution is working , could you give a sample code for that Thanks in Advance

Replies

In CloudKit when offline the loads and fetches fail with an error code. So the app is responsible for handling it.


But with the iCloud key-value file (not CloudKit) the system records the change and pushes it up to the cloud when it is next available. That's what 'ubiquitous' means.

I had the same question. What if the data model is big? Is it better to use coredata + cloudkit or does Apple suggest a better solution?



its a data model with Many entities have a Many-Many relationship.


(PS: To the OP. Coredata with icloud has been depricated. I am glad!)

I think that you could have a field in Coredata called isSyncWithIcloud : Bool and another callled lastSyncDateAndTime : Date.


So when your app has internet conection, check if coredata has uncommitted changes and send it to Icloud, but checking previously that there are no changes in Icloud with Dates and Times after your changes and after that set isSyncWithIcloud to true in coredata.

>** CKOperation with Long-Lived


>about the first solution I think it's complicated to create coredata individually from cloud data and i read that it's recently kind of >deprecated. For the second option I don't know if it's working or not but i included because I found this question with no details

>does anyone know how to handle offline operations ? and it the 3rd solution is working , could you give a sample code for that Thanks in ?>Advance


Handling 'long lived operations' seems tricky. For one, on iOS, CKContainer's -fetchAllLongLivedOperationIDsWithCompletionHandler: does not seem to be working (as of iOS 13). But I have been able to get an operation using -fetchLongLivedOperationWithID:completionHandler:

So it seems that the developer has the overhead of writing long lived operationIDs to disk, and clearing them when the operation finishes.


Another thing I'm thinking about is error handling. What about errors? After 'replaying' a long lived operation, if there is an error, you may need to rollback your local cache and inform the user that an operation failed. So, to do that looks like a pretty good amount of work.


So here's a tricky error handling situation:


App commits change to local cache -> CKModifyRecordsOperation long lived operation is in flight for this change -> App gets killed -> CKModifyRecordsOperation fails with some sort of error while the app is killed.


When the app replays the long lived operation on next launch (which again, the operationID needs to be cached and retrieved from disk by the developer) and gets the error, there are several challenges to handle this situation properly. One challenge is finding what change in the local cache needs to be reverted, assuming the error handling logic requires this. Mapping a generic modify records operation to some action in your app (like OperationThatMarksJuiceAsFavoriteDrink) requires a lot of additional caching for long lived operations, and a bit of introspection.


If the long lived operation succeeds, of course, there's not much of a problem. Replaying the operation would essentially do nothing for the current client. But handling long lived operation errors seems tricky.


The other way would be to do every CKModifyRecordsOperation first, and not committing changes to the local cache until after they succeed. But the app would basically always require a network connection to work (may be okay for some apps, but not mine).