2016-05-16 13 views
0

私は最近、コアデータの新しいinitWithConcurrencyType:NSPrivateQueueConcurrencyTypeマネージドオブジェクトコンテキストの構築を試し始めました。このタイプのMOCを使用する場合は、「ブロック操作がコンテキストに対して指定されたキューで確実に実行されるように」、performBlock:またはperformBlockAndWait:を使用する必要があります。管理オブジェクトコンテキストの `performBlock:`コール内でコアデータ管理オブジェクトの作成が行われるべきですか?

この一環として、私はMOCのプライベートキューで実行するinitWithEntity:insertIntoManagedObjectContext:内部performBlock:ブロックの管理オブジェクトの作成の呼び出しを移動しました。

これは​​記事に示されている戦略に一致します。

[private performBlock:^{ 
    for (NSDictionary *jsonObject in jsonArray) { 
     NSManagedObject *mo = ... ; //Managed object that matches the incoming JSON structure 
    } 
    NSError *error = nil; 
    if (![private save:&error]) { 
     NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
     abort(); 
    } 
}]; 

私はfound myself実際に完了ブロックで新たに作成されたオブジェクトを返すvoid方法で管理対象オブジェクトを初期化してきましたが。

+ (void)managedObjectFromJSON:(NSDictionary *)json completion:(void (^)(XYZManagedObject *object))completion; 

このアーキテクチャーは、単純にJSON解析メソッドからオブジェクトを戻すのに比べて複雑です。また、これらのコンプリート・ブロック・コンストラクターで連鎖された関係管理対象オブジェクトの非同期ロードでも、この設計に関連する並行性の問題/クラッシュが発生しているようです。

私の管理対象オブジェクトのそれぞれは、performBlock:ブロック内から呼び出された完了ブロックを介して、作成されたオブジェクトを返します。

[managedObjectContextPrivateQueue performBlock:^{ 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:managedObjectContextPrivateQueue]; 
    XYZManagedObject *managedObject = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:managedObjectContextPrivateQueue]; 

    [managedObjectContextPrivateQueue save:&error] 

    completion(managedObject); 
}]; 

あるいは、管理オブジェクトはperformBlock:ブロックの外に作成され、唯一の挿入/保存する操作が内部に移動することができますか? NSEntityDescriptionメソッドはブロック外のMOCにアクセスする必要があることに注意してください。

NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:managedObjectContextPrivateQueue]; 
XYZManagedObject *managedObject = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 

[managedObjectContextPrivateQueue performBlock:^{ 
    [managedObjectContextPrivateQueue insertObject:managedObject]; 
    [managedObjectContextPrivateQueue save:&error] 
}]; 

return managedObject; 

または、おそらく私は、メソッドから直接ではなく、補完ブロックから管理オブジェクトを返し、その後、実行するためにブロックを待つperformBlockAndWait:を使用する必要があります。

マネージドオブジェクトコンテキストコールをperformBlock:プライベートキュー経由でルーティングする必要がある場合、マネージオブジェクトを作成して返す方法を教えてください。

+0

「managedObjectFromJSON:」メッセージをブロックに入れることができないのはなぜですか? –

答えて

1

MOC以外の管理対象オブジェクトを作成することができます。 -[NSManagedObjectContext insertObject:]を参照してください。

しかし、一般的にこれをやりたいとは思わないでしょう。これは、条件付きのオブジェクトを作成する場合に便利です。たとえば、ユーザーが編集する可能性のあるオブジェクトを表す管理オブジェクトがある場合は、編集用に非管理バージョンを作成し、変更を保存したときにのみMOCに挿入することができます。それは最善の方法ではありませんが、機能します。

しかし、あなたの質問は、実際にはMOCでの非同期操作に関するものです。私の意見では、管理対象オブジェクトを扱うすべてのAPIを見て、適切に非同期にする方法を理解することが最善の方法です。 は、同じMOCのperformBlock{AndWait}:の中で呼び出し元が実行されていることがわかっていない限り、メソッドから管理オブジェクトを戻す必要があります。これは、管理対象オブジェクトを作成したMOCの外部から管理対象オブジェクトに(確実に)アクセスすることができないためです。

objectIDを返すことができ、呼び出し元に関連付けられたオブジェクトを取得させることができます。それはしばしばより退屈で効率的ではありませんが、MOC境界を越える際には唯一信頼できる解決策です。

関連する問題