找不到NSManagedObject的特定子类


136

我正在使用Core Data开发应用程序。当我使用以下方法创建实例时:

let entity = NSEntityDescription.entityForName("User", inManagedObjectContext: appDelegate.managedObjectContext)
let user = User(entity: entity, insertIntoManagedObjectContext: appDelegate.managedObjectContext)

我在日志中收到警告:

CoreData: warning: Unable to load class named 'User' for entity 'User'.  Class not found, using default NSManagedObject instead.

我该如何解决?

还有另一个问题,如何在NSManagedObject子类中定义实例方法?

编辑:

我已指定实体的类别,如以下屏幕截图所示:

在此处输入图片说明


7
实现核心数据托管对象子类中所述,您是否已在实体类名前面加上模块名?
Martin R

@MartinR:请参阅我的问题的更新。
MsrButterfly

2
该类应为“ YourAppName.User”,请参见文档(我之前的评论中的链接)。
马丁R

@MartinR:谢谢您的帮助。有用。
MsrButterfly

最好的办法是删除这些类并重新创建。这为我工作
阿布舍克

Answers:


220

Xcode 7的更新(最终): 不再需要在类之前添加模块名称(如Xcode 6和Xcode 7的早期beta版本一样)。Apple文档“ 实现核心数据托管对象子类”已相应更新。

数据模型检查器现在为实体具有两个字段“类”和“模块”:

在此处输入图片说明

当您为实体创建Swift管理对象子类时,“模块”字段将设置为“当前产品模块”,并且使用此设置,可以在主应用程序和单元测试中创建实例。托管对象子类一定不能标记@objc(classname)(在https://stackoverflow.com/a/31288029/1187415中可以看到)。

或者,您可以清空“模块”字段(它将显示“无”)并用标记托管对象子类@objc(classname)(在https://stackoverflow.com/a/31287260/1187415中可以看到)。


备注:此答案最初是为Xcode 6写的。针对此问题,各种Xcode 7 beta版本中都有一些更改。由于它是一个被接受的答案,带有很多赞誉和指向它的链接,所以我试图总结当前Xcode 7最终版本的情况。

我进行了自己的“研究”,并阅读了该问题和类似问题CoreData的所有答案 :警告:无法加载名为的类。因此,归因于所有这些人,即使我没有具体列出它们!


Xcode 6的先前答案:

实现核心数据托管对象子类中所述,您必须在模型实体检查器的“类”字段中为实体类名称加上模块名称,例如“ MyFirstSwiftApp.User”。


2
这个正在为我工​​作。问题:如果核心数据包含在框架中,那么由于尚无实际的应用程序,该如何为ManagedObject子类名称加上前缀呢?
艾伦·马卡汀特拉

9
@Allan:您可以尝试@objc(ClassName)Christer的答案中建议的方法。
马丁R

8
它可以工作,但是一旦我在实体检查器中将类名设置为“ APPNAME.User”,我就无法重新生成模型类:Xcode似乎被前缀弄糊涂了,并且它会生成一个带有该名称的文件/类APPNAME。我想念什么吗?
Pascal Bourque 2014年

1
如果在静态库中使用核心数据时在Objective-C中出现此错误怎么办?
George Taskos 2014年

1
@Suragch:我现在终于更新了答案,我希望现在一切都正确。
Martin R

62

只是一个旁注。我遇到过同样的问题。我要做的就是添加@objc(ClassName)我的班级文件。

例:

@objc(Person)
class Person { }

这就解决了我的问题。


1
您以这种方式在Objective-C中定义了类型别名(<%ProjectName%>。Person-> Person)。
MsrButterfly 2014年

好像苹果忘了完全将其转换为迅速..不知道为什么,但这个固定为我漂亮温柔
吉日Zahálka

7
如果您的项目有多个目标,而每个目标都共享CoreData模型,则此功能特别有用。在这些情况下,无法在类名前面加上目标标识符的前缀,因为这会使CD模型仅对一个目标有用。
2014年

@djbp和“为什么不呢?” 我想知道。我喜欢命名空间的概念,但这使我想把MacBook抛在窗外(我有一个带有扩展程序的应用程序,在运行扩展程序时遇到了这个问题)。必须使用名称空间来做到这一点,我只是想不通。
S'pht'Kr 2014年

是的,当在工作空间中使用共享数据模型时,这对我
有用

31

对这个问题的公认答案帮助我解决了同样的问题,但我有一个警告,我认为这对其他人会有所帮助。如果项目(模块)名称中有空格,则必须用下划线替换该空格。例如:

实体:MyEntity类:My_App_Name.MyClass


正是我在寻找!干杯!
manosim 2014年

当我们使用AppName.ClassName设置类名称时,Xcode 9会删除该点并创建一个不带点的类。因此,Xcode 9. *中不再提供此功能。
yo2bh


9

取决于您是否以App vs Tests的身份运行,问题可能在于该应用程序正在寻找,<appName>.<entityName>以及它在作为测试运行时的外观是<appName>Tests.<entityName>。我目前使用的解决方案(Xcode 6.1)是不填写ClassCoreData UI中的字段,而是在代码中执行。

此代码将检测您是否以App vs Tests的身份运行,并使用正确的模块名称并更新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
}()

1
我尝试了您的解决方案,但是在将NSManagedObject转换为实际类时遇到“严重错误:NSArray元素与Swift Array元素类型不匹配”。实际上,不是在强制转换本身时而是在尝试进入for循环时。
罗德里戈·鲁伊斯

1
如果您的模型具有任何继承,则该示例将不起作用。对于每个新实体,还需要遍历子实体,并使用创建的新实体对其进行更新。
安东

8

如果您在项目名称中使用连字符,例如“ My-App”,则使用下划线代替“ My_App.MyManagedObject”之类的连字符。通常,请查看xcdatamodeld文件的名称,并使用与该名称相同的前缀。即“ My_App_1.xcdatamodeld”需要前缀“ My_App_1”


1
哇。谢谢你,谢谢你,谢谢你。我想知道在Apple文档中
哪个小块

5

这可能会帮助遇到相同问题的人。我当时使用的是Swift 2和Xcode 7 beta 2。

该解决方案在我的情况是注释掉@objc(EntityName)EntityName.swift


3

我有同样的警告,尽管我的应用程序似乎运行良好。问题是,在最后一个屏幕上运行“编辑器”>“创建NSManagedObject子类”时,我使用默认的“组”位置,没有显示或选中“目标”,这将子类保存在MyApp.xcodeproj所在的顶部MyApp目录中。
当我改为将组更改为MyApp子文件夹并检查MyApp目标时,警告消失了。


2

上面的答案很有帮助。快速的完整性检查可以为您节省一些时间。进入“项目”>“构建阶段”>“编译源代码”,然后使用“-”按钮删除xcdatamodeld和模型文件,然后使用“ +”按钮将它们重新添加回去。重建-可能会解决。


2

顺便提一句,您要添加前缀:我的应用程序称为“ ABC-def”,Xcode已将“-”转换为“ _”。

为了安全起见,请查找查找器,找到您的项目文件,看看它对数据模型的含义(例如“ ABC_def.xcdatamodeld”),并完全使用那里写的内容!!!


1

上面的答案帮助我解决了与Objective-C有关的其他问题(也许会帮助某人):

如果重构了实体名称,请不要忘记在“实用程序面板”中更改“类”。


0

上面的答案对我有帮助,但这可能对某人有帮助。如果像我一样,您做到了,但仍然遇到问题,请记住简单地“清理您的项目”。对于XCode8,请选择产品>清洁。然后再次运行。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.