自动生成的NSManagedObject子类中出现无效的重新声明 Swift 3。

53

使用Xcode 8.1版本。

在.xcdatamodeld文件中创建名为“MapRegionObject”的实体。图片描述

使用自动代码生成器,点击导航栏上的Editor -> 创建NSManagedOject子类...

得到两个文件:MapRegionObject+CoreDataClass.swift和MapRegionObject+CoreDataProperties。

两个文件中的错误显示在屏幕截图中: MapRegionObject+CoreDataClass.swift 图片描述

MapRegionObject+CoreDataProperties 图片描述

请帮忙修复这些错误,非常感谢!


1
如果您正在使用自动代码生成:在实体对象上的类定义中,您不应该创建自己的NSManagedOject子类。XCode已经在DerivedData中为您创建了它。如果您想创建自己的子类,请在实体上指定另一个codegen。请查看此论坛:https://dev59.com/51oU5IYBdhLWcg3wAjnV - Andrew Veresov
8个回答

128

在使用自动代码生成器之前,必须选择数据模型中的实体:

Entity

然后进入“数据模型检查器”选项卡:

Data Model Inspector

在“Codegen”下选择“Manual/None”

然后就可以创建一个NSManagedObject子类了,这样不会出现错误。


或者,如果您已经使用了“类定义”,则可以进入您现有的.xcdatamodeld文件,并将所有当前实体设置为“Manual/None”下的 Codegen。确保保存项目(文件 -> 保存),删除现有的Derived Data、清理项目,然后编译即可。这样可以解决问题,而无需重新制作整个模型。


5
如果您已经使用“Codegen”下的“Class Definition”选项创建了您的类,并且遇到了这个错误,那么请先删除您的.xcdatamodeld文件并重新创建它。然后在“Codegen”下设置“手动/无”选项,并使用自动生成的代码生成器。 - Marcos Reboucas
13
如果您已经使用了“类定义”,则可以进入现有的.xcdatamodeld文件,并在Codegen下将所有当前实体设置为“手动/无”。确保保存项目(文件->保存),删除现有的派生数据,清理项目,然后构建。这样可以解决问题,而无需重新制作整个模型。 - DJB
它可以工作!但是,在更改 CodeGen 后,请确保保存文件。 - Salis

20

我发现整个过程非常令人困惑,您确实需要了解CoreData中的新内容。基本上,默认情况下会在名为“DerivedData”的地方自动生成类和扩展,该文件夹位于~/Library/Developer/Xcode/DerivedData中,这些类及其扩展存在于代码源之外。对我而言,无法打开并查看它们是很奇怪的,但可以逐渐适应。

如果你的CoreData模型中有一个名为“AppSettings”的实体,你可以直接使用它而不需要自己生成代码。如果你想把代码放到你的项目中,那么在实体上设置Codegen属性为Manual/None,然后像之前一样操作:Editor->Create NSManagedObject classes等。文件将会出现在你的项目中。

好消息是,如果你想制作自定义扩展,直接在你的项目中进行即可。Xcode会将从项目目录之外的其他位置生成的文件与你的项目目录中的文件混合在一起。


谢谢,得票最多的答案解决了我的问题,但这也解释了为什么一开始会出现这种情况。现在我不需要担心那个修复或者当我改变对象时需要不断地重新生成它们。 - robhasacamera

8

1) 清理项目(cmd + shift + K)

2) 在“数据模型检查器”中,为每个创建的实体设置类属性,就像下面的截图一样。

screenshot

3) 再次生成代码(编辑器 -> 创建NSManagedObject子类)

之后一切都应该正常工作。


3
问题在于,你不再需要手动生成NSManagedObjectModel子类了。 参考:https://forums.developer.apple.com/thread/48988

Xcode会自动生成Core Data数据模型中实体和属性的类或类扩展。自动代码生成可以按实体启用或禁用,并且在使用Xcode 8文件格式创建新模型时会为所有实体启用。此功能适用于已升级到Xcode 8格式的任何数据模型。您可以使用数据模型的文件检查器指定Xcode为数据模型生成Swift或Objective-C代码。当为实体启用自动代码生成时,Xcode将根据实体检查器中指定的类名创建一个类或类扩展,并将源放置在项目的派生数据中。对于Swift和Objective-C,这些类可直接从项目的代码中使用。对于Objective-C,在模型中生成的所有实体都将有一个额外的头文件:文件名符合“DataModelName+CoreDataModel.h”的命名约定。


2

在Xcode 8.2.1中,选择菜单-产品-清理,一切都很顺利,非常可靠。


2

关闭项目并按照以下说明操作:

  1. 在 Finder 中找到你的数据库.xcdatamodeld文件。
  2. 右键点击.xcdatamodeld文件 -> 显示包内容,如果在包中再次找到(.xcdatamodel),请再次右键点击并选择“显示包内容”。你应该会得到“contents”文件。
  3. 用文本编辑器打开“contents”文件。
  4. 按下 Command-F (codeGenerationType="class") 并将所有匹配的字符串替换为空字符串。

保存并重新打开 Xcode 项目。一切应该正常工作。


1
这个不起作用。你的方法背后有什么理由吗? - Syed Tariq
同意理由会很有帮助。这对我的同事有效,所以我想确切地了解它在做什么。 - dbreaux

1

除非你真的需要修改生成的属性,否则不要与Xcode争斗,这样做只会让你感到沮丧。

把自动生成的类看作应用程序中的任何其他类。如果您需要向托管对象类添加功能,只需将类定义更改为扩展并扩展您的对象即可。

更改您的类:

class MyManagedObject : NSManagedObject { /* implementation*/ }

转换为中文:"

作为扩展:

"
extension MyManagedObject { /* implementation */ }

0

这不是一个答案,只是对选择过程的解释。

请确保您已经看到斯坦福Core Data课程中的这一部分

以下是我自己写的记录(不是100%准确):

默认选项是类定义,如果您选择此选项。它会生成子类并且可以正常工作。您将能够通过名为Tweet的类访问您的推文。这听起来不错。顺便说一句,如果这样做,它不会显示在文件导航器中。
我们最常选择的是类别/扩展,它只会生成Tweet类的扩展。您必须编写推文类本身。扩展将负责制作所有变量。即使我再次切换到类别/扩展,扩展也不会出现在导航器中。它对你而言有点隐藏。
为什么我们喜欢这个?因为很多时候我们想添加自己的代码。比如在推文中,想象一下您想添加一个静态方法,该方法从Twitter获取数据并将其转换为数据库中的推文。我们应该把代码放在哪里?那么将代码放在推文类中是一个很好的地方...如果有这样一个东西...而扩展将为您处理所有变量业务。
如果您选择手动/无代码生成,则意味着不进行任何代码生成,然后您将使用value/setValue(forKey:)。祝您好运,因为您的代码将一团糟。[即没有.propertyName = value ...您必须执行setValue(value, forKey: propertyName)。]
长话短说,我不确定为什么,但是如果您不选择创建NSManagedObject子类,它似乎仍然可以工作,但是没有展示在后台发生了什么。非常不符合直觉!

同时观看Core Data Stanford课程的现场演示:

现在我们知道我们不想使用value/set(value:forKey:)来访问所有这些内容...我们想要有Users/Tweets的子类。我们想要为所有这些关系都有vars [点符号],所以我们需要生成代码。我们这样做的方式是选择实体...然后我们到CodeGen这里。这默认情况下是类定义。这意味着它已经完成了。它已经生成了一个名为Tweet的类,并且它将与var和所有关系一起工作。那实际上并不是我们想要的。我们想要选择这个[Category/Extension]。只创建一个扩展到Tweet并添加var的内容。这是因为我们想编写Tweet类并在其中放置自己的代码。编写我们自己的类非常常见。但你仍然希望有var魔法。


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