NSManagedObjectの特定のサブクラスが見つかりません


136

Core Dataを使用したアプリの開発に取り組んでいます。私が使用してインスタンスを作成したとき:

let entity = NSEntityDescription.entityForName("User", inManagedObjectContext: appDelegate.managedObjectContext)
let user = User(entity: entity, insertIntoManagedObjectContext: appDelegate.managedObjectContext)

ログに警告が表示されました:

CoreData: warning: Unable to load class named 'User' for entity 'User'.  Class not found, using default NSManagedObject instead.

どうすれば修正できますか?

また、別の質問として、NSManagedObjectサブクラスでインスタンスメソッドを定義するにはどうすればよいですか。

編集:

次のスクリーンショットのように、エンティティのクラスを指定しました。

ここに画像の説明を入力してください


7
コアデータ管理対象オブジェクトサブクラスの実装に記載されているように、エンティティークラス名の前にモジュール名を付けましたか?
マーティンR

@MartinR:私の質問の更新を参照してください。
MsrButterfly 2014

2
クラスは "YourAppName.User"である必要があります。ドキュメントを参照してください(以前のコメントのリンク)。
マーティンR

@MartinR:ご協力ありがとうございます。できます。
MsrButterfly 2014

最善の方法は、それらのクラスを削除して再作成することです。これは私にとってはうまくいった
Abhishek

回答:


220

Xcode 7の更新(最終版): モジュール名をクラスに追加する(Xcode 6およびXcode 7の初期ベータリリースのように)必要がなくなりました。Appleのドキュメント「 コアデータ管理オブジェクトサブクラスの実装」は、それに応じて更新されました。

データモデルインスペクタには、エンティティの「クラス」と「モジュール」という2つのフィールドがあります。

ここに画像の説明を入力してください

エンティティのSwift管理対象オブジェクトサブクラスを作成すると、「モジュール」フィールドが「現在の製品モジュール」に設定され、この設定により、インスタンスの作成はメインアプリケーションと単体テストの両方で機能します。管理対象オブジェクトのサブクラスに、マークを付けない@objc(classname)ください(これは、https://stackoverflow.com/a/31288029/1187415で確認されています)。

または、「モジュール」フィールドを空にして(「なし」と表示@objc(classname)されます)、管理対象オブジェクトのサブクラスにマークを付けることができます(これはhttps://stackoverflow.com/a/31287260/1187415で確認されました)。


備考:この回答は、もともとXcode 6用に書かれたものです。この問題に関して、さまざまなXcode 7ベータリリースにいくつかの変更がありました。それは多くの賛成投票とそれにリンクすることで受け入れられた回答なので、現在のXcode 7最終バージョンの状況を要約しようとしました。

私は自分で「調査」を行い、この質問と同様の質問CoreDataの両方に対するすべての回答を読み ました:警告:という名前のクラスをロードできません。そのため、具体的に記載していなくても、帰属はすべての人に適用されます。


Xcode 6の以前の回答

コアデータ管理オブジェクトサブクラスの実装に記載されているように、モデルエンティティインスペクターの[クラス]フィールドのエンティティクラス名の前に、モジュールの名前を付ける必要があります(例: "MyFirstSwiftApp.User")。


2
これは私のために働いています。質問:コアデータがフレームワークに含まれている場合、実際のアプリはまだないので、ManagedObjectサブクラス名にプレフィックスを付けるにはどうすればよいですか?
Allan Macatingrao 2014

9
@Allan:@objc(ClassName)Christerの回答で提案された方法を試すことができます。
マーティンR

8
動作しますが、エンティティインスペクターでクラス名を「APPNAME.User」に設定すると、モデルクラスを再生成できなくなります。Xcodeはプレフィックスで混乱しているようで、名前でファイル/クラスを生成しますAPPNAME。何か不足していますか?
Pascal Bourque 2014

1
静的ライブラリでコアデータを使用しているときにObjective-Cでこのエラーが発生した場合はどうなりますか?
George Taskos 2014

1
@Suragch:ようやく答えを更新しました。すべてが正しくなっていることを願っています。
マーティンR

62

サイドノートとして。同じ問題がありました。そして私がしなければならなかったすべては追加でした@objc(ClassName)は私のクラスファイル。

例:

@objc(Person)
class Person { }

そして、それは私の問題を解決しました。


1
このようにObjective-Cでtypealias(<%ProjectName%>。Person-> Person)を定義したので、それが機能します。
MsrButterfly

しかし、これはかなり優しく私のためにそれを固定なぜAppleは完全に迅速..いけない知っている、それを変換するために忘れてしまったように思える
イジーZahálkaを

7
これは、各ターゲットがCoreDataモデルを共有する複数のターゲットを持つプロジェクトがある場合に特に便利です。これらの場合、CDモデルを1つのターゲットのみで使用できるようにするため、クラス名の前にターゲットIDの名前を付けることはできません。
djbp

@djbpそして、「なぜそうでないのですか?」知りたいのですが。名前空間の概念は好きですが、MacBookをウィンドウの外に捨てたいと思っていました(拡張機能を備えたアプリがあり、拡張機能を実行するとこの問題が発生します)。名前空間を使用してこれを行うには「正しい」方法が必要ですが、それを理解することはできません。
S'pht'Kr

うん、これはワークスペースで共有データモデルを操作するときにうまくいった
naz

31

この質問への受け入れられた回答は同じ問題を解決するのに役立ちましたが、他の人に役立つだろうと思っていたという警告がありました。プロジェクト(モジュール)名にスペースが含まれている場合は、スペースをアンダースコアに置き換える必要があります。例えば:

エンティティ:MyEntityクラス:My_App_Name.MyClass


まさに探していたもの!乾杯!
manosim

AppName.ClassNameでクラス名を設定すると、Xcode 9はドットを削除し、ドットなしのクラスを作成します。そのため、これはXcode 9. *ではなくなりました。
yo2bh


9

アプリvsテストとして実行しているかどうかに応じて、アプリが探していることが問題で<appName>.<entityName>あり、テストとして実行しているときはのように見える可能性があります<appName>Tests.<entityName>。この時点(Xcode 6.1)で使用する解決策Classは、CoreData UIのフィールドに入力せず、代わりにコードで入力することです。

このコードは、アプリ対テストとして実行しているかどうかを検出し、正しいモジュール名を使用してを更新しmanagedObjectClassNameます。

lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional...
    let modelURL = NSBundle.mainBundle().URLForResource("Streak", withExtension: "momd")!
    let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)!

    // Check if we are running as test or not
    let environment = NSProcessInfo.processInfo().environment as [String : AnyObject]
    let isTest = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest"

    // Create the module name
    let moduleName = (isTest) ? "StreakTests" : "Streak"

    // Create a new managed object model with updated entity class names
    var newEntities = [] as [NSEntityDescription]
    for (_, entity) in enumerate(managedObjectModel.entities) {
        let newEntity = entity.copy() as NSEntityDescription
        newEntity.managedObjectClassName = "\(moduleName).\(entity.name)"
        newEntities.append(newEntity)
    }
    let newManagedObjectModel = NSManagedObjectModel()
    newManagedObjectModel.entities = newEntities

    return newManagedObjectModel
}()

1
私はあなたの解決策を試しましたが、NSManagedObjectを実際のクラスにキャストすると、「致命的なエラー:NSArray要素はSwift配列要素の型と一致しませんでした」と表示されます。実際にはそれ自体をキャストするときではなく、forループに入ろうとするときです。
Rodrigo Ruiz

1
この例は、モデルに何らかの継承がある場合は機能しません。新しいエンティティごとに、サブエンティティを反復処理し、作成した新しいエンティティで更新する必要もあります。
アントン

8

「My-App」のようにプロジェクト名にハイフンを使用している場合は、「My_App.MyManagedObject」のようなハイフンの代わりにアンダースコアを使用します。一般に、xcdatamodeldファイルの名前を確認し、その名前と同じプレフィックスを使用します。つまり、「My_App_1.xcdatamodeld」には接頭辞「My_App_1」が必要です。


1
ワオ。ありがとう、ありがとう、ありがとう。Appleのドキュメントのどこに小さなナゲットがあるのか​​知りたいです:)
nh32rg

5

これは同じ問題を経験している人たちを助けるかもしれません。私はSwift 2とXcode 7ベータ2でした。

ソリューション私の場合は、コメントアウトした@objc(EntityName)EntityName.swift


3

同じ警告が表示されましたが、アプリは正常に動作しているようです。問題は、最後の画面で[エディター]> [NSManagedObjectサブクラスの作成]を実行すると、ターゲットが表示またはチェックされていないデフォルトのグループの場所を使用したため、MyApp.xcodeprojが配置されている最上位のMyAppディレクトリにサブクラスが保存されていました。
代わりに、グループをMyAppサブフォルダーに変更し、MyAppターゲットを確認すると、警告は消えました。


2

上記の回答は役に立ちました。この迅速な健全性チェックにより、時間を節約できます。[プロジェクト]> [ビルドフェーズ]> [ソースのコンパイル]に移動し、「-」ボタンでxcdatamodeldとモデルファイルを削除してから、「+」ボタンでそれらをすぐに追加します。再構築-それはそれを大事にするかもしれません。


2

ちなみに、プレフィックスとして何を追加するかは気をつけてください。私のアプリは「ABC-def」と呼ばれ、Xcodeは「-」を「_」に変換しています。

ファインダーを安全に見るために、プロジェクトファイルを見つけて、データモデル(たとえば、「ABC_def.xcdatamodeld」)の内容を確認し、そこに書かれている内容を正確に使用してください!!!


1

上記の回答は、Objective-Cに関連するさまざまな問題を解決するのに役立ちました(多分それは誰かを助けるでしょう):

エンティティ名をリファクタリングした場合は、「ユーティリティパネル」の「クラス」も変更することを忘れないでください。


0

上記の答えは私を助けましたが、これは誰かを助けるかもしれません。私のようにそれらを実行しても問題が解決しない場合は、「プロジェクトをクリーンアップ」することを忘れないでください。XCode8の場合、製品>クリーン。その後、再度実行します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.