Xcode 8为iOS 10生成的NSManagedObject子类存在问题。

65

我最近将我的iOS应用程序项目更新到iOS 10。现在,我正在尝试更改应用程序的Core Data模型,但是Xcode生成的新NSManagedObject子类已经损坏了。我也试图手动修复子类,但这并不起作用。

Core Data模型的最小工具版本设置为Xcode 7.0,代码生成语言设置为Swift。

这是Xcode生成的代码:

import Foundation
import CoreData
import 

extension Group {

    @nonobjc public class func fetchRequest() -> NSFetchRequest {
        return NSFetchRequest(entityName: "Group");
    }

    @NSManaged public var name: String?
    @NSManaged public var platform: NSNumber?
    @NSManaged public var profiles: NSOrderedSet?

}

// MARK: Generated accessors for profiles
extension Group {

    @objc(insertObject:inProfilesAtIndex:)
    @NSManaged public func insertIntoProfiles(_ value: SavedProfile, at idx: Int)

    @objc(removeObjectFromProfilesAtIndex:)
    @NSManaged public func removeFromProfiles(at idx: Int)

    @objc(insertProfiles:atIndexes:)
    @NSManaged public func insertIntoProfiles(_ values: [SavedProfile], at indexes: NSIndexSet)

    @objc(removeProfilesAtIndexes:)
    @NSManaged public func removeFromProfiles(at indexes: NSIndexSet)

    @objc(replaceObjectInProfilesAtIndex:withObject:)
    @NSManaged public func replaceProfiles(at idx: Int, with value: SavedProfile)

    @objc(replaceProfilesAtIndexes:withProfiles:)
    @NSManaged public func replaceProfiles(at indexes: NSIndexSet, with values: [SavedProfile])

    @objc(addProfilesObject:)
    @NSManaged public func addToProfiles(_ value: SavedProfile)

    @objc(removeProfilesObject:)
    @NSManaged public func removeFromProfiles(_ value: SavedProfile)

    @objc(addProfiles:)
    @NSManaged public func addToProfiles(_ values: NSOrderedSet)

    @objc(removeProfiles:)
    @NSManaged public func removeFromProfiles(_ values: NSOrderedSet)

}

编辑:这些是Xcode给出的具体错误:

1. Group+CoreDataProperties.swift:13:1: Expected identifier in import declaration (the empty import)
2. Group+CoreDataProperties.swift:13:11: 'Group' is ambiguous for type lookup in this context
3. Group+CoreDataProperties.swift:15:16: Cannot specialize non-generic type 'NSFetchRequest'
4. Group+CoreDataProperties.swift:26:11: 'Group' is ambiguous for type lookup in this context
4. Group+CoreDataProperties.swift:43:82: 'SavedProfile' is ambiguous for type lookup in this context

你能解释一下是哪里出了问题吗?是第三行的空导入吗? - DavidA
@DavidAtkinson 是的,Xcode会出现空导入错误。我已经将其他四个错误添加到问题中了。 - Remco Beugels
4
很不幸,我认为这是Xcode 8和8.1 beta版本中的一个错误。如果您自动生成数据,派生数据文件存储在那里,并且文件名以点号开头,则Xcode将无法找到该文件。如果您手动修复它,然后会出现假错误,例如您列出的错误。我还没有找到解决方法,而且我无法相信更多的人还没有发现此错误,因为它似乎会阻止您能够在应用程序中使用核心数据。http://www.openradar.me/27151410 - Longmang
@Longmang 感谢您的解释。希望苹果能尽快为这个问题发布一个更新。 - Remco Beugels
22个回答

111

我终于让我的代码工作了。这是我所做的。 ("Flights" 是我的一个实体之一)

我按照以下方式设置了 "xcdatamodeld"

enter image description here

然后设置了实体:

enter image description here

接着,我使用编辑器 -> 创建 NSManagedObject 子类

这将为我创建两个文件来管理我的 "flights" 实体

"Flights+CoreDataProperties.swift" 和 "Flights+CoreDataClass.swift"

我将 "Flights+CoreDataClass.swift" 重命名为 "Flights.swift"

"Flights.swift" 只有以下内容:

import Foundation
import CoreData

@objc(Flights)
public class Flights: NSManagedObject {

}

Flights+CoreDataProperties.swift是

import Foundation
import CoreData


extension Flights {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
        return NSFetchRequest<Flights>(entityName: "Flights");
    }

    @NSManaged public var ...
}

这对我来说似乎有效。尽管我尝试了许多建议,但无法以其他方式使代码生成器工作。

此外,这让我想了很长时间,我将其添加为一个辅助提示。不要忘记使用新的泛型版本FetchRequest,您可以这样做

let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")

4
这对我有用,非常感谢!我也花了太长时间去寻找解决方案,却只带来了极度的挫败感。我尝试了各种方式,但除了这个方法以外什么都没用。很重要的一点是,在“代码生成”选项中选择“手动/无”。如果保持为“类定义”,似乎它将不起作用。再次感谢您的帮助! - Pierce
2
这对我没有起作用。我的解决方案是将工具版本最小化到Xcode 7.3... 奇怪:S - MarMass
如果您不将其更改为手动/无选项,Xcode会自动生成MO类。 - rwang
谢谢!这个解决方案在最新的Xcode版本(8.3 - 8E162)中完美运行。 - Remco Beugels
你知道 Manual/None 是什么意思吗? - Ketan Dubey
显示剩余6条评论

43

我认为在生成NSManagedObject子类文件后遇到错误的原因可能与更改数据模型时选择的Codegen选项有关。

我不认为这是一个bug,至少在Xcode 8.1 (8B62)中不是。

我遇到了类似的问题,并通过将Codegen选项更改为"Manual/None"并保留模块选项为"Global Namespace"来解决了它。然后我生成了我的NSManagedObject子类文件。但是,根据您的情况,您甚至可能不需要生成NSManagedObject子类。

以下是有关实体Codegen选项的更多详细信息,基于我对苹果文档、苹果开发者论坛和测试我的项目的回顾。

选项1: "Class Definition"

  • 将其视为“即插即用”选项

  • 使用模型编辑器创建要由Core Data管理的实体及其相关属性。

  • 不要使用NSMangagedObject子类生成器。所需文件由Xcode自动生成(但它们不会显示在项目导航器中)。

  • 如果您确实生成了NSManagedObject文件,则Apple会告诉您这些文件不应在文件的头注释中进行编辑。如果您确实需要编辑这些文件,则说明您需要使用另一个Codegen选项。

  • 保留实体的默认类选项(模块=全局命名空间,Codegen=Class Definition)

  • 如果您需要重写NSManagedObject的方法,则可以使用类选项下的名称创建扩展。

    // 可选扩展,在Entity.swift中 extension Entity { // 重写NSManagedObject的方法 }

选项2: "Manual/None"

  • 与选项1类似,只是您可以查看和编辑NSManagedObject子类文件。

  • 使用模型编辑器创建要由Core Data管理的实体及其相关属性。

  • 在使用NSManagedObject子类生成器之前,请将Codegen选项设置为实体的“手动/无”模式。Module选项应该是全局命名空间。

  • 在添加/删除/更新属性后,您有两个选择:(1)手动更新为您生成的NSManagedObject文件, OR(2)再次使用NSManagedObject子类生成器(这将仅更新Entity+CoreDataProperties.swift文件)。

  • 如果需要重写NSManagedObject中的任何方法,则可以创建扩展。扩展应在Entity+CoreDataClass.swift文件中创建,而不是Entity+CoreDataProperties.swift文件(此文件可能会因模型编辑器更改而更新)。

    // 在Entity+CoreDataClass.swift中创建可选扩展 extension Entity { // 重写NSManagedObject方法 }

选项3:“分类/扩展”

  • 如果您有不需要由Core Data管理的自定义属性,请使用此选项。

  • 使用模型编辑器创建要由Core Data管理的实体和相关属性。

  • 确保Module选项设置为当前产品模块,并将Codegen选项设置为“分类/扩展”。

  • 创建自己的NSManagedObject子类,并加入您想要自我管理的属性。

  • 请勿使用NSMangagedObject子类生成器。所需文件将由Xcode自动生成(但不会显示在项目导航器中)。

    // 在Entity.swift中子类化NSManagedObject class Entity: NSManagedObject { // 自我管理的属性 }

    // 在Entity.swift中创建可选扩展 extension Entity { // 重写NSManagedObject方法 }


3
你能否详细说明一下类别/扩展路径?我在数据模型中添加了一个瞬时属性,但我不知道如何编辑生成的文件,因为我在左侧文件资源管理器中看不到它们。当导入头文件时,它们会显示出来,所以它们肯定是在某个地方生成的。 - SolidSnake4444
谢谢。你的回答非常有帮助。你能否也看一下这里。我的问题集中在当你使用Manual/None时如何更改属性。 - mfaani

41
  1. 解决这个问题,请删除应用程序的派生数据。

  2. 然后将模块更改为当前产品模块,并在Codegen中进行更改以使用手动/无选项。

  3. 列表项

1
如果您希望跳过派生数据的删除,请删除您生成的NSManagedObject子类,进行上述更改,保存模型文件,然后再次创建NSManagedObject子类。 - Jason McClinsey
1
这就是如何修复它。 - Paranoid Android

17

尝试将CodeGen设置为手动/无

当我遇到相同的问题时,这对我很有帮助。

输入图像描述


10
您可以尝试以下步骤:
  1. 在Xcode项目导航器中选择.xcdatamodeld文件
  2. Data Model Inspector中,确保Codegen : 手动/无
  3. 然后编辑 -> 创建NSManagedObject子类
  4. 清理产品并重新构建

这个方法有效吗?如果不行,

请确保您的class名称与Entities不同。您可以在Build Phases -> Compile Sources中找到这些类。如果它们重复,请重命名类或实体。

或者,

您可以在项目文件夹中运行此命令以获取更多错误信息:

xcodebuild -verbose

当我遇到此问题时,我收到了以下消息:

duplicate symbol _OBJC_CLASS_$_RandomList in:

xxxx/RandomList.o

xxxx/RandomList+CoreDataClass.o

RandomList.hRandomList+CoreDataClass.h在编译时具有相同的符号。

我想这就是为什么Xcode没有警告你,但编译器会抛出错误的原因。

希望这可以帮助您。


如果您已经创建了这两个文件,只需要执行步骤#2和#3即可。这对我来说是有效的。 - Mani

7
如果您有一个传统的应用程序,并且希望手动添加托管对象类,请按照以下步骤操作:
  1. 确保您的核心数据模型代码生成设置为手动/无
  2. 选择您的核心数据模型文件
  3. 创建托管对象子类

编辑器截图

请注意,保留HTML标记。

6

删除第三个import语句,因为它是空的。

注意:我不知道为什么会出现这种情况,但我猜测这是Xcode 8中的一个漏洞。只需将其删除即可正常工作。


谢谢你的回答!不幸的是,删除三个空的“import”语句并不能解决所有错误。 - Remco Beugels
2
这个可行。 哇...谁负责QA这些东西...苹果加油。 - MiMo
1
这对我来说有效,使用了“手动/无”选项和Xcode 8.0...至少没有构建错误。 - anoop4real

5
在Xcode 8.2.1上,我按照以下方式进行操作:(感谢Daniel Chepenko)

enter image description here

但是 Xcode 8.2.1 会在生成的文件中添加一个愚蠢的“.”

enter image description here

只需删除 . ,它就可以正常运行。


你可以使用 Xcode 7.3.1 设计 CoreData 并生成相关类,然后退出 Xcode 7.3.1 并使用 Xcode 8 打开项目。(我最近的项目也是这样做的,已验证:]) - Alpha Liu

4
我刚遇到了一个问题,我在我的模型中添加了一个Person实体到Core Data模板中。然后为此生成了NSManagedObject子类,但它无法编译,给我一个链接错误。结果发现我应该将Codegen选项更改为手动/无以使其工作(请参见图片右下角)。enter image description here

这对我有效,因为我已经生成了NSManagedObject的子类。 - djneely

3
我认为这是一个Xcode问题,Xcode生成了Core Data类别类的错误语法。我正在为实体“AgentDetails”创建nsmanageobjectsubclass它正在创建以下类 在这里,Xcode在AgentDetails+CoreDataClass.hAgentDetails+CoreDataClass.m中创建了错误的代码结构。这些文件的代码结构如下:

enter image description here

enter image description here

所以它存在重复接口问题,因为AgentDetails.h具有相同的接口。

现在要修复此问题,您需要更改AgentDetails+CoreDataClass.h中的代码。

enter image description here

并且像这样的 AgentDetails+CoreDataClass.m:

enter image description here


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