encodeSystemFields
应该在我本地保存记录的数据库中使用。
一旦我导出数据,在反序列化时是否需要采取任何特殊措施?
在什么情况下应该根据该数据中的信息采取行动?
作为一种变化(如果前一个问题未涉及),这些信息有什么帮助可以防范什么?(我认为是数据损坏)
encodeSystemFields
应该在我本地保存记录的数据库中使用。
一旦我导出数据,在反序列化时是否需要采取任何特殊措施?
在什么情况下应该根据该数据中的信息采取行动?
作为一种变化(如果前一个问题未涉及),这些信息有什么帮助可以防范什么?(我认为是数据损坏)
encodeSystemFields可以避免再次从CloudKit获取CKRecord以进行更新(除了记录冲突)。
其思想是:
当您存储从CloudKit检索到的记录的数据(例如,通过CKFetchRecordZoneChangesOperation检索以将记录更改同步到本地存储):
1.) 将CKRecord编码为NSData:
let record = ...
// archive CKRecord to NSData
let archivedData = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWithMutableData: archivedData)
archiver.requiresSecureCoding = true
record.encodeSystemFieldsWithCoder(with: archiver)
archiver.finishEncoding()
2.) 将archivedData本地存储(例如在您的数据库中),与本地记录相关联。
当您想将对本地记录所做的更改保存回CloudKit时:
1.) 从存储的NSData中取消归档CKRecord:
let archivedData = ... // TODO: retrieved from your local store
// unarchive CKRecord from NSData
let unarchiver = NSKeyedUnarchiver(forReadingWithData: archivedData)
unarchiver.requiresSecureCoding = true
let record = CKRecord(coder: unarchiver)
2.) 使用未归档的记录作为更改的基础。(即在其上设置更改的值)
record["City"] = "newCity"
3.) 通过CKModifyRecordsOperation将记录保存到CloudKit。
从iOS 15 / Swift 5.5开始,这个扩展可能会有所帮助:
public extension CKRecord {
var systemFieldsData: Data {
let archiver = NSKeyedArchiver(requiringSecureCoding: true)
encodeSystemFields(with: archiver)
archiver.finishEncoding()
return archiver.encodedData
}
convenience init?(systemFieldsData: Data) {
guard let una = try? NSKeyedUnarchiver(forReadingFrom: systemFieldsData) else {
return nil
}
self.init(coder: una)
}
}
encodeSystemFields
方法仅编码CKRecord的系统元数据值,而不是您设置的任何键和值。因此,您绝对应该将CKRecord中的“数据”(您设置的字段)单独记录在数据库中 - 这不是冗余的。请注意,不能改变原意。 - breakingobstaclesCKRecord
,因为encodeSystemFields
将从nil
开始?你可以像这样手动创建记录吗?let record = CKRecord(recordType: "...", recordID: CKRecordID(recordName: "...", zoneID: "..."))
- Clifton LabrumCKModifyRecordsOperation
以保存它。如果在操作上设置了perRecordCompletionBlock
或modifyRecordsCompletionBlock
,则您将可以访问服务器在新记录上设置的系统字段。 - sc0rp10n