私のアプリはCoreDataを使用しており(Magical Recordの助けを借りて)、NSOperation
を使用してかなり高度にマルチスレッド化されています。
もちろん、スレッド/操作間でNSManagedObjectID
のみを渡すように細心の注意を払っています。
ここで、操作で対応する管理対象オブジェクトに戻るために、-existingObjectWithID:error:
を使用します。
Collection *owner = (Collection *)[localContext existingObjectWithID:self.containerId error:&error];
しかし、私が返すのはnilであり、error
はこれがエラー#13300であると言っています:NSManagedObjectReferentialIntegrityError
。
このエラーについてのドキュメントの内容は次のとおりです。
NSManagedObjectReferentialIntegrityError
Error code to denote an attempt to fire a fault pointing to an object that does not exist.
The store is accessible, but the object corresponding to the fault cannot be found.
私の場合、これは真実ではありません。そのオブジェクトは存在します。実際、そのCollection
エンティティのすべてのインスタンスをNSFetchRequest
で反復すると、それらの中にそれが見つかり、そのNSManagedObjectID
はまさに-existingObjectWithID:error:
に渡したものです。
さらに、代わりに-objectWithID:
を使用すると、正しいオブジェクトが正常に返されます。
だから私が欠けているものがあります。ここにいくつかの追加の観察/質問があります:
それで、多分私はexistingObjectWithID:error:
が何をするかに関して何かを逃していますか?ドキュメントには次のように書かれています。
If there is a managed object with the given ID already registered in the context, that object is returned directly; otherwise the corresponding object is faulted into the context.
[...]
Unlike objectWithID:, this method never returns a fault.
これは私の問題を助けません。オブジェクトに障害が発生してもかまいません。障害ではありません。実際、オブジェクトのプロパティにアクセスすると、その中の障害は次のコード行で発生します。
NSManagedObjectReferentialIntegrityError
につながる現実的なシナリオは何でしょうか?啓蒙に感謝します。
問題は、渡すNSManagedObjectID
が一時的なものであるということです。 NSManagedObjectID
のisTemporaryID
メソッドを呼び出すことで確認できます。ドキュメントから:
受信者が一時的であるかどうかを示すブール値を返します。
ほとんどのオブジェクトIDはNOを返します。管理対象オブジェクトコンテキストに挿入された新しいオブジェクトには一時IDが割り当てられ、オブジェクトが永続ストアに保存されると、永続IDに置き換えられます。
最初に変更を保存する必要があります永続ストアに、次に他のコンテキストに渡す永続的なIDを取得します。
複数のコンテキストを使用している場合は、管理対象オブジェクトIDをコンテキストAから別のコンテキストBに渡す前に、コンテキストAを保存する必要があります。保存が完了した後でのみ、そのオブジェクトにコンテキストBからアクセスできます。
-objectWithID:
は常にnil以外のオブジェクトを返しますが、ストアにバッキングオブジェクトがない場合は、使用を開始すると例外がスローされます。 -existingObjectWithID:error:
は、実際にSQLを実行し、そのオブジェクトが使用されているコンテキストにまだ登録されていない場合はI/Oを実行します。
NSManagedObjectReferentialIntegrityError = 133000
NSManagedObjectReferentialIntegrityError存在しないオブジェクトを指す障害を発生させようとする試みを示すエラーコード。ストアにアクセスできますが、障害に対応するオブジェクトが見つかりません。 Mac OS Xv10.4以降で利用できます。 CoreDataErrors.hで宣言されています。
これを参照してください ドキュメント 。
このチュートリアル あなたに役立つかもしれません。
したがって、考えられる理由は、存在しないオブジェクトをフェッチしようとしていることです。これは通常、存在しないオブジェクトのオブジェクトIDを作成しようとしたときに発生します。 objectidが返され、このobjectIdでオブジェクトを取得しようとすると、この例外がスローされます。
NSManagedObjectContextDidSave通知を処理しているときにそれらを見つけました。別のコンテキストが削除したオブジェクトの多くは、(Duh!)削除されたため、フェッチできませんでした。ただし、現在のコンテキストですでに障害が発生しているオブジェクトのように、削除されたオブジェクトの一部は問題なく表示されました。
同様の問題が発生する可能性があります。ストアを反復処理したときに見つかるオブジェクトは、削除される前にそのコンテキストにフォールトされていて、変更をそのコンテキストにマージしていないか、まだ完全にマージされていない可能性があります。
ObjectIDが一時的ではないのに、この問題が発生しました。これは、親を子MOCに設定するのを愚かに忘れたためです。
childManagedObjectContext.parent = managedObjectContext