问题
I am using CloudKit Sharing and am having an issue deleting records. I create two records: an Entry and an Asset. If I set the .parent
of the Asset to point to the Entry, then when I attempt to delete both the Entry and the Asset in the same batch, it fails with a reference violation error:
<CKError 0x600002ac2190: \"Reference Violation\" (31/2025); server message = \"Record delete would violate validating reference ([a1]), rejecting update\"
Details
I create a parent record (Entry) and a child record (Asset), and set the Asset's .parent
to the Entry:
let eid = CKRecord.ID(recordName: "e1", zoneID: CKRecordZone.ID(zoneName: "test", ownerName: CKCurrentUserDefaultName))
let e = CKRecord(recordType: "Entry", recordID: eid)
e["title"] = "Entry"
let aid = CKRecord.ID(recordName: "a1", zoneID: CKRecordZone.ID(zoneName: "test", ownerName: CKCurrentUserDefaultName))
let a = CKRecord(recordType: "Asset", recordID: aid)
a["position"] = 1
a.setParent(e)
Then I save both in the same call:
let op = CKModifyRecordsOperation(recordsToSave: [e,a], recordIDsToDelete: nil)
op.modifyRecordsCompletionBlock = { (records, recordIDs, error) in
print("Returned from modify")
print("records: \(records)")
print("error: \(error)")
}
CKContainer.default().privateCloudDatabase.add(op)
The operation completes successfully and the records are properly created in CloudKit.
But, when I attempt to delete both:
let op = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: [eid, aid])
op.modifyRecordsCompletionBlock = { (records, recordIDs, error) in
print("Returned from modify")
print("records: \(records)")
print("deleted: \(recordIDs)")
print("error: \(error)")
}
CKContainer.default().privateCloudDatabase.add(op)
I get the above error.
Work Arounds
I realize that I could delete the Asset first, and when that returns, delete the Entry. But, my remote management code batches many things together and I don't want to re-work it figure out which things to do first, and I want to minimize the number of remote calls I need.
I've also discovered that if I add another field to the Asset record that references the Entry with a .deleteSelf
action, this all works. So, in the above code where I create the Asset, if I add the following (while keeping the setParent()
call:
a["entryRef"] = CKRecord.Reference(record: e, action: .deleteSelf)
Then all works correctly.
But, why should I need to create another field I don't need? I would think that sending the deletions in a single call would let CloudKit handle the references properly, without the need for this extra field.
Has anyone experienced this or found a way to work around it without needing the extra reference field? Using CKRecord.References
imposes a limit of 750 references on the parent, and I'd rather not have that limit.
来源:https://stackoverflow.com/questions/56796246/cannot-delete-ckrecords-with-parent-set