最近、「管理対象オブジェクトのコンテキストを取得するためにAppDelegateを呼び出すべきではない」ことがわかりました。 Appleもこの推奨事項をドキュメントに入れています ここ 。これは次のようになります:
ビューコントローラは通常、アプリケーションデリゲートなどのグローバルオブジェクトからコンテキストを取得するべきではありません。これにより、アプリケーションアーキテクチャが厳格になります。ビューコントローラが独自に使用するコンテキストを作成することもできません(ネストされたコンテキストでない限り)。これは、コントローラーのコンテキストを使用して実行された操作が他のコンテキストに登録されていないことを意味する場合があります。そのため、ビューコントローラーが異なればデータに対する視点も異なります。
さらに、彼らはコンテキストを取得するための他のいくつかの方法について言及しました。今のところ、彼らがそこで何を言おうとしているのか理解できません。誰かがこの問題に光を当ててください。ステートメントをサポートするコードスニペットは大歓迎です。
[〜#〜]編集[〜#〜]
ただし、アプリケーションやドキュメント、またはViewController以外の場所からコンテキストを取得する方が簡単または適切な場合もあります。 Core Databaseアプリケーションで使用する可能性のあるいくつかのオブジェクトは、管理対象オブジェクトコンテキストへの参照を保持します。管理対象オブジェクト自体には、配列コントローラーやオブジェクトコントローラー(OS XではNSArrayControllerとNSObjectController、iOSではNSFetchedResultsController)などのCore Dataをサポートするさまざまなコントローラーオブジェクトと同様に、独自のコンテキストへの参照があります。
これらのオブジェクトの1つからコンテキストを取得すると、たとえば複数のコンテキストを使用するためにアプリケーションを再構築した場合、コードが有効なままになる可能性が高いという利点があります。たとえば、管理対象オブジェクトがあり、それに関連する新しい管理対象オブジェクトを作成する場合は、元のオブジェクトにその管理対象オブジェクトコンテキストを要求し、それを使用して新しいオブジェクトを作成できます。これにより、作成する新しいオブジェクトが元のオブジェクトと同じコンテキストにあることが保証されます。
正確には何ですか?以下の高投票の回答とは似ていないことを確認してください。誰かがAppleドキュメントのこの部分を理解するのを手伝ってくれますか?
これは依存性注入と呼ばれます。基本的に、呼び出し元/コンストラクターは、NSManagedObjectContext
を呼び出された/構築されたものに設定する必要があります。
AppDelegate
で、NSManagedObjectContext
をrootViewController
に関連付けられているUIWindow
に設定する必要があります。
次に、rootViewController
はNSManagedObjectContext
を次のViewControllerに設定する必要があります。
どうやって?これは、View Controllerクラスの単純なプロパティであり、呼び出し元は次を使用します。
[nextViewController setManagedObjectContext:[self managedObjectContext]];
シングルトンを推奨する人もいますが、それは避けるのが最善のもう1つの深い暗い穴です。
依存性注入が最良のアプローチです。
これは、Appleが設計したアプローチです。他の選択肢には、AppDelegateまたは別のシングルトンの形式が含まれます。
「コントローラー間で同じコンテキストを渡すことの欠点は、同じエンティティが2つの異なる場所で変更された場合、マージの競合を管理する必要があることです。」
これはまったく別の問題であり、not複数のNSManagedObjectContext
インスタンスで解決される予定です。実際、複数のインスタンスは状況を悪化させ、マージの競合を保証します。
そのような状況では、View Controllerは、管理対象オブジェクトの変更をリッスンし、それらに対応する必要があります。 UIで一度に2か所で更新することを不可能にします。ユーザーは一度に2つの場所に集中できないため、2番目の場所がリアルタイムで更新されます。
それがその問題に対する正しい答えです。
両方のエンティティを同じコンテキストに置くことで、それが正しく機能することを確認できます。複数のコンテキストがあると、それらは同じデータを持つメモリ内の2つのオブジェクトになり、コンテキストに保存しないと変更に気付くことができません。
ただし、ユーザーの介入なしにデータを変更しているView Controllerがある場合、別の問題が発生します。ビューコントローラは、ユーザーがデータを変更または表示するためのものです。それらはnotデータのあらゆる種類のバックグラウンド処理の場所です。
あなたが輸入の状況にあるなら、それはあなたが尋ねたものとは異なる質問です。その場合、あなたは複数のスレッド(UIスレッド、インポートスレッド)を使用していて(そうあるべきです)、必須それぞれに少なくとも1つのコンテキストがあります。
そのような状況では、マージの競合のリスクがあり、発生する状況に合わせてコーディングする必要があります。最初のステップは、NSManagedObjectContext
インスタンスのマージポリシーを変更することです。
そのドキュメントを読み間違えているのではないかと思います。
それが説明しているのは、NSManagedObjectContext
インスタンスからNSManagedObject
を取得する機能です。これは絶対に便利です。たとえば、オブジェクトを追加または編集する機能を持つViewControllerを考えてみましょう。 justNSManagedObject
をビューコントローラーにプッシュすることで、そのビューコントローラーが何に触れるかを制御および決定できます。受信ビューコントローラーは、受信したNSManagedObject
の編集を許可する必要があることを認識しています。 NSManagedObjectContext
がどのように機能しているかは関係ありません。メインで動作している可能性があり、子供で動作している可能性があり、単体テストで分離されている可能性があり、知る必要も気にする必要もありません。渡されたNSManagedObject
からのデータを表示し、ユーザーが編集内容を保存することを選択した場合は、関連するNSManagedObjectContext
を保存します。
そのドキュメントは、NSManagedObjectContext
が住むための普遍的な場所(別名シングルトン)を持つことを示唆していません。 NSManagedObjectContext
に関連付けられているNSManagedObject
にアクセスする別の方法がある場合は、アクセスしても問題がなく、間違いなくそうするのが理にかなっていることを示唆しています。
シングルトンアプローチは、マネージドオブジェクトコンテキストを取得する場合に最適です。実際にはアプリの複雑さに依存しますが、私の場合、通常は1つの管理対象オブジェクトコンテキストを保持し、変更が必要なときに一時的にネストされたコンテキストを操作します。
管理対象オブジェクトモデルとコンテキストへのパブリック参照を含むすべてのCoreData初期化メソッドを含むシングルトンベースの「DataManager」クラスを使用することで、「DataManager.h」クラスをインポートしてを呼び出すことでデータにアクセスできます。シングルトン:
// I have a method to create an object that requires the Manage Object Context, so I call it from the DataManager singleton
SomeObject *newObject = [SomeObject createObjectInContext:[[DataManager sharedInstance] managedObjectContext]];
// I have a method in DataManager to save the context
[[DataManager sharedInstance] saveContext];
それは実際には簡略化されたバージョンです。私は通常、ネストされた管理対象オブジェクトコンテキストを使用するため、管理対象オブジェクトの追加または変更がユーザーによって確認されるまで、メインの管理対象オブジェクトコンテキストは変更されません。その複雑さはすべて「DataManager」クラスに含めることができます。
これは少しトピックから外れていますが、ネストされたコンテキストについてさらに学ぶ必要がある場合:ネストされたコンテキストを使用してメインの管理対象オブジェクトコンテキストを変更しないと、深刻な問題が発生しました。この記事は、その一部が頭に浮かびましたが、ネストされたコンテキストを理解して実装するのに役立ちました。