Xcode 8为iOS 10生成损坏的NSManagedObject子类

时间:2016-09-23 09:25:34

标签: core-data nsmanagedobject ios10 xcode8

我最近将iOS应用程序项目更新到iOS 10.现在我尝试更改应用程序的核心数据模型,但Xcode生成的新NSManagedObject子类已损坏。我也尝试修复子类手册,但这不起作用。

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

这是Xcode生成的代码:

$viewdefs ['<Module Name>'] =
    array(
       '<View Name>View' =>
           array(
               'templateMeta' =>
                   array(
                       ...
                       'includes' =>
                           array(
                               0 =>
                                   array(
                                       'file' => 'path/to/your/script.js',
                                   ),
                               1 =>
                                   array(
                                       'file' => 'path/to/your/script.js',
                                   ),
                           ),
                       ...
                   ),
                   ...
           ),
           ...
   );

编辑:这些是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)

}

22 个答案:

答案 0 :(得分:105)

我终于让我上班了。这就是我做的。 (航班是我的实体之一)

我按如下方式设置xcdatamodeld

enter image description here

然后是实体

enter image description here

然后我用了编辑器 - &gt;创建NSManagedObject子类

这为我的航班实体创建了两个文件

航班+ CoreDataProperties.swift

航班+ 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 ...
}

这似乎对我有用。我无法让Codegen以任何其他方式工作,即使我尝试过许多建议。

这也让我抓了一会儿,我把它作为助手添加。不要忘记使用新的Generics版本的FetchRequest,你可以做到这一点

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

答案 1 :(得分:42)

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

我不认为这是一个错误。至少在Xcode 8.1(8B62)中没有。

我遇到了类似的问题并通过将Codegen选项更改为&#34;手册/无&#34;来修复它。并将Module选项保留为&#34; Global Namespace&#34;。然后我生成了我的NSManagedObject子类文件。但是,根据您的具体情况,您甚至可能不需要生成NSManagedObject子类。

以下是我对Apple的文档,Apple开发人员论坛以及使用我自己的项目进行测试时对Codegen实体选项的更多详细信息。

选项1:&#34;课程定义&#34;

  • 将此视为&#34;即插即用&#34;选项

  • 使用模型编辑器创建实体和关联的属性 您希望Core Data管理。

  • 不要使用NSMangagedObject子类生成器。所需 Xcode会自动为您生成文件(但是他们会这样做 没有出现在你的项目导航器中。)

  • 如果您确实生成了NSManagedObject文件,Apple会告诉您 这些文件不应该在标题注释中编辑 文件。如果你确实需要编辑这些文件,那么这是个好兆头 你需要使用另一个Codegen选项。

  • 保留实体的默认类选项(Module = Global 命名空间和Codegen =类定义)

  • 如果需要覆盖NSManagedObject的方法,则可以 使用Class选项下的Name创建扩展名。

    // Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }

选项2:&#34;手动/无&#34;

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

  • 使用模型编辑器创建实体和关联的属性 您希望Core Data管理。

  • 在使用NSManagedObject子类生成器之前,请设置Codgen 选项&#34;手动/无&#34;对于实体。 Module选项应该是 全球命名空间。

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

  • 同样,如果您需要覆盖NSManagedObject中的方法,那么 可以创建一个扩展。扩展应该在。中创建 实体+ CoreDataClass.swift文件而不是 Entity + CoreDataProperties.swift文件(此文件可能会更新到期 模型编辑器的变化)。

    // Optional extension in Entity+CoreDataClass.swift extension Entity { // Override NSManagedObject methods }

选项3:&#34;类别/扩展&#34;

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

  • 使用模型编辑器创建实体和关联的属性 您希望Core Data管理。

  • 确保“模块”选项设置为“当前产品模块”和“ Codegen选项设置为&#34;类别/扩展&#34;。

  • 使用您的属性创建自己的NSManagedObject子类 将自我管理。

  • 不要使用NSMangagedObject子类生成器。所需 Xcode会自动为您生成文件(但是他们会这样做 不会出现在项目导航器中。)

    // Subclass NSManagedObject in Entity.swift class Entity: NSManagedObject { // Self managed properties }

    // Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }

答案 2 :(得分:39)

  1. 要解决此问题,请删除该应用的派生数据。

  2. 然后将模块更改为当前产品模块,并将 Codegen 中的更改更改为手动/无

  3. List item

答案 3 :(得分:17)

尝试设置CodeGen:手动/无 模块:当前产品模块

当我遇到同样的问题时,它对我有用。

enter image description here

答案 4 :(得分:10)

您可以尝试以下步骤

  1. 在Xocde Project Navigator中选择 .xcdatamodeld 文件
  2. 数据模块检查器中,确保 Codegen 手动/无
  3. 然后修改 - &gt; 创建NSManagedObject子类
  4. 清洁产品并重建
  5. 那有用吗?如果不是

    确保所有实体的名称不同。您可以在构建阶段 - &gt;中找到这些课程。 编译来源。重命名类或实体(如果它们重复)

    或者

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

    xcodebuild -verbose

    我遇到此问题时收到此消息

      

    重复符号_OBJC_CLASS _ $ _ RandomList in:

         

    xxxx / RandomList.o

         

    XXXX / RandomList + CoreDataClass.o

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

    我认为为什么Xcode没有警告你,但编译器会抛出错误

    希望这会对你有所帮助

答案 5 :(得分:7)

如果您有遗留应用,并希望继续手动添加托管对象类

  1. 确保您的核心数据模型codegen设置为手动/无
  2. 选择核心数据模型文件
  3. 创建托管对象子类
  4. screenshot of editor

答案 6 :(得分:6)

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

注意:我不知道为什么会这样,但我想这是Xcode 8中的一个错误。只需将其删除即可。

答案 7 :(得分:5)

Xcode 8.2.1 上,我顺便说一句:(感谢 Daniel Chepenko

enter image description here

Xcode 8.2.1 会在生成的文件中添加一个愚蠢的

enter image description here

只需删除,它就会正常运行。

答案 8 :(得分:4)

我刚刚遇到一个问题,我只是将模型中的Person实体添加到Core Data模板中。然后为它生成NSManagedObject子类,它不会编译,给我一个链接器错误。事实证明我应该将Codegen选项更改为Manual / None以使其工作(请参见图片的右下角部分)。enter image description here

答案 9 :(得分:3)

我认为这是一个xcode问题,xcode会为核心数据类别类生成错误的语法。 我正在为一个实体nsmanageobjectsubclass创建AgentDetails It is creating the following classes

此处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

答案 10 :(得分:2)

在数据模型检查器中,选择&#39;模块&#39;下的当前产品模块。 &#39; Codegen&#39;下的手动/无。 (这允许您在同一实体下修改属性时编辑子类文件并重新生成CoreDataProperties.swift。)

enter image description here

然后,您可以在“编辑器”菜单下选择“创建NSManagedObjectSubclass”。 Xcode将为您创建2个文件YourEntity + CoreDataClass.swift和YourEntity + CoreDataProperties.swift。请注意,如果您没有最新的Xcode(8.2.1),则您在模型检查器中设置的任何可选/非可选属性将无法正确显示。你可以编辑 YourEntity + CoreDataProperties.swift文件。

答案 11 :(得分:1)

Xcode 8.1似乎在内部生成Model Class。只需删除创建的2个类,您仍然可以使用代码中的实体。

以下是我收到的错误消息

<unknown>:0: error: filename "Recipe+CoreDataProperties.swift" used twice: '/Users/Rick/Desktop/Devslop/Rick Recipe/Recipe+CoreDataProperties.swift' and '/Users/Rick/Library/Developer/Xcode/DerivedData/Rick_Recipe-cctgjudvqobxlwetbcwmzrgxigwg/Build/Intermediates/Rick Recipe.build/Debug-iphonesimulator/Rick Recipe.build/DerivedSources/CoreDataGenerated/Rick_Recipe/Recipe+CoreDataProperties.swift'
<unknown>:0: note: filenames are used to distinguish private declarations with the same name
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1

答案 12 :(得分:1)

此外,如果您自己添加NSManagedObject子类,请不要忘记按照以下步骤操作: 转到&#39; .xcdatamodeld&#39; - &GT;选择实体 - &gt;显示数据模型检查器 - &gt; Codegen - &gt;选择&#39;手动/无&#39;

这对我有用。

答案 13 :(得分:0)

我发现这个Post from David Atkinson在某种程度上有所帮助。 如果我按照David描述的方式生成代码。我只是得到一些语法错误的代码,如果我修复错误一切都像以前一样。没有丢失的文件以&#39;开头。&#39;更多。

我必须纠正的语法错误 - 不必要的进口 - 以及一些不打算在我的代码中公开的公共财产

答案 14 :(得分:0)

我正在运行最新的Xcode 8.1 beta(8T47)版本。

根据错误日志(见下文),将创建两个自动生成的文件副本。一个副本放在Xcode项目文件夹中(在Xcode左侧工具栏的目录中可见),并在项目的DerivedData文件夹中创建第二个副本:

/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataProperties.swift
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataClass.swift

删除Xcode项目目录中的副本将解决所有问题,但证明没有意义,因为您无法再编辑这些文件......

我不会说这是一个解决方案,而只是一种半实现方式来构建项目。希望这个bug很快就能解决。

Error Log

答案 15 :(得分:0)

对我来说,我通过手动创建NSManagedObject的子类来创建CocoaTouch类。我将模块设置为Current Product Module,将Codegen设置为Category / Extension,它运行良好。

答案 16 :(得分:0)

In my particular case, I had added CoreData to an existing project which already had a Model class by the same name as my entity. Deleting the old Model class fixed the problem, as its type was colliding with the new CoreData Entity class.

答案 17 :(得分:0)

考虑到可以解决问题的很多答案,我正在撒盐  缺乏真正的原因背后的真正原因。

我偶然发现了这个相同的问题,通过快速研究,我发现:

  • 直到Xcode 7,Core Data实体的默认行为是开发人员必须手动创建和维护相应NSManagedObject子类的更改。 (这可以并且仍然可以通过使用编辑器菜单选择“创建NSManagedObject子类..”选项来实现)。

  • 从Xcode 8开始,Apple在名为 Codegen 的数据模型检查器中包括了一个新设置,用于管理和维护NSManagedObject子类。此设置的默认值为“类定义”,它告诉Xcode在编译时根据定义的实体生成NSManagedObject子类,并将其放在派生数据文件夹中。

在项目中包含我们的NSManagedObject子类+ Xcode自动生成的子类使我们了解“多重命令产生...”编译时间错误的真正原因,因为我们现在已经复制了受管对象模型!!!

然后的解决方案是使用一个或另一个,而不是同时使用!我个人更喜欢将托管对象模型包含在项目中,因此我已将“ Codegen”设置更改为“ Manual / None”。如果您不向模型添加逻辑,那么您可以选择删除项目的托管对象模型,然后让Xcode根据提及的设置的“类定义”值来执行其操作。这是处理此问题的正确方法。

您可以在此处找到一篇精彩的文章,详细说明所有这些内容:

https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041

答案 18 :(得分:-1)

在执行Create NSManagedObject子类之前,您需要做的是将CodeGen设置为Category / Extension。

答案 19 :(得分:-1)

我有一个航班实体,数据模型检查器中的这些设置对我有用:

  1. 将名称设置为空(您将看到一些灰色的“NSManagedObject”文本)。默认值将写为“Flights”,只需删除它。

  2. 模块中没有任何内容。“全局命名空间”会显示为灰色。

  3. Codegen to Manual / None。

  4. 然后转到编辑器 - &gt;创建NSManagedObject子类以创建swift文件

  5. 将Flights + CoreDataClass.swift重命名为Flights.swift

  6. 这是屏幕截图的链接(出于某种原因,imgur拒绝了它:()https://drive.google.com/file/d/0B8a3rG93GTRedkhvbWc5Ujl4Unc/view?usp=sharing

答案 20 :(得分:-1)

我用下面的例子解决了

创建 CurrentcyPair.xcdatamodeld

选择 CurrentcyPair.xcdatamodeld ,然后选择默认-> 实体(CurrencyPair),类(.ManagedCurrencyPair)

选择实体,然后打开检查器。将数据模型的代码生成设置为 Manual / None

答案 21 :(得分:-2)

重命名以下内容后:

发件人:YourEntity + CoreDataClass.swift   致:YourEntity.swift

发件人:YourEntity + CoreDataProperties.swift   收件人:YourEntityCoreDataProperties.swift

然后它的工作原理。它看起来像&#34; +&#34;引起了这个问题。