Swift ';类的NSManagedObject';类名';必须具有有效的N实体说明;错误

Swift ';类的NSManagedObject';类名';必须具有有效的N实体说明;错误,swift,core-data,Swift,Core Data,我在CDModel.xcdatamodeld中创建了一个简单实体“CDWorkout”,其中有一个属性“name”。AppDelegate中容器的名称也是“CDModel”。“CDWorkout”的类别代码为类别/扩展。以下是CD健身课程的代码: class CDWorkout: NSManagedObject { class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -&

我在CDModel.xcdatamodeld中创建了一个简单实体“CDWorkout”,其中有一个属性“name”。AppDelegate中容器的名称也是“CDModel”。“CDWorkout”的类别代码为类别/扩展。以下是CD健身课程的代码:

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”而终止应用程序,原因是:“训练生成器.CDCOUNTROUP”类的NSManagedObject必须具有有效的NSEntityDescription。”


我忘记了什么?

我遇到的问题是,我需要将我的CDO实体的类模块设置为当前产品模块


在Xcode 10中,数据模型检查器的类部分有一个下拉列表。

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

它应该与扩展名为.xcdatamodeld的源文件同名。e、 g.modelFileName.xcdatamodelId


我在coredatastack中遇到了类似的问题,它是由
Swift
代码制作的
NSManagedObjectModel
。问题在于
NSEntityDescription.managedObjectClassName
属性的值错误。缺少
Swift模块
前缀

正确设置:

let entity = NSEntityDescription()
entity.name = PostEntity.entityName // `PostEntity`
entity.managedObjectClassName = PostEntity.entityClassName // `MyFrameworkName.PostEntity`
entity.properties = [....]
其中:
entityName
entityClassName
定义如下

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
    }

}

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

对我有效的组合是:

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

我尝试将CoreData添加到现有项目中,并对其进行了多次重命名。我在不知不觉中得到了多个.xcdatamodeld。解决方案是删除.xcdatamodeld并生成NSManagerObject,然后再次重新创建它。

在我的例子中,数据类的自动生成标头中的@objc修饰符也存在同样的问题

@objc(CachedMovie)
public class CachedMovie: NSManagedObject {
我刚刚删除了objc(CachedMovie)
,它开始在您的文件modeldataClass中工作
可能类名不正确,因为在更改名称之前,名称类中的某些内容很容易回答此问题。未删除

@objc(Workout)
解决方案出现在“实体名称和类名”的纪录片中。 在您的Xcode中,然后再执行(编辑器->创建NSManagedObject子类) 必须更改实体的类名才能添加“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
}
}

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

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

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

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


因此,如果您收到带有此点符号的警告,则它不会在AppDelegate检查持久容器名称的模块中查找。 let container=NSPersistentContainer(名称:“CoreData”)

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

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


GL:)

对于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)
    //...
}

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


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

@objc(Reminder)
public class Reminder: NSManagedObject {


}

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

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

解决方案 首先,在框架中,通过以下步骤手动为实体提供模块名称:

  • open.xcdatamodel
  • 选择要编辑的实体
  • 打开数据模型检查器(右侧边栏中的第四个面板)
  • 部分,默认情况下元素模块显示当前产品模块——在此输入您的模块名称
  • 对每个实体重复这些步骤

    其次,在框架中,为您在项目中使用的每个NSManagedObject重写
    描述
    ,f.ex。你有:

    public class Person: NSManagedObject {
    
    }
    
    使用不带模块名称的字符串覆盖该描述,如:

    public class Person: NSManagedObject {
    
        public override var description: String {
            return "Person"
        }
    }
    
    如果您使用方便的Person初始化器(如public class Person: NSManagedObject { public override var description: String { return "Person" } }