可编码为 CKRecord

Posted

技术标签:

【中文标题】可编码为 CKRecord【英文标题】:Codable to CKRecord 【发布时间】:2017-12-23 01:07:20 【问题描述】:

我有几个可编码的结构,我想创建一个通用协议来将它们编码为 CloudKit 的 CKRecord 并解码回来。

我有一个 Encodable 扩展来创建字典:

extension Encodable 

    var dictionary: [String: Any] 
        return (try? JSONSerialization.jsonObject(with: JSONEncoder().encode(self), options: .allowFragments)) as? [String: Any] ?? [:]
    

然后在协议扩展中,我将记录创建为属性,如果类型是数据,我尝试创建 CKAsset。

var ckEncoded: CKRecord? 

    // Convert self.id to CKRecord.name (CKRecordID)
    guard let idString = self.id?.uuidString else  return nil 
    let record = CKRecord(recordType: Self.entityType.rawValue,
                          recordID: CKRecordID(recordName: idString))

    self.dictionary.forEach 

        if let data = $0.value as? Data 
            if let asset: CKAsset = try? ckAsset(from: data, id: idString)  record[$0.key] = asset 
         else 
            record[$0.key] = $0.value as? CKRecordValue
        
    

    return record

解码:

func decode(_ ckRecord: CKRecord) throws 

    let keyIntersection = Set(self.dtoEncoded.dictionary.keys).intersection(ckRecord.allKeys())
    var dictionary: [String: Any?] = [:]

    keyIntersection.forEach 

        if let asset = ckRecord[$0] as? CKAsset 
            dictionary[$0] = try? self.data(from: asset)
         else 
            dictionary[$0] = ckRecord[$0]
        
    

    guard let data = try? JSONSerialization.data(withJSONObject: dictionary) else  throw Errors.LocalData.isCorrupted 
    guard let dto = try? JSONDecoder().decode(self.DTO, from: data) else  throw  Errors.LocalData.isCorrupted 


    do  try decode(dto) 
    catch  throw error 
 

除了数据类型外,一切都可以正常工作。它无法从字典中识别出来。所以,我无法将其转换为 CKAsset。提前谢谢你。

【问题讨论】:

【参考方案1】:

到目前为止,我还发现 Apple 对此没有明确的支持。

我的解决方案是手动编码/解码:在我的 Codable 子类中,我添加了两种方法:

/// Returns CKRecord
func ckRecord() -> CKRecord 
    let record = CKRecord(recordType: "MyClassType")
    record["title"] = title as CKRecordValue
    record["color"] = color as CKRecordValue
    return record



init(withRecord record: CKRecord) 
    title = record["title"] as? String ?? ""
    color = record["color"] as? String ?? kDefaultColor

对于更复杂情况的另一种解决方案是使用一些 3rd 方库,我遇到的一个是:https://github.com/insidegui/CloudKitCodable

【讨论】:

【参考方案2】:

所以我也遇到了这个问题,并且对任何解决方案都不满意。然后我发现这有点帮助,虽然https://github.com/ggirotto/NestedCloudkitCodable 不能很好地处理部分解码

【讨论】:

以上是关于可编码为 CKRecord的主要内容,如果未能解决你的问题,请参考以下文章

NSCoding 到 CKRecord

生成具有 CoreData 等属性的 CKRecord 类

Swift:如何将可编码类型作为函数输入传递给编码或解码 json

将可编码结构编码为 Alamofire POST 参数 - Swift

如何在可编码结构中使用计算属性(swift)

C# Unicode字符集批量转码为汉字(互转)