Reputation: 1640
I've created simple entity 'CDWorkout' with one attribute 'name' inside CDModel.xcdatamodeld. Name of container in AppDelegate is also 'CDModel'. Class Codegen for 'CDWorkout' is Category/Extension. Here is code for CDWorkout class:
class CDWorkout: NSManagedObject {
class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -> CDWorkout{
let workout = CDWorkout(context: context)
workout.name = "anyName"
return workout
}
}
the createWorkout function is called from another viewController with context argument as container.viewContext
but it immediately crashes with message:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An NSManagedObject of class 'Workout_Generator.CDWorkout' must have a valid NSEntityDescription.'
What did i forget about?
Upvotes: 51
Views: 33239
Reputation: 21
In my case problem was in CLASS_NAME+Class.swift file. Issue resolved after deleting @objc(CLASS_NAME) on the top
Upvotes: 0
Reputation: 33
In the scope of "low hanging fruit" of error tracing, which was also my case, make sure the declaration of the @objc(CLASS_NAME)
matches the class name, in the file CLASS_NAME+Class.swift
Concretely:
@objc(CLASS_NAME)
public class CLASS_NAME: NSManagedObject {
I originally created the Entity with one name but refactored it. However the refactor tool didn't propose the change or I accidentally missed it.
Upvotes: 0
Reputation: 89
What fixed it for me was that I had an empty space in the name and didn't notice because of a line break. Removing it fixed the problem..
It was:
container = `NSPersistentContainer(name: "ContainerName ")`
Instead of:
container = NSPersistentContainer(name: "ContainerName")
Upvotes: 1
Reputation: 2183
For me this worked,
Adding
@objc('YourEntityClassName')
above the class declaration in 'YourEntityClassName+CoreDataClass' file.
Note: I am using this in an SPM package.
Upvotes: 0
Reputation: 1340
In my case, I had my Core Data model inside a Swift Package and had to follow this amazing guide and finally this is what did it:
I opened the model and selected the entity and in the right panel I selected the Data Model Inspector
and in the Class panel, I manually entered the Module’s name i.e. the Swift Package name.
Upvotes: 0
Reputation: 111
In AppDelegate
check persistent container name.
let container = NSPersistentContainer(name: "CoreData")
If you trying to reach nonexistent Core Data
, that may manifest as this error.
Name should be exact same as .xcdatamodeld
object in navigation menu.
Upvotes: 11
Reputation: 1422
I've got the same issue. In my case I used CoreData initialised and managed in framework wich I integrated with main app via SPM.
First, in the framework provide module name for entity by hand, by following steps:
Repeat these steps for each entity.
Second, in the framework override description
for each NSManagedObject you use in project, f.ex. you have:
public class Person: NSManagedObject {
}
override there description with String without module name, like:
public class Person: NSManagedObject {
public override var description: String {
return "Person"
}
}
Code presented above will help if you use convenience initialiser for Person (like Person(context: Context)
) which uses description
to specify Person.entity()
.
Upvotes: 4
Reputation: 1640
The issue I had was that I needed to have the Class Module set to Current Product Module for my CDWorkout Entity.
In Xcode 10 there is a drop down in the Class section of the Data Model Inspector.
Upvotes: 48
Reputation: 11123
I encountered this issue using Swift Package Manager to import a Swift Package that had a model file included as a resource. In my case setting the Module of my entity to Current Production Module
produced an incorrect value in the model file. When I used the debugger to print the model after loading the persistent container the fully qualified class name was something like Module_Module.Class
instead of the expected Module.Class
. I had to manually type the module name instead of using Current Production Module
to resolve the issue.
Upvotes: 3
Reputation: 61
For me, I forgot to add @objc(Reminder) in this below example. I wrote the NSManagedObject class programmatically.
@objc(Reminder)
public class Reminder: NSManagedObject {
}
Upvotes: 2
Reputation: 8130
One way this could happen is by trying to rename your entities. Make sure that these are the same!
Upvotes: 9
Reputation: 1198
For SwiftUI you need to also update this method from 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)
//...
}
Upvotes: 0
Reputation: 781
If you are using coreData from a static library make sure you specify the module aswell
This gives you the correct entity access MyStaticLibrary.MyManagedObject
So if your receiving warnings with this dot notation, its not looking in your module
Upvotes: 7
Reputation: 106
The mistake I made was to change the name of the entity and the generated "NSManagedObject Subclass" and not updating the name of the class. How to fix:
Upvotes: 1
Reputation: 7
it easy to answer to this question. without removed
@objc(Workout)
the solution is on documentary Core Data Programming on "Entity Name and Class Name". here in your Xcode before doing (Editor -> Create NSManagedObject SubClass) must change your class Name of Entities to add "MO", CoreData can differentiate between class Name and Entitie Name. and the
@objc(Workout)
will not be created, give us this one:
class CDWorkoutMO: NSManagedObject {
class func createWorkout(workoutInfo : Workout, in context: NSManagedObjectContext) -> CDWorkoutMO {
let workout = CDWorkoutMO(context: context)
workout.name = "anyName"
return workout
}
}
Upvotes: -1
Reputation: 688
in your file modeldataClass probably name of Class is incorrect cause before you change name something in your name class
Upvotes: 1
Reputation: 1245
In my case the same problem was in @objc modifier in auto-generated header of data-class
@objc(CachedMovie)
public class CachedMovie: NSManagedObject {
I just removed @objc(CachedMovie)
and it began to work
Upvotes: 18
Reputation: 278
I was trying out adding CoreData to existing project and I renamed things a lot. I ended up with multiple .xcdatamodeld without knowing it. The solution was removing .xcdatamodeld and generated NSManagerObject and recreating it again.
Upvotes: 0
Reputation: 2191
I came across this same error message when trying to insert/add a managed object from an extension (SiriKit). It seems to have been an issue with the namespace of the extension not matching the .xcdatamodeld
file, because I was creating the entity description using MyClass.entity()
.
The combination that worked for me was:
@objc(MyClass)
at the top of each NSManagedObject
subclasslet entity = NSEntityDescription.entity(forEntityName: "MyClass", in: context)!
Upvotes: 11
Reputation: 6732
I had similar issue in CoreData stack with NSManagedObjectModel
made from Swift
code. The issue was in wrong value for NSEntityDescription.managedObjectClassName
attribute. The Swift module
prefix was missed.
Correct setup:
let entity = NSEntityDescription()
entity.name = PostEntity.entityName // `PostEntity`
entity.managedObjectClassName = PostEntity.entityClassName // `MyFrameworkName.PostEntity`
entity.properties = [....]
Where: entityName
and entityClassName
defined like this.
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
}
}
Upvotes: 0
Reputation: 3017
I had a silly minor issue that resulted in the same error. I was initializing NSPersistentContainer with the incorrect name.
It should have the same name as the source file with the extension .xcdatamodeld. e.g. modelFileName.xcdatamodelId
let persistentContainer = NSPersistentContainer(name: "modelFileName")
Upvotes: 38