web-dev-qa-db-ja.com

Xcode 8はiOS 10の壊れたNSManagedObjectサブクラスを生成します

IOSアプリプロジェクトを最近iOS 10に更新しました。アプリのコアデータモデルを変更しようとしていますが、Xcodeが生成する新しいNSManagedObjectサブクラスが壊れています。また、サブクラスのマニュアルを修正しようとしましたが、これは機能しません。

Core Data Modelの最小ツールバージョンは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
61
Remco Beugels

私はついに私の仕事を得ました。これが私がしたことです。 (フライトは私のエンティティの1つです)

次のようにxcdatamodeldをセットアップします

enter image description here

そして、エンティティとして

enter image description here

次に、エディタ-> NSManagedObjectサブクラスの作成を使用しました

これにより、フライトエンティティの2つのファイルが作成されます

Flights + CoreDataProperties.Swift

フライト+ CoreDataClass.Swift

私はFlights + CoreDataClass.Swiftの名前をFlights.Swiftに変更しました

フライト。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の新しいGenericsバージョンを忘れないでください

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

NSManagedObjectサブクラスファイルを生成した後にこれらのエラーが発生した理由は、データモデルが変更されたときに選択されたCodegenオプションに関係していると思われます。

これはバグだとは思いません。少なくともXcode 8.1(8B62)にはありません。

同様の問題が発生し、Codegenオプションを「Manual/None」に変更し、Moduleオプションを「Global Namespace」のままにして修正しました。 NSManagedObjectサブクラスファイルを生成しました。ただし、状況によっては、NSManagedObjectサブクラスを生成する必要さえありません。

以下は、Appleのドキュメントのレビュー、Apple開発者フォーラム、および独自のプロジェクトでのテストに基づいたエンティティCodegenオプションの詳細です。

オプション1:「クラス定義」

  • これを「プラグアンドプレイ」オプションと考えてください

  • モデルエディターを使用して、Core Dataで管理するエンティティと関連属性を作成します。

  • NSMangagedObjectサブクラスジェネレーターは使用しないでください。必要なファイルは、Xcodeによって自動的に生成されます(ただし、プロジェクトナビゲーターには表示されません)。

  • NSManagedObjectファイルを生成する場合、Appleは、これらのファイルのヘッダーコメントでこれらのファイルを編集してはならないことを通知します。これらのファイルを編集する必要がある場合、これは別のCodegenオプションを使用する必要があることを示す良い兆候です。

  • エンティティのデフォルトのクラスオプションのままにします(モジュール=グローバルネームスペース、コード生成=クラス定義)

  • NSManagedObjectのメソッドをオーバーライドする必要がある場合は、Classオプションの下のNameを使用して拡張機能を作成できます。

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

オプション2:「手動/なし」

  • NSManagedObjectサブクラスファイルを表示および編集できることを除いて、オプション1と同様です。

  • モデルエディターを使用して、Core Dataで管理するエンティティと関連属性を作成します。

  • NSManagedObjectサブクラスジェネレーターを使用する前に、エンティティのCodgenオプションを「Manual/None」に設定します。 ModuleオプションはGlobal Namespaceである必要があります。

  • 属性を追加/削除/更新した後、次の2つの選択肢があります。(1)生成されたNSManagedObjectファイルを手動で更新しますOR(2)NSManagedObjectサブクラスジェネレータを再度使用しますEntity + CoreDataProperties.Swiftファイル)。

  • 繰り返しますが、NSManagedObjectのメソッドとメソッドをオーバーライドする必要がある場合は、拡張機能を作成できます。拡張は、Entity + CoreDataProperties.Swiftファイルではなく、Entity + CoreDataClass.Swiftファイルで作成する必要があります(このファイルは、モデルエディターの変更により更新される可能性があります)。

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

オプション3:「カテゴリ/拡張機能」

  • Core Dataで管理する必要のないカスタムプロパティがある場合は、このオプションを使用します。

  • モデルエディターを使用して、Core Dataで管理するエンティティと関連属性を作成します。

  • ModuleオプションがCurrent Product Moduleに設定され、Codegenオプションが「Category/Extension」に設定されていることを確認します。

  • 自己管理するプロパティを使用して、独自のNSManagedObjectサブクラスを作成します。

  • NSMangagedObjectサブクラスジェネレーターは使用しないでください。必要なファイルは、Xcodeによって自動的に生成されます(ただし、プロジェクトナビゲーターには表示されません)。

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

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

42
Ryan H.
  1. この問題を解決するには、アプリの派生データを削除します。

  2. 次に、ModuleCurrent Product Moduleに変更し、CodegentoManual/None.

  3. List item
39
akshay

CodeGen:Manual/None Module:Current Product Moduleを設定してみてください

私が同じ問題に直面したとき、それは私のためにうまくいった。

enter image description here

17
Daniel Chepenko

これらの手順を試すことができます

  1. Xocde Project Navigatorで。xcdatamodeldファイルを選択します
  2. Data Modul Inspectorで、Codegenを確認します:Manual/None
  3. 次に編集-> NSManagedObjectサブクラスを作成
  4. 製品のクリーニングと再構築

それは仕事ですか?そうでない場合

すべてのclassEntitiesと同じ名前でないことを確認してください。これらのクラスはBuild Phases-> Compile Sourcesにあります。重複している場合、クラスまたはエンティティの名前を変更します

または

プロジェクトフォルダーでこのコマンドを実行して、エラー情報を取得できます

xcodebuild -verbose

この問題が発生したときにこのメッセージが表示されました

シンボル_OBJC_CLASS _ $ _ RandomListの複製:

xxxx/RandomList.o

xxxx/RandomList + CoreDataClass.o

RandomList.hおよびRandomList + CoreDataClass.hは、コンパイル時に同じシンボルを持ちます

Xcodeが警告を出さなかったのに、コンパイラがエラーをスローすると思う

これがあなたを助けることを願っています

10
SamBundy

レガシーアプリがあり、管理オブジェクトクラスを手動で追加し続ける場合

  1. コアデータモデルのコード生成がManual/Noneに設定されていることを確認してください
  2. コアデータモデルファイルを選択します
  3. 管理対象オブジェクトのサブクラスを作成する

screenshot of editor

7
Neil Japhtha

3番目のimportステートメントは空なので削除します。

注:これが発生する理由はわかりませんが、Xcode 8のバグだと思います。削除するだけで正常に機能します。

6
Lawrence413

Xcode 8.2.1で、私はそれを道にした:(ありがとうダニエル・チェペンコ

enter image description here

ただし、Xcode 8.2.1は、生成されたファイルに愚かなを追加します:

enter image description here

を削除するだけで、正しく実行されます。

5
Alpha Liu

モデルのPersonエンティティをCore Dataテンプレートに追加したところ、問題が発生しました。次に、そのためにNSManagedObjectサブクラスを生成しましたが、コンパイルされず、リンカーエラーが発生しました。 CodegenオプションをManual/Noneに変更して動作させることになっていることがわかりました(図の右下を参照)。 enter image description here

4
ppalancica

これはxcodeの問題で、xcodeがコアデータカテゴリクラスの間違った構文を生成するものだと思います。 1つのエンティティnsmanageobjectsubclassに対してAgentDetailsを作成しています It is creating the following classes

ここで、xcodeはAgentDetails+CoreDataClass.hおよびAgentDetails+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

3
souvickcse

[データモデルインスペクター]で、[モジュール]の下の[現在の製品モジュール]および[コード生成]の下の[手動/なし]を選択します。 (これにより、サブエンティティファイルを編集し、同じエンティティで属性を変更したときにCoreDataProperties.Swiftを再生成できます。)

enter image description here

[エディタ]メニューで[NSManagedObjectSubclassの作成]を選択できます。 XcodeはYourEntity + CoreDataClass.SwiftとYourEntity + CoreDataProperties.Swiftの2つのファイルを作成します。最新のXcode(8.2.1)がない場合、モデルインスペクターで設定したオプション/非オプションのプロパティは正しく表示されません。 YourEntity + CoreDataProperties.Swiftファイルで編集できます。

2
Ohmy

また、NSManagedObjectサブクラスを自分で追加する場合は、次の手順に従うことを忘れないでください。「。xcdatamodeld」に移動->エンティティを選択->データモデルインスペクターを表示-> Codegen->「手動/なし」を選択

これは私のために働いた。

1

Xcode 8.1は内部でモデルクラスを生成しているようです。作成された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
1
user1988055

私は以下の例を使って解決しました

作成CurrentcyPair.xcdatamodeld

CurrentcyPair.xcdatamodeldを選択し、デフォルトを選択-> エンティティ(CurrencyPair)、クラス(.ManagedCurrencyPair)

エンティティを選択し、インスペクターを開きます。データモデルのコード生成を手動/なしとして設定します

0
Wasim

私はこれを見つけました David Atkinsonからの投稿 これは何らかの方法で役立ちます。 Davidが説明した方法でコードを生成した場合。いくつかの構文エラーのあるコードを取得しましたが、エラーを修正すると、すべてが以前のように機能します。 「。」で始まるファイルはありません。もう。

私が修正しなければならない構文エラーは-不必要なインポートです-そして私のコードで公開されることを意図していないいくつかの公開プロパティ

0
tetanuss

問題を解決する多くの答えを見ることができるが、ここで実際に起こっていることの背後にある本当の理由に欠けているので、私は一粒の塩を入れています。

私はこれとまったく同じ問題に出くわしましたが、簡単な調査を行うことで次のことがわかりました。

  • Xcode 7まで、コアデータエンティティのデフォルトの動作は、開発者が対応するNSManagedObjectサブクラスの変更を手動で作成および維持する必要があったことでした。 (これは、[Create NSManagedObject subclass ..]オプションを選択するエディターメニューを使用することで実現できます。).

  • Xcode 8以降、Appleは、NSManagedObjectサブクラスを管理および維持するためのCodegenという名前の新しい設定をData Model Inspectorに追加しました。この設定のデフォルト値は「クラス定義」です。これは、コンパイル時に定義済みのエンティティに基づいてNSManagedObjectサブクラスを生成し、派生データフォルダーに配置するようXcodeに指示します。

プロジェクト内にNSManagedObjectサブクラスとXcodeが自動的に生成するサブクラスがあると、管理オブジェクトモデルが重複しているため、「複数のコマンドが生成する...」コンパイル時エラーの背後にある本当の理由につながります!!!

解決策は、両方ではなく、どちらか一方を使用することです!私は個人的にプロジェクト内で管理オブジェクトモデルを使用することを好むため、この「Codegen」設定を「Manual/None」に変更しました。モデルにロジックを追加しない場合は、プロジェクトの管理オブジェクトモデルを削除して、Xcodeに上記の設定の「クラス定義」値に基づいて処理を実行させることもできます。これは、この問題に対処する正しい方法です。

このすべてを詳細に説明している素晴らしい記事をここで見つけることができます:

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

最新のXcode 8.1ベータ(8T47)ビルドを実行しています。

エラーログ(下記参照)によると、自動生成されたファイルの2つのコピーが作成されます。 1つのコピーはXcodeプロジェクトフォルダー(Xcodeの左側のツールバーのディレクトリに表示されます)に配置され、2つ目のコピーはプロジェクトの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プロジェクトディレクトリのコピーを削除すると、すべての問題が修正されますが、これらのファイルを編集できなくなるため、意味がありません。

これは解決策とは言いませんが、むしろプロジェクトを構築するための半ばばかげた方法です。このバグがすぐに解決されることを願っています。

Error Log

0
Mike

私にとっては、NSManagedObjectを手動でサブクラス化してCocoaTouchクラスを作成しました。モジュールをCurrent Product Moduleとして設定し、CodegenをCategory/Extensionとして設定すると、うまく機能します。

0
alitosuner

私の特定のケースでは、既存のプロジェクトにCoreDataを追加しましたが、このプロジェクトには既にエンティティと同じ名前のModelクラスがありました。古いModelクラスを削除すると、そのタイプが新しいCoreData Entityクラスと衝突するため、問題が修正されました。

0
jonbauer