核心数据 NSManagedObject 向下转换 XCode 7 和 Swift

Core Data NSManagedObject downcast with XCode 7 and Swift

运行 以下代码在 return 行

中止
Type is not Workout 
Could not cast value of type 
'NSManagedObject_Workout_' (0x7fcca20620f0) to 
'AppName.Workout' (0x100ea5f40)). 

if let...里面的部分永远不会执行。

func createWorkoutWithName (name: String) -> Workout? {
    let entityName = NSStringFromClass(Workout.classForCoder())
    let newEntity = NSEntityDescription.insertNewObjectForEntityForName(entityName, inManagedObjectContext: managedObjectContext)
    if let newEntity = newEntity as? Workout {
        newEntity.name = name
    }
    NSLog("createWorkoutWithName: Type is not Workout")
    return (newEntity as! Workout)

}

我过去遇到过这个问题,我在 XCode 6.x 中解决了它,方法是进入实体检查器并设置 Class = AppName.Workout

建议此解决方案的几个答案之一是 How come I can cast to NSManagedObject but not to my entity's type?

XCode 7 为这个问题添加了一个新的转折点: 当我设置

Class = AppName.Workout

在实体检查器中,XCode 7 自动将 class 名称更改为

Class = AppNameWorkout

删除 AppName 和 ClassName 之间的点。

当我无法在 AppName 和 ClassName 之间设置一个点时,我该如何在 XCode 7 中执行此操作?

转到您的 cdatamodel..您声明实体的位置..实体下方有一个默认配置。根据您的实体检查 Class 列。默认情况下,这将有一个点前缀。删除点前缀。它应该可以工作。据我所知,您不必在实体 class 名称前加上 Xcode 7 中的模块名称。因此,您不能在 class name.I 中使用点我是 iOS 开发的新手。所以我可能不完全正确。但是删除点前缀解决了我在 Xcode 7.

中的问题

您需要两个修复程序: 第一:将您的实体 class 名称设置为您的实体名称。例如:

Entity name = Entity
Class name = Entity

其次:将此代码添加到您的实体 class 文件上方:

@obj(Entity name)

例如:

@obj(Entity)
Class Entity: NSManagedObject { 
                   ...
}

这些解决方案与您提供的 link 的组合使我找到了解决方案,但我花了一些时间才将它们拼凑在一起。这是我想出的(基本上只是一个疏忽):

  1. 单击文件中的 .xcdatamodelId 文件 structure/project 导航器窗格(最左侧)。
  2. Select 您遇到问题的实体。
  3. 在“实用程序”窗格(最右侧)中,查找看起来像 1997 年单元格的图标 phone,数据模型检查器。
  4. 在实体设置下,您应该看到两个字段,"Name" 和 "Class" - 使用您正在使用的 class 的名称设置 "Class"(通常与 "Name").
  5. 相同

这就是我搞砸的地方,即使我的所有其他实体都有这个设置,我忘记在这个特定实体上设置它。在执行这些步骤之前,您甚至会注意到默认的 "class" 是 NSObject,反映了错误消息。这里的其他一些解决方案可能最终会做同样的事情,但我发现这是 simplest/quickest 解决方案。

我应该注意,我已经设置了一些其他项目,例如 @objc(Entity) 互操作性参考。