如何使用 Cloudkit 将字典(或任何其他复杂结构)保存到 iCloud 中?
How to save a dictionary (or any other complex structure) into iCloud using Cloudkit?
我需要将日期绑定到一个值并将其保存到 Cloudkit。与其为每个对象和下标“date”和“value”保存一个新的 CKRecord
,我更希望 CKRecord
是一个字典数组:[(date, value)]。我环顾四周,找不到任何此类 Cloudkit 数据存储的示例。我本以为 Codable 会被桥接到 Cloudkit 但我没有看到任何迹象表明这一点。有一个 library 可以处理这个,但它不处理这种类型的嵌套。有办法吗?
尽管 CKRecord
确实能够支持 Array
,但它主要用于存储简单的数据类型,例如字符串、数字和 CKRecord.Reference
。您没有具体指出您的 'value' 类型是什么,但这是一个使用 JSONEncoder
/JSONDecoder
将对 writing/reading 任何可编码类型的支持添加到 CKRecord
。 encoder/decoder 只是将 Encodable
/Decodable
类型 to/from 转换为二进制 Data
表示,CKRecord
也支持。
private let encoder: JSONEncoder = .init()
private let decoder: JSONDecoder = .init()
extension CKRecord {
func decode<T>(forKey key: FieldKey) throws -> T where T: Decodable {
guard let data = self[key] as? Data else {
throw CocoaError(.coderValueNotFound)
}
return try decoder.decode(T.self, from: data)
}
func encode<T>(_ encodable: T, forKey key: FieldKey) throws where T: Encodable {
self[key] = try encoder.encode(collection)
}
}
用法如下所示:
let collection: [[Date: String]] = [[:]]
let record = CKRecord(recordType: "MyRecord")
try? record.encode(collection, forKey: "collection")
let persisted = try? record.decode(forKey: "collection") as [[Date: String]]
我需要将日期绑定到一个值并将其保存到 Cloudkit。与其为每个对象和下标“date”和“value”保存一个新的 CKRecord
,我更希望 CKRecord
是一个字典数组:[(date, value)]。我环顾四周,找不到任何此类 Cloudkit 数据存储的示例。我本以为 Codable 会被桥接到 Cloudkit 但我没有看到任何迹象表明这一点。有一个 library 可以处理这个,但它不处理这种类型的嵌套。有办法吗?
尽管 CKRecord
确实能够支持 Array
,但它主要用于存储简单的数据类型,例如字符串、数字和 CKRecord.Reference
。您没有具体指出您的 'value' 类型是什么,但这是一个使用 JSONEncoder
/JSONDecoder
将对 writing/reading 任何可编码类型的支持添加到 CKRecord
。 encoder/decoder 只是将 Encodable
/Decodable
类型 to/from 转换为二进制 Data
表示,CKRecord
也支持。
private let encoder: JSONEncoder = .init()
private let decoder: JSONDecoder = .init()
extension CKRecord {
func decode<T>(forKey key: FieldKey) throws -> T where T: Decodable {
guard let data = self[key] as? Data else {
throw CocoaError(.coderValueNotFound)
}
return try decoder.decode(T.self, from: data)
}
func encode<T>(_ encodable: T, forKey key: FieldKey) throws where T: Encodable {
self[key] = try encoder.encode(collection)
}
}
用法如下所示:
let collection: [[Date: String]] = [[:]]
let record = CKRecord(recordType: "MyRecord")
try? record.encode(collection, forKey: "collection")
let persisted = try? record.decode(forKey: "collection") as [[Date: String]]