Reputation: 668
I'm using the Swift boilerplate code for Core Data in a fresh project. My .xcdatamodeld
file has a single entity defined (Task
) with a single attribute (name
).
I have a Task.swift
file that looks like this:
import CoreData
class Task: NSManagedObject {
@NSManaged var name: String
}
When I run this, it works:
var firstTask = NSEntityDescription.insertNewObjectForEntityForName("Task",
inManagedObjectContext: managedObjectContext) as NSManagedObject
firstTask.setPrimitiveValue("File my TPS reports", forKey: "name")
var error: NSError?
managedObjectContext.save(&error)
I can even go into the SQLite database being used by the iOS simulator and confirm that the row was added.
However, when I run the exact same code as above but with as Task
instead of as NSManagedObject
, I get a crash with the error message Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
, associated with the var firstTask
… line. If I continue execution, I get EXC_BAD_ACCESS
and 0 misaligned_stack_error_
at the top of Thread 1 each time I advance it.
Why might this cast lead to all this?
Upvotes: 38
Views: 20376
Reputation: 1
This blog helped me! I implemented this for unit test btw.
I still don't know why I had to do this though...
guard let entity = NSEntityDescription.entity(forEntityName: "Task", in: context) else {
XCTFail("❌ Failed to create entity")
return
}
let task = Task(entity: entity, insertInto: context) // This is Task type.
https://developer.apple.com/documentation/coredata/nsentitydescription/1425111-entity
Env: Xcode 16.2
Upvotes: 0
Reputation: 6335
Xcode 7 + Swift 2
Person.swift
@objc(Person)
class Person: NSManagedObject {
}
Data model
Then simply call
let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: self.managedObjectContext) as! Person
Upvotes: 4
Reputation: 1584
An update for @Ben Gottlieb answer under XCode 7.1 and Swift 2.0
@objc class ImageRecordMO: NSManagedObject{
Open your .xcdatamodled file.
Select your entity and click the data model inspector on the right panel.
Enter the class name, see the figure below
Select your module to be Current Product Module, see the figure below.
Upvotes: 5
Reputation: 2519
This is even frustrated if you tried all the above suggestions and non of them working for me!!
So this is what works for me.
1- Select your xcdatamodeld file
2- Make sure that all your entities has No Module in the "Data Model Inspector", if you see "Model: Current Product Module" ..clear it it so it looks like the attached image.
3- Delete your App to clear core data
4- If still not working, delete your entities and regenerate them.
Upvotes: 31
Reputation: 21
I had to add the @objc() and set the class in the coredata interface. In the CoreData right window, in the Entity area, there are Name and Class textbox. Class must not be MSManagedObject but instead your class. I created a simple working example!
Upvotes: 2
Reputation: 4963
I've run into this problem in the last few days and strangely the solution that worked for me was a variant of that suggested above.
I added the @objc declaration to the generated subclasses, but removed any namespace prefix in the class name in the object model (it had a default prefix of "PRODUCT_MODULE_NAME." after the subclasses were generated). That worked.
Upvotes: 1
Reputation: 743
I guess only changing the class field in the .xcdatamodel doesn't work anymore because I still got the following exception: fatal error: use of unimplemented initializer 'init(entity:insertIntoManagedObjectContext:)' for class
So, I entered this code in my custom class:
init(entity: NSEntityDescription!,
insertIntoManagedObjectContext context: NSManagedObjectContext!) {
super.init(entity: entity, insertIntoManagedObjectContext: context)
}
Suddenly, it worked! The NSManagedObject is now down-castable to my custom class. I can't really understand why this is the solution, but it works :)
Upvotes: 7
Reputation: 3355
You need to modify your Task.swift file. Adding @objc(Task) like below
import CoreData
@objc(Task)
class Task: NSManagedObject {
@NSManaged var name: String
}
I think this as a bug if your project does not contain any objective-c codes. However, you need to add that line until this fixed.
I learned it from here.
Upvotes: 11
Reputation: 85522
Make sure your Class name field is actually Module.Task, where Module is the name of your app. CoreData classes in Swift are namespaced. Right now, your object is being pulled out of the context as an NSManagedObject, not as a Task, so the as-cast is failing.
Upvotes: 50