您可以使用CoreData对象的可编码接口对数据进行编码和解码,但它不像普通的旧swift对象那样自动.下面是如何直接用核心数据对象实现JSON解码:
首先,使对象实现可编码.此接口必须在对象上定义,而不是在扩展中定义.您还可以在此类中定义编码键.
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
struct :
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
要对数据进行编码,需要使用encode协议函数执行类似的操作.