您可以将 Codable 接口与 CoreData 对象一起使用来编码和解码数据,但是它不像与普通的旧 swift 对象一起使用时那样自动。以下是您可以使用 Core Data 对象直接实现 JSON 解码的方法:
首先,你让你的对象实现 Codable。此接口必须在对象上定义,而不是在扩展中。您还可以在此类中定义您的编码键。
class MyManagedObject: NSManagedObject, Codable {
@NSManaged var property: String?
enum CodingKeys: String, CodingKey {
case property = "json_key"
}
}
接下来,您可以定义 init 方法。这也必须在类方法中定义,因为可解码协议需要 init 方法。
required convenience init(from decoder: Decoder) throws {
}
但是,与托管对象一起使用的正确初始化程序是:
NSManagedObject.init(entity: NSEntityDescription, into context: NSManagedObjectContext)
因此,这里的秘诀是使用userInfo字典将正确的上下文对象传递给初始化程序。为此,您需要CodingUserInfoKey
使用新键扩展结构:
extension CodingUserInfoKey {
static let context = CodingUserInfoKey(rawValue: "context")
}
现在,您可以作为上下文的解码器:
required convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext else { fatalError() }
guard let entity = NSEntityDescription.entity(forEntityName: "MyManagedObject", in: context) else { fatalError() }
self.init(entity: entity, in: context)
let container = decoder.container(keyedBy: CodingKeys.self)
self.property = container.decodeIfPresent(String.self, forKey: .property)
}
现在,当您为托管对象设置解码时,您需要传递正确的上下文对象:
let data = //raw json data in Data object
let context = persistentContainer.newBackgroundContext()
let decoder = JSONDecoder()
decoder.userInfo[.context] = context
_ = try decoder.decode(MyManagedObject.self, from: data) //we'll get the value from another context using a fetch request later...
try context.save() //make sure to save your data once decoding is complete
要对数据进行编码,您需要使用编码协议功能执行类似的操作。