12

私は、次の Core Data エラー ( 133000)が発生した多くのユーザーの 1 人です。

Object's persistent store is not reachable from this NSManagedObjectContext's coordinator

SO のいたるところで見たように、これは Core Data のスレッド制限によるものです。
ただし、すべての正しいスレッド制限に準拠していますが、このエラーはまだ発生しています。

以下のコードを使用して NSManagedObject を作成し、メイン スレッドで関数を実行します。

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                        selector:@selector(commitPlayer:)
                                                                          object:message];
[[NSOperationQueue mainQueue] addOperation:operation];
[operation release];

この関数はオブジェクトを作成し、完全に満足しています。
次に、オブジェクトを取得しようとする[objectContext existingObjectWithID:objectID error:&error]と、前述のエラーで nil が返されます。

念のため、@synchonized ミューテックス ロック ブロックでオブジェクト フェッチをラップしましたが、まだそのオブジェクトのフェッチに失敗しています。

手動でコンテキストを保存するとこれが修正されるようですが、この時点でDBを保存するべきではないため、オブジェクトが保存されているかどうかに関係なく、オブジェクトをフェッチしたいと考えています。

4

5 に答える 5

15

答えを見つけました。
問題はスレッドとは関係ありませんでした。それは単純に、すでに書き込みが行われていたためです (そのため、Occam の Razor を介してスレッド化の問題であると人々が想定するのはそのためです)。

このエラーが表示される本当の理由は、インターネットが言うようにスレッド化とは関係ありませんが、別の読み取り/書き込みを試みているのと同時に読み取り/書き込みが既に進行中であるためです。

[objectContext existingObjectWithID:objectID error:&error]返されるオブジェクトが実際に存在することを保証するために、データベースで I/O を実行します。ただし、私の場合、スタックの上位で既に読み取りを実行していました。

親の子を読み取ろうとしてから、各子を読み取ろうとしました。実際には、障害のあるオブジェクト[objectContext objectWithID:objectID]をフェッチし、必要に応じて適切な I/O を実行するために使用する必要があります。

これは正しい方法であるだけでなく、子エンティティのリストだけが必要な場合に 500 億個の子エンティティを読み込まないことでメモリを節約します。

誰かのために物事を明確にするのに役立つことを願っています!

于 2012-08-22T06:19:20.897 に答える
5

NSManagedObjectContextDidSaveNotification に関連した私の事例を共有したいと思います。

この問題は、Core Data スタックとの相互作用を伴うテスト ケースの UnitTests ターゲットでのみ発生しました。

ユニット テスト ターゲットの私の構成では、そのような各ケースの前に、Core Data の .sqlite3 ファイルの削除を実行し、管理対象オブジェクト コンテキストと永続ストア コーディネーターを新しい新しい状態に再インスタンス化するマクロをbeforeEach持つブロックが先行するため、データベース全体がcleanUnitTestsDatabase()新しい/次のテストケースで実行するたびにクリーンな状態になります。

現在のテスト ケースが既にパスされ、次の次のテスト ケースが既に入力されているため、現在のデータベースが削除された後に次のメソッドが呼び出されることがあったため、これが問題の原因でした。

- (void)managedObjectContextDidSaveNotification:(NSNotification *)notification {
    NSManagedObjectContext *savedContext = [notification object];

    if ([savedContext isEqual:self.mainQueueManagedObjectContext] == NO) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.mainQueueManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
        });
    }
}
于 2013-09-22T12:57:13.277 に答える
2

NSManagedObject の 2 つの読み取りが互いにクラッシュし、元の質問でエラー メッセージが生成されるというこの問題の例を示したいと思いました。しかし、これは NSManagedObjectContextDidSaveNotification が設定されていて、mergeChangesFromContextDidSaveNotification を実行している場合にのみ発生します...興味深いことに、この通知は valueForKey の読み取り時に発生していました...そこに問題があるかどうかはわかりません。

    NSArray *theEvents = nil;
NSError *error = nil;

if ([currentObject valueForKey:@"event58Identifier"]) theEvents = [eventStore calendarItemsWithExternalIdentifier:[currentObject valueForKey:@"event58Identifier"]];

そして、私はそれをどのように解決しましたか:0)

    NSArray *theEvents = nil;
NSError *error = nil;
NSString * identEvent = [currentObject valueForKey:@"event56Identifier"];

if (identEvent) theEvents = [eventStore calendarItemsWithExternalIdentifier:identEvent];

いずれにせよ、NSLog を入れて、できるだけ多くの保存を見つけてください。多くの保存や読み取りは必要ない可能性が高く、すべてを 1 回の読み取りまたは 1 回の書き込みで取得するようにしてください。

于 2013-03-13T21:52:29.520 に答える
1

私の問題は少し異なっていましたが、同じエラーが発生していました。NSManagedObjectContext異なるNSPersistentStoreCoordinators (サードパーティのライブラリ)を持つ複数の s がありました。NSManagedObjectContextDidSaveNotification通知が発生したときに競合が発生していました。つまり、NSManagedObjectContextの 1 つに、それが認識していない変更を通知しています。それは、「オブジェクトの永続ストアは、この NSManagedObjectContext のコーディネーターから到達できません」が別の言葉で言っていたことです:)

于 2013-01-23T21:25:03.387 に答える