【问题标题】:How to save a dictionary (or any other complex structure) into iCloud using Cloudkit?如何使用 Cloudkit 将字典(或任何其他复杂结构)保存到 iCloud 中?
【发布时间】:2020-08-20 13:07:16
【问题描述】:
我需要将日期绑定到一个值并将其保存到 Cloudkit。与其为每个对象和下标“日期”和“值”保存一个新的CKRecord,我更希望CKRecord 是一个字典数组:[(日期,值)]。我环顾四周,找不到这种类型的 Cloudkit 数据存储的任何示例。到目前为止,我本以为 Codable 会被桥接到 Cloudkit,但我没有看到任何迹象表明这一点。有一个library 可以处理这个问题,但它不处理这种类型的嵌套。有没有办法做到这一点?
【问题讨论】:
标签:
ios
swift
icloud
cloudkit
ckrecord
【解决方案1】:
虽然CKRecord 确实能够支持Array,但它主要用于存储简单的数据类型,如字符串、数字和CKRecord.Reference。您没有特别指出您的“值”类型是什么,但这里有一个使用JSONEncoder/JSONDecoder 将支持写入/读取任何可编码类型到CKRecord 的示例。编码器/解码器只是简单地将Encodable/Decodable 类型转换为/从二进制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]]