将CoreData属性存储为(Codable)数据而不是(NSCoding)Transformables

时间:2018-04-14 19:17:38

标签: swift core-data nscoding codable

我有简单结构的数组,我想将其打包到Core Data属性中。我不需要Core Data独立处理每个对象,因此在一个属性上打包到数组似乎很好,开销也更少。

完整的解决方案可能是推出自己的NSValueTransformer。我可以完全控制进程和存储。但是,将更多工作放在一边,因为Swift 4现在我们实际上有另一种方法来开箱即用的序列化 - 将对象存储为Data属性,由Swift 4的序列化{{1协议和(比方说)Codable / JSONEncoder实现。这将是使用通过JSONDecoder下的默认NSValueTransformer序列化的Transformable属性的更典型方法的替代方法。

一个直接的优势是不必从NSCoding继承并符合NSObject,因为在我的例子中是简单的值类型。仅这一点让我想开始使用NSCoding作为我的默认方法。显然,使用JSON编码器意味着在Codable下转换和表示数据,即使Core Data / sqlite将其视为utf8 / BLOB。然而,根据我收集的内容,默认转换器到(二进制)plist格式也不是最有效的。

是否有其他人采用这种方法或以其他方式知道是否可能存在任何重大缺陷或影响而我未考虑过?简而言之,这可能是一种合理的方法吗?

1 个答案:

答案 0 :(得分:1)

我不知道您是否仍在寻找解决此问题的方法,但这是我使用的解决方案的概述。假设aStruct: Codable,您可以使用此策略。

在核心数据模型中,我为所需实体创建了诸如类型数据的encodedStructArray之类的属性。

然后在该实体的swift扩展中,我创建一个具有普通swift类型的计算式读写var:

    var structArray: [aStruct] {
        get {
            guard let data = encodedStructArray else { return [] }
            guard let result = try? JSONDecoder().decode([aStruct].self, from: data) else { return [] }
            return result
        }
        set {
            encodedStructArray = try? JSONEncoder().encode(newValue)
        }
    }

现在,您可以像在任何地方使用var一样,但是出于性能方面的考虑,将其拉出并使用它,而不是直接在多个位置使用var,因为此示例不会缓存该值。

如果希望缓存结果,则需要向数据模型添加一个瞬态,其名称为structArray,且类型未定义,并将缓存值保留在其原语中。有关示例,请参见Core Data文档。