37

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?

Jano
  • 60,366
  • 20
  • 152
  • 174
William Proffitt
  • 633
  • 2
  • 6
  • 12

8 Answers8

48

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.

Ben Gottlieb
  • 84,498
  • 22
  • 171
  • 170
  • Thanks for the suggestion Ben. I just tried changing it to `as AppName.Task` and I seem to be getting the same behavior. Any other ideas? Perhaps you meant something else? – William Proffitt Jun 11 '14 at 03:38
  • 4
    Nevermind. Got it working now. Your suggestion plus SiLo's request helped me get it all figured out. I needed to use `AppName.Task` in the Class field in the Core Data model entity inspector. – William Proffitt Jun 11 '14 at 03:52
  • 1
    Could you please point out in your answer that you should add AppName.Model in the xcdatamodeld file. I took me a little bit to figure out. – Matt3o12 Jun 12 '14 at 18:38
  • 1
    I can get an app working and can cast if I've properly set the module name in the underlying data model. My problem is, I can't get a test to work without blowing up when hitting the line of code where I'm casting the NSManagedObject to my Swift model. Any ideas why? – Daniel D Jul 08 '14 at 08:04
  • 1
    I went in and put the app name before the entity name in the core data model entity inspector in the class field. It still doesn't work for me. So I entered .. I still get the EXC_BREAKPOINT error. Any suggestion? – zumzum Jul 09 '14 at 19:38
  • @zumzum Yes, when you run as Test it's Tests. – Ludovic Landry Nov 07 '14 at 07:04
  • 1
    @LudovicLandry but we can't have both, . and Tests. as a class name field, which one should we use to allow the app to run and tests without keep changing it? – Rodrigo Ruiz Nov 21 '14 at 05:11
  • @RodrigoRuiz see http://stackoverflow.com/questions/25076276/unabled-to-find-specific-subclass-of-nsmanagedobject/26796626#26796626 – Ludovic Landry Nov 21 '14 at 08:17
  • 5
    It appears to me that this solution doesn't work any more with XCode 7 beta 2: The entity inspector of XCode 7 beta 2 removes the dot from `AppName.Task` -> `AppNameTask`. (I used this solution successfully with XCode 6.x) – Gerd Castan Jul 05 '15 at 07:59
29

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

polarware
  • 2,409
  • 1
  • 22
  • 18
  • 1
    In my case in particular what I was missing was adding the Class itself instead of the module. Thanks for posting a visual which made this clear for me. – Carlos Pinto Sep 08 '15 at 01:50
  • This should be the accepted answer.. none of other answers are working. thanks @polarwar – Nookaraju Jun 09 '17 at 11:41
11

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

Owen Zhao
  • 2,827
  • 1
  • 20
  • 41
6

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

Jovan Jovanovski
  • 533
  • 7
  • 15
5

An update for @Ben Gottlieb answer under XCode 7.1 and Swift 2.0

  1. add @objc to your class. See Owen Zhao's answer. The following is an example:
@objc
class ImageRecordMO: NSManagedObject{
  1. Open your .xcdatamodled file.

  2. Select your entity and click the data model inspector on the right panel.

  3. Enter the class name, see the figure below

  4. Select your module to be Current Product Module, see the figure below.

enter image description here

Anson Yao
  • 1,426
  • 16
  • 27
4

Xcode 7 + Swift 2

Person.swift

@objc(Person)
class Person: NSManagedObject {
}

Data model

enter image description here

Then simply call

let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: self.managedObjectContext) as! Person
Viktor Kucera
  • 5,779
  • 2
  • 30
  • 38
2

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!

  • 1
    the problem of casting the nsmanaged object to custom, happens when you try to do it in the test target, not on the main project, as in your example. – kmarin Aug 07 '15 at 16:34
1

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.

Julien Couvreur
  • 3,615
  • 25
  • 37