Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How come I can cast to NSManagedObject but not to my entity's type?

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?

like image 618
William Proffitt Avatar asked Jun 11 '14 03:06

William Proffitt


4 Answers

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.

like image 175
Ben Gottlieb Avatar answered Nov 16 '22 01:11

Ben Gottlieb


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.

enter image description here

like image 31
polarware Avatar answered Nov 15 '22 23:11

polarware


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.

Youtube video at 11:45

like image 11
Owen Zhao Avatar answered Nov 16 '22 01:11

Owen Zhao


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 :)

like image 7
Jovan Jovanovski Avatar answered Nov 16 '22 01:11

Jovan Jovanovski