Hi,
when using CKSynEgine
it is the responsibility of the app to implement CKSyncEngineDelegate.
One of the methods of CKSyncEngineDelegate
is nextFetchChangesOptions.
The implementation of this method should return a batch of CKRecords
so that CKSyncEngine
can do the syncing whenever it thinks it should sync. A simple implementation might look like this:
func nextRecordZoneChangeBatch(
_ context: CKSyncEngine.SendChangesContext,
syncEngine: CKSyncEngine) async -> CKSyncEngine.RecordZoneChangeBatch?{
await CKSyncEngine.RecordZoneChangeBatch(pendingChanges: syncEngine.state.pendingRecordZoneChanges) { recordID in
// here we should fetch to local representation of the value and map it to a CKRecord
}
}
The problem I am having is as follows:
If the CKRecords
I am returning in a batch have dependencies between each other (using CKRecord.Reference
or the parent
property) but are not part of the same batch, the operation could fail. And as far as I understand, there is no way to prevent this situation because:
A:
The batch I can return is limited in size. If the number of CKRecords
is too large, I have to split them into multiple batches.
B:
Splitting them is arbitrary, since I only have the recordID
at this point, and there is no way to know about the dependencies between them just by looking at the recordID.
So basically my question is: how should the implementation of nextRecordZoneChangeBatch
look like to handle dependencies between CKRecords?
Did you really see that kind of error? If yes, would you mind to share the details about how you trigger the error?
I'd assume that, when triggering nextRecordZoneChangeBatch(_:syncEngine:)
, CKSyncEngine
will ensure the records that have dependencies are included in context.options.scope
(CKSyncEngine.SendChangesOptions.Scope), if you put the records together when adding a pending change.
For example, if you relate two records with CKReference
, you'd save both records when adding the pending change:
let pendingSaves: [CKSyncEngine.PendingRecordZoneChange] = [theSourceRecord, theTargetRecord].map { .saveRecord($0.recordID) }
syncEngine.state.add(pendingRecordZoneChanges: pendingSaves)
If you did add both records to the pending change, but one of them is excluded in the scope, I’d suggest that you file a feedback report (http://developer.apple.com/bug-reporting/) to see what the CloudKit folks have to say – If you do so, please share your report ID here.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.