私のCocoa/Applicationは、メインスレッド上にマネージオブジェクトコンテキストを持っています。私は私のデータを更新する必要がある場合 私のプログラムがされます:コアデータを2つのマネージオブジェクトコンテキストをマージする
- は
- サーバから新しいデータを受信新しいスレッドを起動し
- メインスレッドに通知を送信新しい管理対象オブジェクトコンテキスト
- を作成します。 2つのコンテキストをマージするために
これは、メインスレッドの通知を受信する機能である
- (void)loadManagedObjectFromNotification:(NSNotification *)saveNotification
{
if ([NSThread isMainThread]) {
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
} else {
[self performSelectorOnMainThread:@selector(loadManagedObjectFromNotification:) withObject:saveNotification waitUntilDone:YES];
}
}
エラーは表示されません。 私の問題は、マージ結果です。実際には両方のコンテキストから管理対象オブジェクトを連結しています。
マイエンティティは、属性と関係の本当に単純なリストです。
おそらく、更新された管理オブジェクトが新しいものではなく、最初のものの編集されたバージョンであることを理解するために、マージがいくつかの指示を必要とするかもしれません。 私は、Entity(IDのように動作する属性)とマージポリシーのようなものを一意に識別する方法を指定する必要があると思います(2つの管理対象オブジェクトが同じオブジェクトを表す場合は、lastModificationDateより最近)。
オブジェクトごとに1つの更新されたコピーを持つために2つのコンテキストを正しくマージする方法を理解するだけでいいです。
更新1
この問題は現在明らかです。 2つのコンテキストに大きな違いがあります:ObjectID。 メインスレッドのコンテキストがPersistent Storeコーディネータを使用してManagedObjectをフェッチしている間、2番目のスレッドはリモートURLをフェッチすることによってそれらのオブジェクトを作成します。たとえオブジェクトの内容が同じであっても、2つの異なるobjectIDを持ちます。
私のオブジェクトはすでに一意の識別子を持っていましたので、この値を設定するためにsetObjectIdを使用できます。 (Appleの文書によれば、これは良い考えではない)
オブジェクトIDが異なることは明らかです。なぜなら、ストアからオブジェクトをフェッチして更新するのではなく、オブジェクトを作成するからです。それで、私はあなたがオブジェクトを結合するために他の何かを必要としなかったという私の答えで言ったのです。とにかく、この状況を処理する適切な方法は、管理対象オブジェクトIDの使用です。管理オブジェクトIDはスレッドセーフなので、メインスレッドから別のスレッドに渡すことができます。次に、existingObjectWithID:error:を使用して、特定のIDに関連付けられたオブジェクトを取得し、更新してコンテキストを保存します。これで、マージが期待どおりに動作します。 –
また、スレッド間でどの管理対象オブジェクトIDを渡す必要があるかを事前に把握していない場合は、別のスレッドで単に述部を使用してオブジェクトをフェッチし、サーバーから取得したオブジェクトに対応するオブジェクトを取得し、コンテキストを保存します。 –
正解!問題はobjectIdsでした。フェッチを行い、既存のオブジェクトを更新する必要があるたびに、ストアからオブジェクトを取得して更新します。 – Giuseppe