找不到 NSManagedObject 的特定子类

Posted

技术标签:

【中文标题】找不到 NSManagedObject 的特定子类【英文标题】:Unable to find specific subclass of NSManagedObject 【发布时间】:2014-08-01 08:47:58 【问题描述】:

我正在使用 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 子类中定义实例方法?

编辑:

我已经指定了实体的类,如下图所示:

【问题讨论】:

您是否在实体类名称前加上模块名称,如Implementing Core Data Managed Object Subclasses 中所述? @MartinR:查看我的问题更新。 该类应该是“YourAppName.User”,请参阅文档(我之前评论中的链接)。 @MartinR:感谢您的帮助。它有效。 最好的办法是删除这些类并重新创建它。这对我有用 【参考方案1】:

Xcode 7 更新(最终版): 不再需要将模块名称附加到类(如 Xcode 6 和 Xcode 7 的早期 beta 版本中)。 Apple 文档Implementing Core Data Managed Object Subclasses 已 相应更新。

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

当您为实体创建 Swift 托管对象子类时, “模块”字段设置为“当前产品模块”,并使用此设置 创建实例既适用于主应用程序,也适用于单元测试。 托管对象子类必须@objc(classname) 标记(这在https://***.com/a/31288029/1187415 中观察到)。

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


备注:此答案最初是为 Xcode 6 编写的。 各种 Xcode 7 beta 版本有一些变化 尊重这个问题。因为这是许多人公认的答案 赞成票和链接,我试图总结情况 对于当前的 Xcode 7 最终版本。

我做了自己的“研究”并阅读了这个问题和类似问题的所有答案 CoreData: warning: Unable to load class named。所以归属于他们所有人,即使我没有 具体列出来!


Xcode 6 的先前答案:

如 Implementing Core Data Managed Object Subclasses 中所述,您必须 在模型实体检查器的 Class 字段中的实体类名称前加上您的模块名称,例如“MyFirstSwiftApp.User”。

【讨论】:

这个对我有用。问题:如果核心数据包含在框架中,由于还没有实际的应用程序,如何在 ManagedObject 子类名称前加上前缀? @Allan:您可以尝试 Christer 的回答中建议的 @objc(ClassName) 方法。 它可以工作,但是一旦我在实体检查器中将类名设置为“APPNAME.User”,我就无法重新生成模型类:Xcode 似乎被前缀混淆了,它生成一个名为 APPNAME 的文件/类。我错过了什么吗? 在静态库中使用核心数据时,如果在 Objective-C 中出现此错误怎么办? @Suragch:我现在终于更新了答案,我希望现在一切都是正确的。【参考方案2】:

作为旁注。我遇到过同样的问题。我所要做的就是在我的类文件中添加@objc(ClassName)

例子:

@objc(Person)
class Person  

这解决了我的问题。

【讨论】:

您以这种方式在 Objective-C 中定义了 typealias (.Person -> Person),所以它可以工作。 似乎 Apple 忘记将其完全转换为 swift .. 不知道为什么,但这很温和地为我修复了它 如果您的项目具有多个目标,其中每个目标共享 CoreData 模型,这将特别有用。在这些情况下,不可能在类名前加上目标标识符的前缀,因为这会使 CD 模型仅对其中一个目标有用。 @djbp “为什么不呢?”我想知道。我喜欢命名空间的概念,但这让我想把我的 MacBook 扔出窗外(我有一个带有扩展的应用程序,并在运行扩展时遇到了这个问题)。必须有一种“正确”的方式来使用命名空间来做到这一点,我就是想不通。 是的,在工作区中使用共享数据模型时,这对我有用【参考方案3】:

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

实体:MyEntity 类:My_App_Name.MyClass

【讨论】:

正是我想要的!干杯! 当我们使用 AppName.ClassName 设置类名时,Xcode 9 会删除点并创建一个没有点的类。所以这不再是 Xcode 9.*.【参考方案4】:

记得删除你的模块

【讨论】:

这解决了我的问题。【参考方案5】:

根据您是否作为应用程序与测试运行,问题可能是应用程序正在寻找<appName>.<entityName>,而当它作为测试运行时,它看起来是<appName>Tests.<entityName>。我目前使用的解决方案(Xcode 6.1)是不在 CoreData UI 中填写 Class 字段,而是在代码中完成。

此代码将检测您是否作为 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
()

【讨论】:

我尝试了您的解决方案,但在将 NSManagedObject 转换为其实际类时出现“致命错误:NSArray 元素无法匹配 Swift Array 元素类型”。实际上不是在投射自身时,而是在尝试进入 for 循环时。 如果您的模型中有任何类型的继承,则该示例不起作用。对于每个新实体,您还需要迭代子实体并使用您创建的新实体更新它们。【参考方案6】:

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

【讨论】:

哇。谢谢你,谢谢你,谢谢你。我很想知道苹果文档中那个小金块在哪里:)【参考方案7】:

这可能会对遇到同样问题的人有所帮助。我是,使用 Swift 2 和 Xcode 7 beta 2。

在我的情况下,The solution 是在 EntityName.swift 中注释掉 @objc(EntityName)

【讨论】:

【参考方案8】:

以上答案很有帮助。这种快速的健全性检查可能会为您节省一些时间。进入 Project > Build Phases > Compile Sources 并使用“-”按钮删除您的 xcdatamodeld 和模型文件,然后使用“+”按钮将它们添加回来。重建——这可能会解决它。

【讨论】:

【参考方案9】:

我收到了同样的警告,但我的应用似乎运行良好。 问题是,在最后一个屏幕上运行 Editor > Create NSManagedObject Subclass 时,我使用了默认的 Group 位置,没有显示或检查 Target,这将子类保存在 MyApp.xcodeproj 所在的顶部 MyApp 目录中。 当我改为将 Group 更改为 MyApp 子文件夹并检查 MyApp 目标时,警告消失了。

【讨论】:

【参考方案10】:

顺便说一下,你添加的前缀要小心:我的应用程序被称为“ABC-def”,Xcode 已将“-”转换为“_”。

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

【讨论】:

【参考方案11】:

以上答案帮助我解决了与 Objective-C 相关的不同问题(也许它会帮助某人):

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

【讨论】:

【参考方案12】:

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

【讨论】:

【参考方案13】:

在 Xcode 7 中,实体和类名称可以相同,但 Codegen 应该是类定义。在这种情况下,不会有警告等。

【讨论】:

以上是关于找不到 NSManagedObject 的特定子类的主要内容,如果未能解决你的问题,请参考以下文章

找不到 NSManagedObject 的特定子类

在 CoreData 中使用 NSManagedObject 子类找不到 xcode8 标头

将资源注入 NSManagedObject 子类实例

Xcode 8.0 NSManagedObject 子类模板在哪里

CoreData 错误:找不到类,而是使用默认的 NSManagedObject [重复]

“找不到源存储的模型”核心数据错误