0

GCD を介して、ユーザー定義の同時実行キューで同時にディスパッチされる 2 つのブロックがあります。ブロック フローのある時点で、同じセットのコア データ管理オブジェクトにアクセスする必要があります。フェッチによって明示的にではなく、対多リレーション セットを持つ既にフェッチされたオブジェクトを介して。

私が理解している限り、ブロックにはそれぞれ独自のコンテキストが必要であり、完了時に両方のコンテキストをメインスレッドのコンテキストにマージする必要があります。

ただし、2 つのコンテキストを作成してから 3 つ目のコンテキストにマージする代わりに、次のような方法があるかどうか疑問に思っています。

- (void)someMethodThatAppliesToAdisjointSetWithRange:(NSRange)range fromSharedObject:(NSManagedObject*)someSharedObject
{
  //  Do some stuff...

  //  Create sortDescriptors

  __block NSArray* entities = nil;
  dispatch_sync(dispatch_get_main_queue(), ^{
    entities = [[[someSharedObject valueForKey:@"sprites"] sortedArrayUsingDescriptors:sortDescriptors] retain];
    entities = [entities subarrayWithRange:range]
  });

  for(id anEntity in entities)
  {
    //  STRICTLY retrieve properties from the entities
    //  And do stuff with these, BUT DON'T modify the entities themselves.
  }

  //  Continue doing stuff that has nothing to do with the managed objects.
}

- (void)dispatchMethod
{

  dispatch_async(_concurrentQueue, ^{
    [self someMethodThatAppliesToAdisjointSetWithRange:NSMakeRange(0, floor(pageData.count/2.)) fromSharedObject:someSharedObject];
  });

  dispatch_async(_concurrentQueue, ^{
    [self someMethodThatAppliesToAdisjointSetWithRange:NSMakeRange(floor(pageData.count/2.), ceil(pageData.count/2.)) fromSharedObject:someSharedObject];
  });
}

上記についての私の考えは、メイン スレッドでのディスパッチが並行フロー内に同期ポイントを作成するということです。管理対象オブジェクト自体を変更することさえしていないので、問題ないはずです。ただし、テストの 1 日中のある時点で、コア データの「ステートメントはまだアクティブです」という不一致の例外が発生しました。だから今、彼は上記のコードはまだ安全ではないと考えています。ただし、例外は実際にはアプリ内の他のコードによって引き起こされた可能性があります。

何かご意見は?

4

1 に答える 1

0

経験的な答えは NO です。おそらく、managedObject 内のリレーションシップへのあらゆる種類のアクセスが失敗する可能性があり、コンテキストがリレーションシップ内のオブジェクトを暗黙的に取得する必要があるためです。

あれは、

for(id anEntity in entities)
  {
    //  STRICTLY retrieve properties from the entities
    //  And do stuff with these, BUT DON'T modify the entities themselves.
  }

引き続き managedObjectContext へのアクセスが必要です。

提案されたアプローチの代わりに 2 つのローカル コンテキストを使用する同じコードでは、"Statement is still active" 例外は発生しません。

于 2012-10-15T06:31:06.437 に答える