核心数据 NSManagedObject 到 JSON 编码不起作用

Posted

技术标签:

【中文标题】核心数据 NSManagedObject 到 JSON 编码不起作用【英文标题】:CoreData NSManagedObject & JSON Encodable not working 【发布时间】:2019-10-04 12:22:00 【问题描述】:

我正在尝试在 ios 13.1.2 和 Swift 4.2 上创建一个对象类,它既是符合 EncodableNSManagedObject 的类。这是我的课:

import CoreData

class Test: NSManagedObject, Decodable 
    @NSManaged var name: String?

    enum CodingKeys: String, CodingKey 
        case name
    

    required convenience init(from decoder: Decoder) throws 
        let managedContext = AppDelegate.persistentContainer.viewContext

        guard let entity = NSEntityDescription.entity(forEntityName: "TestEntity", in: managedContext) else  fatalError() 

        self.init(entity: entity, insertInto: managedContext)

        let values = try decoder.container(keyedBy: CodingKeys.self)
        name = try values.decodeIfPresent(String.self, forKey: .name)
    

我的数据模型:

还有我在 AppDelegate 中的 persistentContainer:

static var persistentContainer: NSPersistentContainer = 
    let container = NSPersistentContainer(name: "testContainer")
    container.loadPersistentStores(completionHandler:  (storeDescription, error) in
        if let error = error as NSError? 
            fatalError("Unresolved error \(error), \(error.userInfo)")
        
    )
    return container
()

我使用此方法创建Test 类的新实例:

do 
    let test = try JSONDecoder().decode(Test.self, from: "\"name\":\"Test\"".data(using: .utf8)!)
    print(test.name)
 catch let error 
    print(error)

但这给了我以下错误:

valueNotFound(Test.Test, Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value.", underlyingError: nil))

我在这里做错了什么?

【问题讨论】:

嘿!你是如何解决这个问题的? 我也遇到了同样的问题 【参考方案1】:

我终于让它工作了。这发生在我身上,因为我使用了一个符合 NSManagedObject 和 Decodable 的单独模型,就像 OP 的 Test 类一样。答案here 让我成功了,但我缺少的是,我必须修改生成的实体类以符合 Decodable 并将其用作我的可编码模型,而不是使用单独的模型。

因此,在将 Codegen 更改为 Manual 并创建 NSManagedObject 类(如上面提到的链接)后,您在文件 Test+CoreDataClass.swift 中的类变为:

import CoreData

@objc(Test)
public class Test: NSManagedObject, Decodable 
    @NSManaged var name: String?

    enum CodingKeys: String, CodingKey 
        case name
    

    required convenience init(from decoder: Decoder) throws 
        let managedContext = AppDelegate.persistentContainer.viewContext

        guard let entity = NSEntityDescription.entity(forEntityName: "TestEntity", in: managedContext) else  fatalError() 

        self.init(entity: entity, insertInto: managedContext)

        let values = try decoder.container(keyedBy: CodingKeys.self)
        name = try values.decodeIfPresent(String.self, forKey: .name)
    

【讨论】:

【参考方案2】:

当您使用“新建文件...”手动添加子类时,可能会发生这种情况。

要将子类添加为项目中的可编辑类文件,而不是自己添加,请执行以下操作:

    打开数据模型文件 在实体下,选择相关实体 在 Data model Inspector 中,确保“Codegen”设置为“Manual” 从上方菜单中,选择Editor -> Create NSManagedObject subclass...

【讨论】:

以上是关于核心数据 NSManagedObject 到 JSON 编码不起作用的主要内容,如果未能解决你的问题,请参考以下文章

将更改 NSManagedObject 保存到核心数据失败

将 NSManagedObject 更新为核心数据

如何在不复制目标 NSManagedObject 的情况下将目标 NSManagedObject 添加到另一个具有反向多对多核心数据关系的对象?

核心数据:更新 NSManagedObject 并选择回退到原始状态

ios核心数据:如何更改NSManagedObject而不将其保存到上下文中

Xcode 和核心数据 - “创建 NSManagedObject 子类”