Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to find specific subclass of NSManagedObject

Update for Xcode 7 (final): Prepending the module name to the class (as in Xcode 6 and early beta releases of Xcode 7) is no longer necessary. The Apple documentation Implementing Core Data Managed Object Subclasses has been updated accordingly.

The Data Model inspector has now two fields "Class" and "Module" for an entity:

enter image description here

When you create a Swift managed object subclass for the entity, the "Module" field is set to "Current Product Module", and with this setting creating instances works both in the main application and in unit tests. The managed object subclass must not be marked with @objc(classname) (this was observed in https://stackoverflow.com/a/31288029/1187415).

Alternatively, you can empty the "Module" field (it will show "None") and mark the managed object subclasses with @objc(classname) (this was observed in https://stackoverflow.com/a/31287260/1187415).


Remark: This answer was originally written for Xcode 6. There were some changes in the various Xcode 7 beta releases with respect to this problem. Since it is an accepted answer with many upvotes and links to it, I have tried to summarize the situation for the current Xcode 7 final version.

I did both my own "research" and read all the answers to both this question and the similar question CoreData: warning: Unable to load class named. So attribution goes to all of them, even if I don't list them specifically!


Previous answer for Xcode 6:

As documented in Implementing Core Data Managed Object Subclasses, you have to prefix the entities class name in the Class field in the model entity inspector with the name of your module, for example "MyFirstSwiftApp.User".


Just as a side-note. i had the same issue. And all i had to do was add @objc(ClassName) in my class file.

Example:

@objc(Person)
class Person { }

And that solved my issue.


The accepted answer to this question helped me resolve the same issue but I had a caveat that I thought would be helpful to others. If your project (module) name has a space in it you must replace the space with an underscore. For example:

Entity: MyEntity Class: My_App_Name.MyClass


Remember to remove your module:

enter image description here


Depending if you are running as App vs Tests the issue can be that the app is looking for <appName>.<entityName> and when it's running as test it's looking as <appName>Tests.<entityName>. The solution I use at this time (Xcode 6.1) is to NOT fill the Class field in the CoreData UI, and to do it in code instead.

This code will detect if you are running as App vs Tests and use the right module name and update the managedObjectClassName.

lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional...
    let modelURL = NSBundle.mainBundle().URLForResource("Streak", withExtension: "momd")!
    let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)!

    // Check if we are running as test or not
    let environment = NSProcessInfo.processInfo().environment as [String : AnyObject]
    let isTest = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest"

    // Create the module name
    let moduleName = (isTest) ? "StreakTests" : "Streak"

    // Create a new managed object model with updated entity class names
    var newEntities = [] as [NSEntityDescription]
    for (_, entity) in enumerate(managedObjectModel.entities) {
        let newEntity = entity.copy() as NSEntityDescription
        newEntity.managedObjectClassName = "\(moduleName).\(entity.name)"
        newEntities.append(newEntity)
    }
    let newManagedObjectModel = NSManagedObjectModel()
    newManagedObjectModel.entities = newEntities

    return newManagedObjectModel
}()

If you are using a hyphen in your project name like "My-App" then use an underscore instead of the hyphen like "My_App.MyManagedObject". In general, look at the name of the xcdatamodeld file and use the same prefix as in that name. I.e. "My_App_1.xcdatamodeld" requires the prefix "My_App_1"


This may help those experiencing the same problem. I was, with Swift 2 and Xcode 7 beta 2.

The solution in my case was to comment out @objc(EntityName) in EntityName.swift.