特定のオブジェクトIDからコアデータオブジェクトを取得する方法


120

次のコードを使用して、Core DataでオブジェクトのIDを簡単に取得できます。

NSManagedObjectID *moID = [managedObject objectID];

ただし、特定のオブジェクトIDを指定して、コアデータストアからオブジェクトを取得する方法はありますか?次のように、NSFetchRequestを使用してこれを実行できることを知っています。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Document" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(objectID = %@)", myObjectID];
[fetchRequest setPredicate:predicate];

ただし、独自のフェッチ要求を開始しない方法でそれを実行したいと思います。何か案は?


しかし、フェッチリクエストの方法を使用すると、プロパティまたはリレーションをプリフェッチするように設定できるため、アクセスする際に多くのクエリよりも優れた効率が得られます。
Malhal

回答:


208

あなたが欲しい:

-(NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID
                                   error:(NSError **)error

そのIDを持つストアからオブジェクトを取得します。存在しない場合はnilを取得します。

(注意:NSManagedObjectContextには、似たような名前の2つのメソッドがあり、私をつまずきました。それらを正しく保つために、他の2つは次のとおりです。

-(NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID

... そのようなオブジェクトが実際にストアに存在するかどうかに関係なく、提供されたobjectIDで障害オブジェクトを作成します。存在しない場合は、NSManagedObjectContext'sを使用して最初にオブジェクトを挿入しない限り、障害を発生させるものはすべて失敗しますinsertObject:。これについて私が見つけた唯一の用途は、ObjectIDを保持しながら、ストアからストアへオブジェクトをコピーすることです。

-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID

... このmanagedObjectContextによってストアからフェッチされた場合、そのIDを持つオブジェクトを返します。この方法の有用性を誰かが知っている場合は、コメントしてください。)

[eta。]:最初の方法と他の2つの方法のもう1つの重要な違いは、existingObjectWithID:error:決して障害を返さないことです。常にオブジェクト全体をフェッチします。それを回避しようとしている場合(たとえば、大きなblobプロパティを持つフェッチにコストがかかるオブジェクトを操作する場合)は、objectWithID:またはobjectRegisteredForID:で賢くする必要があります。または、適切に構成されたフェッチ要求を使用してください。]


11
-(NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectIDオブジェクトがコンテキスト内にすでに存在するかどうかを確認したいだけで、それをフェッチしたくない場合に、おそらく役立ちます。
トニー

私の状況。オン-tableView:didSelectRowAtIndexPath: UIAlertViewはい/いいえが表示されていると。「はい」-オブジェクトに関するいくつかの作業があります。NSFetchedResultsControllerリモートからバックグラウンドのCoreDataアップデートを使用します。そのため、オブジェクトを保存できません。画面にアラートが表示されている間、ストレージを更新してオブジェクトを削除できます。objectIdを保存してから、アラートデリゲートでもう一度取得します。私が使用しているためNSFetchedResultsController、必要なオブジェクトはすべてこの時点ですでにコンテキストにあります。さらに、コンテキスト内にオブジェクトがない場合、CoreDataは無駄なフェッチを試みるべきではありません。
kpower 2012

いい答え、ありがとう!これらのメソッド名は本当にトリッキーです。間違ったものですべてを台無しにするのは簡単です
ジャッカル

すばらしい回答です。明確化に感謝します。障害を発生させようとする際に例外が発生するのを防ぐために最初にobjectWithId:電話をかける必要性insertObjectは、本当に私には自明ではありませんでした。
スタニスラフパンケビッチ2013

3
objectRegisteredForID:別のコンテキストの操作からのobjectIDのリストがあり、ローカルコンテキストに古いデータがある可能性があるもののみを更新する場合に便利です。これにより、オブジェクトグラフ(したがってメモリ使用量)-registeredObjectsが抑制されます。オブジェクトがコンテキストでフォールトされているかどうかを確認するために、objectIDをループしてチェックするよりも優れています。
スターリングアーチャー

4

objectWithID:はあなたが探している方法であり、これを行うには推奨される方法です。objectWithID:これを行う他の方法とは異なり、NSManagedObjectContextを効率的に使用して、オブジェクトを必要なレベルだけプルします。objectWithID:は、バッキングストレージに移動する前に、親コンテキスト、永続ストアコーディネーター、および永続ストア自体のメモリ内情報を正しく使用します。

これについては、WWDC 2012セッションの「コアデータのベストプラクティス」で詳しく説明しています。


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