There isn’t a ton of info out there on it, and I’ve got some tips that I’m not sure I’ll get around to blogging about so I’ll add them here in a thread 👇
CKDatabaseSubscription
CKRecordZoneSubscription
CKQuerySubscription
Unless you’re *only* using the default zone, you should start with CKDatabaseSubscription.
If you know you’re for sure not supporting sharing, you can get away with a recordZoneSub *mostly*.
Subscribe to database changes from your private *and* shared databases.
Next, get record zone changes from the database subscription and then pass those into a CKFetchRecordZoneChangesOperation.
You’ll see both shared and custom zone record CRUD ops now.
At first I loosely coupled them but I’d argue to tightly couple them. If you generate a new one on the fly each time its change tag is new too, not what you want.
You need to cache the record along with the model to persist that.
If you’re using .deleteSelf on an existing one you’ll need to set a new reference as the parent, these CKReferences require .actionNone.
One thing that might feel weird at first is you get deleted record IDs, and then changed records. So it’s on you to see if you’ve got a “changed” record in your cache or not, i.e. is it new or an edit?
Might not be a big deal for some but it was for me.
So if you have lists -> list items, deal with lists first then list items.
Remember, the server is the truth, CloudKit is the glue and your local cache is representing that.
1) Its database change token
2) A dictionary for each zone change token, i.e. <CKRecordZoneID *, CKChangeToken *>
Are your requests lasting a long time, like SEVEN DAYS? That’s because you didn’t set your operation’s qualityOfService property and CloudKit chose for you....and it chose utility 🙃.
Set this accordingly for each operation.
If you’re building a WatchKit app - you can pretty much skip the connectivity framework and just query CloudKit 👌 Their API is strikingly similar across platforms.
A lot of sample code, when saving, uses the most relaxed save policy. Is it easiest? Yeah. Is it a good idea? Probably not. Apple made forced locks the default for a reason so I’d opt to use them. I only use .chnagedKeys in one place, and it’s to force edits.
This ties into saves because...
I won’t go huge into implementation details but the flow doesn’t really seem to be documented super clearly so I’ll lay it all out here from start to finish. This assumes you’ve got your record hierarchy setup correctly as mentioned before.
- Use UICloudSharingController one of two ways. Either you’ve shared already, so fetch the record and pass it with the container to the initializer. Or, you supply a preparation handler to create the share initially.
- Person accepts the share. Handle the delegate method and use the operation on CKContainer to pass the metadata and accept it.
Anyways if you’ve got resilient data, diffing and batch updates you’ve now got real-time collaboration which is awesome.
I won’t spend a lot of time here. If you’ve watched any of the CloudKit sessions, they all mention how important it is to handle all errors and they’re right. There’s something like 22 to look out for, it’s difficult at first but really it’s not a huge deal.
Anyways, I think that’s about it! Hope it helps a #iosdev out there!