gpt4 book ai didi

swift - 如何在核心数据中使用 swift 4 Codable?

转载 作者:行者123 更新时间:2023-11-28 07:23:27 31 4
gpt4 key购买 nike

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

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

enter image description here

并自己定义了 Foo:

import CoreData

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

但是这样使用时:

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)

编译器因以下错误而失败:

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

目标文件是定义Foo

的文件

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

Core Data 是否支持Codable

最佳答案

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

首先,让您的对象实现 Codable。此接口(interface)必须在对象上定义,而不是在扩展中定义。您还可以在此类中定义您的编码键。

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

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

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

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

但是,用于托管对象的正确初始化程序是:

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

所以,这里的秘诀是使用 userInfo 字典将正确的上下文对象传递到初始化程序中。为此,您需要使用新 key 扩展 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

要对数据进行编码,您需要使用编码 协议(protocol)函数执行类似的操作。

关于swift - 如何在核心数据中使用 swift 4 Codable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57309098/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com