CoreData: 警告:无法加载名为的类

97

我正在使用Xcode 6.1将一个现有的Objective-C电视节目应用程序复制为一个新的Swift版本,并且在使用CoreData时遇到了一些问题。

我已经创建了4个实体的模型,创建了它们的NSManagedObject子类(在Swift中),并且所有文件都设置了正确的应用程序目标(对于“编译源”)。

每当我尝试插入一个新实体时,仍然会出现以下错误:

CoreData:警告:无法加载名为“Shows”的类以供实体“Shows”使用。找不到类,使用默认的NSManagedObject代替。

一些评论:

在保存到Core Data时,我使用父级-子级上下文方式来允许后台线程处理。我通过设置ManagedObjectContext来完成这个操作:

lazy var managedObjectContext: NSManagedObjectContext? = {
  // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
  let coordinator = self.persistentStoreCoordinator
  if coordinator == nil {
    return nil
  }
  var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
  managedObjectContext.persistentStoreCoordinator = coordinator
  return managedObjectContext
}()

通过使用以下方式保存数据:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
  var context = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
  context.parentContext = self.managedObjectContext!
  ...rest of core data saving code here...
})
13个回答

182
这个警告是我们在Swift实现细节被解决之前必须处理的怪事之一。警告会出现偶然,即使您不按照以下步骤操作,您的设置可能仍然有效。
我已经成功地摆脱了大部分情况下的警告,通过确保在模型编辑器中正确设置了类。与许多其他SOF帖子(包括此问题的答案)不同,建议包括模块名称(例如MyApp.Shows)并没有对我有帮助。
请确保检查以下三项:
1. 适用于Xcode 7 beta 3及以下版本的工作版本 2. 适用于Xcode 7.1中的Swift 2.0版本(适用于Xcode 7 beta 4及以上版本) 您需要删除“模块”中的“当前产品模块”文本! 3. 您还应该遵循频繁推荐的建议,包括...
@objc(Show)

就在你的班级上方。

注意: 如果您使用的是Xcode 7 beta 4或更高版本,则此步骤是可选的。

3.
还要确保将创建的托管对象转换为正确的类,因为默认情况下只是NSManagedObject

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show

4
谢谢!我确实已经按照建议的命名规范进行了更新,而且似乎是 '@objc(Show)' 这一行代码解决了 '无法加载类...' 的错误。非常感激! - JimmyJammed
1
请参考这个问题。那里有足够的信息来理解正在发生的事情。 - Mundi
4
有趣的是,我不得不移除 @objc(MyClass) - Andrew
我还必须删除@objc(MyClass)才能使其正常工作。 - Kent
1
@Mundi,你可能需要再次更新你的答案。请查看khunshan的答案更新。 - Suragch
显示剩余7条评论

80

SWIFT 2 / XCODE 7 更新:

这个问题(请参考我的回答中的四月三日的评论)已经在苹果发布的 Swift 2XCode 7 测试版中得到了解决。 所以,您现在不需要在 Swift 中使用 Mundi 回答的 @objc(myEntity) 或者在类名前面使用 "MyAppName."。这样将不再起作用。因此,请删除这些内容,只需在文件中放置Class名称,并选择当前工作模块作为Module即可。

选择当前工作模块

但是对于那些在 Swift 中使用@objc(myEntity)(像我一样),您可以使用另一个解决方案,它可以很好地工作。

在 xcdatamodel 中正确设置类,应该看起来像这样:

设置类

准备好了。Module.Class是 Swift 和 XCode 6 中 CoreData 的模式。当使用 Model Policy 或其他 CoreData 内容时,您也需要相同的步骤。注意:在图片中,Name 和 Class 应该是 Car 和 MyAppName.Car(或者您实体的名称)。这里,User 是个错字。


2
是的,这肯定会得到解决。自动生成的类应该已经用@objc(<在实体检查器中输入的类名>)进行了装饰,或者更有可能的是,苹果公司将一开始就不需要这样做。 - Milos
2
对于仍在阅读此内容的人。在我的情况下,使用 'MyAppName.Car' 并不起作用,但当我去掉 'MyAppName.' 部分后就可以了。所以在两个字段中都只使用 Car 就可以了。 - Gideon
@khunshan 刚刚再次检查了一下。我认为你应该取消删除包含我的名字的那个被划掉的句子。我的解决方案仍然有效。显然,删除 @obj(MyClass) 与此无关(误报)。我在原始答案中指出,它有时仍然有效,谁知道为什么。 - Mundi
是的。我总是确保我拥有最新的官方Xcode以及最新的测试版(如果有)。在7.1.1(7B1005)中没有明显的变化。 - Mundi
1
你是冠军!!!! 让person = NSEntityDescription.insertNewObject(forEntityName: "Person", into: context) as! Person - Abhimanyu Rathore
显示剩余6条评论

36

当使用Xcode 7和纯Swift的时候,我实际上需要从我的自动生成的NSManagedObject子类(通过 编辑器 > 创建NSManagedObject子类...)中移除@objc(MyClass)


4
哇,感谢您发布这个答案。我差点要开始对着墙撞头了。 - Zia
我也遇到了同样的问题 - 已经提交了一个错误报告。 - MirekE
也对我有用。不得不将其删除。很奇怪。 - Kent
1
根据我的实验结果,看起来是一个误报。 - Mundi
我不得不将其删除并设置当前产品模块,才能使其正常工作。 - Oleg Sherman

13
在Xcode 7 beta 2(我相信1也是这样),在模型配置中,将一个新的类型为File的托管对象设置为模块 Current Product Module,并且在配置中显示对象的类为.File
删除模块设置使其为空白或删除句号,这样配置中的类名只是File,这两个操作是等效的,因为每个操作都会导致另一个变化。保存此配置将删除所述错误。

9
在Xcode 6.1.1中,您无需添加@objc属性,因为基本实体是一个objc类的子集(NSManagedObject)(参见Swift类型兼容性)。在CoreData中,需要完整的Module.Class名称。请注意,模块名称是在“Build Settings” -> “Packaging” -> “Product Module Name”中设置的。默认情况下,这个设定是$(PRODUCT_NAME:c99extidentifier),它将是目标的名称

是的!这就是现代答案(xcode 6.3.2)。使用正确的包名称是关键。在我的情况下,它已经将“my-product”转换为“my_product”,这对Core Data产生了很大的影响。 - SimplGy

6
使用xCode 7和Swift 2.0版本,您无需添加@objc(NameOfClass),只需在“Show the Data Model Inspector”选项卡中更改实体设置即可,如下所示-
名称 - “Your Entity Name”
类 - “Your Entity Name”
模块 - “Current Product Module”
链接如下:enter image description here 实体类文件的代码如下(在我的代码中,实体是Family):
import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

这个例子在我的应用程序中使用xCode 7.0+ swift 2.0能够正常工作。


3
请勿忘记将 PRODUCT_MODULE_NAME 替换为您的产品模块名称。
创建新实体时,您需要进入数据模型检查器(最后一个选项卡),并将 PRODUCT_MODULE_NAME 替换为您的模块名称,否则在创建持久存储协调器时会导致 class not found 错误。

2

在进行类型转换时,您还需要使用(至少在Xcode 6.3.2中)模块.类。例如,假设您的模块(即产品名称)是Food,您的类是Fruit。

let myEntity =  NSEntityDescription.entityForName("Fruit", inManagedObjectContext: managedContext)

let fruit = NSManagedObject(entity: myEntity!, insertIntoManagedObjectContext:managedContext) as! Food.Fruit

总结:

  • 在数据模型编辑器中定义实体时,请包含模块名称(名称:Fruit,类别:Food.Fruit)
  • 在代码中访问实体时(例如SWIFT),请使用Module.class进行转换(例如Food.Fruit)

谢谢,第二点非常重要。我在转换时必须使用“模块.类”。 - Zoyt


1
在数据模型编辑器中更改实体类名称以对应所涉及的类,并在每个NSManagedObject的文件中在类声明正上方添加@objc(NameOfClass),这样在单元测试期间就可以解决我的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接