元柔道整復師エンジニアBlog

- 元柔道整復師エンジニアBlog -

『 エンジニアをリングする。』

CoreDataのSubclass/Propertiesクラスを生成したらMultiple commands produce...によりビルトが通らなくなった

オフライン時のデータ保持のために、CoreDataを使いう機会がありそのときにつまずいたことを書いていく。

もともとCoreDataモデルをいくつか作成していて、
これまで通りに今回もCoreDataモデル(User)を新たに追加するために

  • CoreDataModel.xcdatamodelを作成する
  • CoreDataModelにEntityを追加する
  • 管理対象のオブジェクトサブクラス+CoreDataClassおよびプロパティファイル+CoreDataPropertiesを作成する

の手順で生成したあとにビルドを通してみると

:-1: Multiple commands produce '/Users/ユーザ名/Library/Developer/Xcode/DerivedData/***/Build/Intermediates.noindex/***.build/Debug-iphoneos/***.build/Objects-normal/arm64/User+CoreDataProperties.o':
1) Target 'Scheme名' (project 'App名') has compile command for Swift source files
2) Target 'Scheme名' (project 'App名') has compile command for Swift source files

:-1: Multiple commands produce '/Users/ユーザ名/Library/Developer/Xcode/DerivedData/***/Build/Intermediates.noindex/***.build/Debug-iphoneos/***.build/Objects-normal/arm64/User+CoreDataClass.o':
1) Target 'Scheme名' (project 'App名') has compile command for Swift source files
2) Target 'Scheme名' (project 'App名') has compile command for Swift source files

というエラーが発生した。

どちらもNSManagedObjectサブクラスを生成したときのUser+CoreDataPropertiesUser+CoreDataClassが影響してるみたい...

しかし、これまで通り作業手順は変えてもいないのに急になぜ!?

....と思いつつ調べてみた

※以降からは、 CoreDataから生成した管理対象のオブジェクトサブクラス〇〇+CoreDataClassとプロパティファイル〇〇+CoreDataPropertiesをまとめてNSManagedObjectと呼んでいます。

原因

どうやらXcode8以降、CoreDataからNSManagedObjectを生成する際のコード生成オプション(Codegen)設定が追加されたみたいで

これまでのようなCoreDataのEntity作成後に
手動でEditor > Create NSManagedObject Subclass...をしなくても、デフォルト状態でNSManagedObjectを自動生成してくれる仕組みになったらしい。

そこでCodegenの設定を見てみると、 f:id:CHU-BURA:20190518141834p:plain

Codegenプロパティ値は、デフォルトであるクラス定義Class Definitionとなっていた。

このClass Definitionは公式によると

Choose Class Definition If You Won't Need to Edit the Generated Logic or Properties
Choose this option when you don’t need to edit the properties or functionality of the managed object subclass and properties files that Core Data generates for you.
The generated source code doesn’t appear in your project’s source list. Xcode produces the class and properties files as part of the build process and places them in your project’s build directory.
These files regenerate whenever the related entity changes in the data model.


生成されたロジックやプロパティを編集する必要がない場合は、クラス定義(Class Definition)を選択してください。
Core Dataが生成する管理対象オブジェクトサブクラスおよびプロパティファイルのプロパティや機能を編集する必要がない場合は、このオプションを選択してください。
生成されたソースコードは、プロジェクトのソースリストには表示されません。 Xcodeは、ビルドプロセスの一部としてクラスファイルとプロパティファイルを作成し、それらをプロジェクトのビルドディレクトリに配置します。
これらのファイルは、関連するエンティティがデータモデル内で変更されるたびに再生成されます。
Generating Code | Apple Developer Documentation

要するにプロジェクト内のソースとして見えていないだけで、Class Definitionを設定した時点でNSManagedObjectが内部的に生成されていた。

そしてNSManagedObjectが生成されているにもかかわらず、
再度、手動でEditor > Create NSManagedObject Subclass...したことにより同一名のNSManagedObjectが重複してしまいコンパイルエラーが発生した。

これまで生成したCoreDataのCodegenプロパティを見てみると
Class Definitionではなく、Manula/Noneの設定がされていて、なんらかの影響でデフォルトの設定になってしまってたようだ...

解決

現在のClass Definitionを設定した状態で、そのあとに手動追加していたEditor > Create NSManagedObject Subclass...をしなければ簡単に解決はする....

しかし今回の場合は、生成したNSManagedObjectにメンバ変数やメソッドを追加したい。
→ Core Dataが生成する管理対象オブジェクトサブクラスおよびプロパティファイルのプロパティや機能を編集する必要がある。

そうなると現在の設定Class DefinitionでNSManagedObjectを生成した場合は、生成されたNSManagedObjectのロジックやプロパティを編集することができない。

そこでCodegenプロパティをManula/Noneにすることで、

  • NSManagedObjectの自動生成を無効にして
    → 同一名のNSManagedObjectによる重複エラーの回避
  • 手動Editor > Create NSManagedObject Subclass...でNSManagedObjectを生成できる。
    → NSManagedObjectのロジックやプロパティの編集が可能

f:id:CHU-BURA:20190518184359p:plain

Choose Manual/None to Edit Properties and Logic in the Managed Object Subclass
Choose this option to edit the properties in your managed object subclass, for example, to alter access modifiers, and to add additional convenience methods or business logic.
With Manual/None, Core Data doesn’t generate files to support your class. You create and maintain your class, including its properties, manually. Core Data then locates these files using the values you supply in the class name and module fields.
To generate the class and properties files initially:

  1. Choose Editor > Create NSManagedObject Subclass from the menu at the top of the screen.
  2. Select your data model, then the appropriate entity, and choose where to save the files. Xcode places both a class and a properties file into your project.

You can now see and edit both the class and properties files in your project source list.


管理対象サブクラスのプロパティとロジックを編集するには、Manula/None を選択します。
このオプションを選択すると、たとえば、アクセス修飾子を変更したり、便利なメソッドやビジネスロジックを追加したりするために、管理オブジェクトサブクラスのプロパティを編集できます。
Manual / Noneの場合、Core Dataはクラスをサポートするためのファイルを生成しません。手動でクラスを作成し、そのプロパティも含めて管理します。その後、Core Dataは、クラス名とモジュールフィールドに指定した値を使用してこれらのファイルを見つけます。
クラスファイルとプロパティファイルを最初に生成するには

  1. 画面上部のメニューから「エディタ」>「NSManagedObjectサブクラスの作成」を選択します。
  2. データモデルを選択してから適切なエンティティを選択し、ファイルの保存場所を選択します。Xcodeはクラスとプロパティファイルの両方をプロジェクトに配置します。

これで、プロジェクトソースリスト内のクラスファイルとプロパティファイルの両方を表示して編集できます。
Generating Code | Apple Developer Documentation

参考