【问题标题】:'An NSManagedObject of class 'className' must have a valid NSEntityDescription.' error'类 'className' 的 NSManagedObject 必须具有有效的 NSEntityDescription。'错误
【发布时间】:2018-01-08 03:04:03
【问题描述】:

我在 CDModel.xcdatamodeld 中创建了具有一个属性“名称”的简单实体“CDWorkout”。 AppDelegate 中的容器名称也是“CDModel”。 'CDWorkout' 的类 Codegen 是类别/扩展。这是 CDWorkout 类的代码:

class CDWorkout: NSManagedObject {

    class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -> CDWorkout{
        let workout = CDWorkout(context: context)
        workout.name = "anyName"
        return workout
    }
}

createWorkout 函数从另一个 viewController 调用,上下文参数为 container.viewContext,但它立即崩溃并显示消息:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“类“Workout_Generator.CDWorkout”的 NSManagedObject 必须具有有效的 NSEntityDescription。”

我忘记了什么?

【问题讨论】:

  • 如果我们构建 SPM 然后 Class Module 设置为空

标签: swift core-data


【解决方案1】:

我遇到的问题是我需要为我的 CDWorkout 实体将 Class Module 设置为 Current Product Module

在 Xcode 10 中,Data Model Inspector 的 Class 部分有一个下拉菜单。

【讨论】:

  • 对于那些寻找这个的人,在 Xcode 10 中,它是数据模型检查器的类部分中的一个下拉菜单。 (选择您的 xcdatamodeld 文件)
【解决方案2】:

我遇到了一个愚蠢的小问题,导致了同样的错误。我用不正确的名称初始化 NSPersistentContainer。

它应该与扩展名为.xcdatamodeld的源文件同名。例如modelFileName.xcdatamodelId

let persistentContainer = NSPersistentContainer(name: "modelFileName")

【讨论】:

    【解决方案3】:

    在我的情况下,同样的问题出现在自动生成的数据类标头中的 @objc 修饰符中

    @objc(CachedMovie)
    public class CachedMovie: NSManagedObject {
    

    我刚刚删除了@objc(CachedMovie),它开始工作了

    【讨论】:

    • 是的,这是真的,最好不要问为什么
    • 它不允许我从自动生成的文件中删除 @objc 注释..
    【解决方案4】:

    我在尝试从扩展 (SiriKit) 插入/添加托管对象时遇到了同样的错误消息。扩展名的命名空间与.xcdatamodeld 文件不匹配似乎是一个问题,因为我正在使用MyClass.entity() 创建实体描述。

    对我有用的组合是:

    • @objc(MyClass) 在每个 NSManagedObject 子类的顶部
    • 数据模型中的实体使用默认的“全局命名空间”,而不是“当前产品模块”
    • 使用let entity = NSEntityDescription.entity(forEntityName: "MyClass", in: context)! 创建实体描述

    【讨论】:

    • 我在这里有点密集-对于我的模型,我只有一个选项-空白和“当前产品模块”-您引用的“全局命名空间”是空白吗?同样对于实体描述 - 如何创建实体描述?我是否只是在创建托管对象的实例后添加该代码? IE。在这段代码之后? var newSavedModel = SomeEntity(context: managedContext)
    • @TheJeff 对不起,但我不完全确定,我已经有几年没有接触过这种东西了。我猜这个空白与“全局命名空间”相同。我在上面创建的实体描述应该传递到 NSManagedObject(entity:insertInto:) 的初始化程序中,正如 here 所讨论的那样。
    【解决方案5】:

    在 AppDelegate 中检查持久化容器名称。 让容器 = NSPersistentContainer(name: "CoreData")

    如果您尝试访问不存在的核心数据,则可能会出现此错误。

    名称应与导航菜单中的 .xcdatamodeld 对象完全相同。

    GL :)

    【讨论】:

      【解决方案6】:

      如果您使用的是静态库中的 coreData,请确保同时指定模块

      这为您提供了正确的实体访问权限MyStaticLibrary.MyManagedObject

      因此,如果您收到带有此点符号的警告,则它不会在您的模块中查找

      【讨论】:

        【解决方案7】:

        可能发生这种情况的一种方法是尝试重命名您的实体。确保它们相同!

        【讨论】:

        • 是的,这就是问题所在。只是不在我正在寻找的对象上。在正确的对象上检查。如果您有 EventDay 和 EventTime,请尝试在 Core Data 模型中排列您正在调查的对象..
        【解决方案8】:

        对我来说,我忘记在下面的示例中添加 @objc(Reminder)。我以编程方式编写了 NSManagedObject 类。

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

        【讨论】:

          【解决方案9】:

          我在使用 Swift 包管理器导入一个包含模型文件作为资源的 Swift 包时遇到了这个问题。在我的情况下,将我的实体的模块设置为 Current Production Module 在模型文件中产生了不正确的值。当我在加载持久化容器后使用调试器打印模型时,完全限定的类名类似于Module_Module.Class,而不是预期的Module.Class。我不得不手动输入模块名称而不是使用Current Production Module 来解决问题。

          【讨论】:

            【解决方案10】:

            我也有同样的问题。在我的例子中,我使用了在框架中初始化和管理的 CoreData,我通过 SPM 与主应用程序集成。

            解决方案

            首先,在框架中手动为实体提供模块名称,步骤如下:

            1. 打开 .xcdatamodel,
            2. 选择要编辑的实体,
            3. 打开Data Model Inspector(右侧边栏中的第四个面板),
            4. Class 元素模块默认显示 Current Product Module -- 在此处输入您的模块名称

            对每个实体重复这些步骤。

            其次,在框架中为您在项目 f.ex 中使用的每个 NSManagedObject 覆盖 description。你有:

            public class Person: NSManagedObject {
            
            }
            

            用不带模块名称的字符串覆盖那里的描述,例如:

            public class Person: NSManagedObject {
            
                public override var description: String {
                    return "Person"
                }
            }
            

            如果您使用便利的 Person 初始化程序(如 Person(context: Context)),上面介绍的代码将有所帮助,它使用 description 指定 Person.entity()

            【讨论】:

            • 对于那些阅读这个答案的人来说,SPM 是 Swift 包管理器。我已经尝试过了,并且不需要描述代码就可以像魅力一样工作。谢谢。
            【解决方案11】:

            在你的文件modeldataClass中 在您更改名称类中的某些内容之前,可能类的名称不正确

            【讨论】:

              【解决方案12】:

              我犯的错误是更改实体的名称和生成的“NSManagedObject 子类”,而不是更新类的名称。如何解决:

              • 打开 .xcdatamodeld
              • 点击实体
              • 打开右侧面板
              • 转到数据模型检查器
              • 更改类文本字段的名称

              【讨论】:

                【解决方案13】:

                我在 CoreData 堆栈中遇到了类似的问题,NSManagedObjectModelSwift 代码制成。问题在于NSEntityDescription.managedObjectClassName 属性的值错误Swift module 前缀丢失。

                正确设置:

                let entity = NSEntityDescription()
                entity.name = PostEntity.entityName // `PostEntity`
                entity.managedObjectClassName = PostEntity.entityClassName // `MyFrameworkName.PostEntity`
                entity.properties = [....]
                

                其中:entityNameentityClassName 定义如下。

                extension NSManagedObject {
                
                    public static var entityName: String {
                        let className = NSStringFromClass(self) // As alternative can be used `self.description()` or `String(describing: self)`
                        let entityName = className.components(separatedBy: ".").last!
                        return entityName
                    }
                
                    public static var entityClassName: String {
                        let className = NSStringFromClass(self)
                        return className
                    }
                
                }
                

                【讨论】:

                  【解决方案14】:

                  我正在尝试将 CoreData 添加到现有项目中,并且我重命名了很多东西。我在不知不觉中得到了多个 .xcdatamodeld 。解决方案是删除 .xcdatamodeld 并生成 NSManagerObject 并重新创建它。

                  【讨论】:

                    【解决方案15】:

                    这个问题很容易回答。没有删除

                    @objc(Workout)
                    

                    解决方案在“实体名称和类名称”的纪录片Core Data Programming 中。 在你做之前在你的 Xcode 中 (Editor -> Create NSManagedObject SubClass) 必须更改您的实体类名称以添加“MO”,CoreData 可以区分类名称和实体名称。和

                    @objc(Workout) 
                    

                    不会被创建,给我们这个:

                    class CDWorkoutMO: NSManagedObject {
                    
                     class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -> CDWorkoutMO {
                        let workout = CDWorkoutMO(context: context)
                        workout.name = "anyName"
                        return workout
                    }
                    }
                    

                    like I do on my Xcode

                    【讨论】:

                      【解决方案16】:

                      对于 SwiftUI,您还需要从 SceneDelegate 更新此方法:

                      func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
                          //This gets the context from AppDelegate and sets is as moc environment variable
                          let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
                          let contentView = ContentView().environment(\.managedObjectContext, context)
                          //...
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2018-12-06
                        • 1970-01-01
                        • 1970-01-01
                        • 2021-03-28
                        • 2021-10-02
                        • 1970-01-01
                        • 1970-01-01
                        • 2023-03-24
                        相关资源
                        最近更新 更多