【问题标题】:No NSEntityDescriptions in any model claim the NSManagedObject subclass任何模型中都没有 NSEntityDescriptions 声明 NSManagedObject 子类
【发布时间】:2018-12-09 08:48:53
【问题描述】:

我是 CoreData 的新手,我正在尝试创建一个缓存机制,其中在从 API 解析对象后,我将它们保存到数据模型中,然后再次获取它以在 tableview 上显示它。我正在尝试使用NSFetchedResultsController 获取它。在初始化 NSFetchedResultsController 时,我遇到了这个运行时异常:

2018-12-09 15:03:20.493509+0800 [5184:148001] [error] error: 
No NSEntityDescriptions in any model claim the NSManagedObject subclass 
'Product' so +entity is confused.  Have you loaded your 
NSManagedObjectModel yet ?
CoreData: error: No NSEntityDescriptions in any model claim the 
NSManagedObject subclass 'Product' so +entity is confused.  Have you 
loaded your NSManagedObjectModel yet ?
2018-12-09 15:03:20.493718+0800[5184:148001] [error] error: + 
[Product entity] Failed to find a unique match for an 
NSEntityDescription to a managed object subclass
CoreData: error: +[Product entity] Failed to find a unique match for an 
NSEntityDescription to a managed object subclass

可能是什么原因?

【问题讨论】:

  • 在创建持久化容器时是否拼错了模型名称?
  • 仔细检查,我没有拼错
  • 找到了罪魁祸首!!在实例化 fetchrequest 时,我应该使用 NSFetchRequest<Product>(entityName: "Product") 而不是 Product.fetchRequest() as! NSFetchRequest<Product>
  • tldr;初始化你的 NSManagedObjectContext。这是我在尝试调试我的 Coredata 问题时遇到的少数 stackoverflow 问题之一,所以我将把我的解决方案放在这里。在我开始删除/打印之前,我有各种方法/功能工作,这并不重要。但我最近处理的函数之间的区别在于上下文没有初始化。在分配上下文之前,我使用 fetchrequest 调用我的泛型类型 E。所以希望这对某人有所帮助。
  • 此错误的另一个原因可能是创建了一个新实体并且它的设置与其他实体不同。我指的是实体检查器中的 Module 和 Codegen 字段。

标签: ios swift


【解决方案1】:

如果您在使用 SwiftUI 时遇到过类似的问题,可以尝试将实体的类 moduleGlobal Namespace 更改为 Current Product Module.

转到您的 xcdatamodeld 文件并选择有问题的实体。然后在数据模型检查器中,通过单击字段右侧的箭头将模块字段从默认的全局命名空间更改为可用值“当前产品模块”。

这允许我的应用程序编译而不会遇到错误。

【讨论】:

    【解决方案2】:

    我的经验:

    实体类缺少类名上方的@objc(Person) 行。 我确实有更多的类在没有这条线的情况下工作,但只有在创建这个特定实体时才会出现这个错误。

    @objc(Person)
    public class Person: NSManagedObject {
    
    }
    

    【讨论】:

    • 谢谢,但是通过添加这一行,我得到了更多新的警告和错误......
    【解决方案3】:

    当我将 Core Data ModelCodegen 属性更改为键入 Category/Extension,为 Core Data Model 创建自定义类。

    正如@dypbrg所指出的,更改以下代码段

    Product.fetchRequest() 
    

    到下面的代码段

    NSFetchRequest<Product>(entityName: "Product")
    

    似乎解决了这个问题。

    【讨论】:

    • 为什么我们不能使用 Product.fetchRequest() ?
    • @MichałZiobro,它们是不同的返回类型。 Product.fetchRequest() 返回通用的 NSFetchRequest,而 NSfetchRequest(entityName: "Product") 返回 NSFetchRequest。使用as! NSFetchRequest&lt;Product&gt; 强制转换前者似乎是一个问题。
    • 今天是 2020 年的事情,这是一种可悲的状态
    • @MStrapko 但是你可以这样做let fetchRequest: NSFetchRequest&lt; Product &gt; = Product.fetchRequest() 是正确的类型
    【解决方案4】:

    在我的例子中,我更改了实体的名称和 swift-class,但忘记在 xcdatamodeld 中更新为新的 swift-class 名称。

    (在 xcdatamodel 视图中,在左侧窗格的“CONFIGURATIONS”下,选择“Default”并确保类的名称正确。)

    【讨论】:

      【解决方案5】:

      在我的例子中,我使用的是 SwiftUI,NSManagedObjectContext 在持久存储异步函数返回之前被使用。

      然后我跟着核心数据示例项目用 Xcode 解决了这个问题:

      @main
      struct TestCoreDataApp: App {
          //Inside the PersistenceController initialiser the store is loaded, so gives it time before passing the context to the SwiftUI View
          let persistenceController = PersistenceController.shared
      
          var body: some Scene {
              WindowGroup {
                  ContentView()
                      .environment(\.managedObjectContext, persistenceController.container.viewContext)
              }
          }
      }
      

      【讨论】:

      • 这正是我的问题。我试图初始化容器并像.environment(\.managedObjectContext, PersistenceController.shared.container.viewContext) 这样一步传递上下文。没想到在struct中实例化控制器会有这么大的效果。
      • 是的,标准的核心数据 Xcode 模板项目提供了一个示例项目,它清楚地说明了如何将核心数据与 SwiftUI 一起使用。
      • @OliverD,如果您的目标是iOS 15及以上,现在您可以像使用它一样直接使用它。参考developer.apple.com/wwdc21/10017 (18:16)
      【解决方案6】:

      适用于在混合项目(Obj-C + Swift)中遇到此问题的任何人。

      在我的例子中,CoreData xcdatamodel 作为 SPM 包内的资产交付并在此包内使用。使用 Swift 项目没有问题,但使用混合项目时我遇到了同样的问题。

      解决我的问题的解决方案:

      1. 对@Sam 提到的NSManagedObjects 使用@objc 注释

         @objc(Entity) 
         public class Entity: NSManagedObject {
        
         }
        
      2. 为每个实体使用全局命名空间而不是当前产品模块(查看@Pomme2Poule 的回答如何做到这一点)

      【讨论】:

        【解决方案7】:

        对我来说,我没有将 AppDelegate 中的 NSPersistentContainer 命名为与我创建的 xcdatamodelId 相同。

        let container = NSPersistentContainer(name: "DataModel")
        

        【讨论】:

          【解决方案8】:

          我也遇到了同样的问题,最后在persistentContainerlazy initilaize 找到了根本原因。

          在 AppDelegate.swift 中,删除 lazy 对我有用。

          // MARK: - Core Data stack
          
              lazy var persistentContainer: NSPersistentCloudKitContainer = {...}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-01-21
            • 1970-01-01
            • 2022-12-31
            • 2017-03-12
            • 2018-03-28
            • 1970-01-01
            • 2016-03-07
            相关资源
            最近更新 更多