首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可编码为CKRecord

可编码为CKRecord
EN

Stack Overflow用户
提问于 2017-12-23 09:07:21
回答 2查看 1.4K关注 0票数 8

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

我为Encodable提供了一个创建字典的扩展:

代码语言:javascript
复制
extension Encodable {

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

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

代码语言:javascript
复制
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
}

解码:

代码语言:javascript
复制
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。提前谢谢你。

EN

回答 2

Stack Overflow用户

发布于 2018-06-11 07:37:39

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

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

代码语言:javascript
复制
/// 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
}

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

票数 1
EN

Stack Overflow用户

发布于 2019-07-11 16:14:07

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47948924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档