如何在 Core Data 中使用 swift 4 Codable? [英] How to use swift 4 Codable in Core Data?

查看:36
本文介绍了如何在 Core Data 中使用 swift 4 Codable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Codable 似乎是一个非常令人兴奋的功能.但我想知道我们如何在 Core Data 中使用它?特别是,是否可以直接从/向 NSManagedObject 编码/解码 JSON?

Codable seems a very exciting feature. But I wonder how we can use it in Core Data? In particular, is it possible to directly encode/decode a JSON from/to a NSManagedObject?

我尝试了一个非常简单的例子:

I tried a very simple example:

并自己定义了Foo:

import CoreData

@objc(Foo)
public class Foo: NSManagedObject, Codable {}

但是当像这样使用它时:

But when using it like this:

let json = """
{
    "name": "foo",
    "bars": [{
        "name": "bar1",
    }], [{
        "name": "bar2"
    }]
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let foo = try! decoder.decode(Foo.self, from: json)
print(foo)

编译器因这个错误而失败:

The compiler failed with this errror:

super.init isn't called on all paths before returning from initializer

目标文件是定义了Foo

我想我可能做错了,因为我什至没有传递 NSManagedObjectContext,但我不知道把它贴在哪里.

I guess I probably did it wrong, since I didn't even pass a NSManagedObjectContext, but I have no idea where to stick it.

Core Data 是否支持 Codable?

Does Core Data support Codable?

推荐答案

您可以将 Codable 接口与 CoreData 对象一起使用来编码和解码数据,但是它不像与普通的旧 swift 对象一起使用时那样自动.以下是直接使用 Core Data 对象实现 JSON 解码的方法:

You can use the Codable interface with CoreData objects to encode and decode data, however it's not as automatic as when used with plain old swift objects. Here's how you can implement JSON Decoding directly with Core Data objects:

首先,让对象实现 Codable.此接口必须在对象上定义,而不是在扩展中定义.你也可以在这个类中定义你的编码键.

First, you make your object implement Codable. This interface must be defined on the object, and not in an extension. You can also define your Coding Keys in this class.

class MyManagedObject: NSManagedObject, Codable {
    @NSManaged var property: String?

    enum CodingKeys: String, CodingKey {
       case property = "json_key"
    }
}

接下来,您可以定义 init 方法.这也必须在类方法中定义,因为Decodable协议需要init方法.

Next, you can define the init method. This must also be defined in the class method because the init method is required by the Decodable protocol.

required convenience init(from decoder: Decoder) throws {
}

但是,与托管对象一起使用的正确初始化程序是:

However, the proper initializer for use with managed objects is:

NSManagedObject.init(entity: NSEntityDescription, into context: NSManagedObjectContext)

所以,这里的秘诀是使用 userInfo 字典将正确的上下文对象传递给初始化程序.为此,您需要使用新密钥扩展 CodingUserInfoKey 结构:

So, the secret here is to use the userInfo dictionary to pass in the proper context object into the initializer. To do this, you'll need to extend the CodingUserInfoKey struct with a new key:

extension CodingUserInfoKey {
   static let context = CodingUserInfoKey(rawValue: "context")
}

现在,您可以作为上下文的解码器:

Now, you can just as the decoder for the 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)
}

现在,当您为托管对象设置解码时,您需要传递正确的上下文对象:

Now, when you set up the decoding for Managed Objects, you'll need to pass along the proper context object:

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 协议函数执行类似的操作.

To encode data, you'll need to do something similar using the encode protocol function.

这篇关于如何在 Core Data 中使用 swift 4 Codable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆