1

データがメインモックにマージされる前に、着信同期データを処理するセカンダリ管理対象オブジェクトコンテキストがあります。残念ながら、マージポリシーの問題と思われる問題が発生しています。この問題は、通知をメインのmocにマージするときではなく、その前に...セカンダリコンテキストがそれ自体を保存しているときに発生します。

セカンダリコンテキストのマージポリシーはNSMergeByPropertyObjectTrumpMergePolicyです。このポリシーを削除してデフォルトで通常のエラーに戻すと、この問題は発生しなくなります。ただし、特にこのコンテキストでデフォルトのマージポリシーを使用したくないため、これが最初から問題である理由を理解しようとしています。

アクティブな属性を持つUserオブジェクトがあります。サーバーから同期オブジェクトが着信してユーザーを再アクティブ化すると、フローは次のようになります。

オブジェクトに変更を適用する前の初期状態は次のとおりです。

(SyncObject *) $29 = 0x0051b6f0 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 0;
...

オブジェクトに変更を適用した後、予想どおり、次のようになります。

(SyncObject *) $30 = 0x0051b6f0 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 1;
...

少し後、保存の直前に、オブジェクトがまだアクティブであることを確認しました(この場合、メモリアドレスを直接poしたため、intです)。

(int) $45 = 5355248 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 1;
...

次に、保存します。

[syncContext save:&error];

そして、マージ通知ブロックで、通知を印刷すると次のように表示されます。

updated = "{(\n    <User: 0x51b6f0> (entity: User;
id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ;
data: {\n    active = 0;\n
...

さらに悪いことに、その時点でのオブジェクトは次のように表示されます。

(int) $47 = 5355248 <User: 0x51b6f0> (entity: User; id: 0x526030 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617> ; data: {
active = 0;
...

メモリ内のオブジェクトがSQLストア内のデータによって上書きされているように見えるのはなぜですか?私が理解しているように、NSMergeByPropertyObjectTrumpMergePolicyは、メモリ内の異なる値がストア内のそれらの値の上に保存されることを意味しますが、明らかにそれは起こっていることではありません。私は本当に困っています。この問題は、サーバーからの変更が破棄されている可能性があることを示しているように思われるため、心配しています。ここで何が起こっているのかをもっと知っている人がいたら、実際に何が起こっているのかを理解したいと思います。

マージポリシーを削除すると、予想どおり、この保存によってマージエラーがスローされますが、新しい変更が「古い」と見なされる理由がわかりません。

 (NSError *) $8 = 0x00566720 Error Domain=NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)" UserInfo=0x591c90 {
conflictList=(
"NSMergeConflict (0x5df220) for NSManagedObject (0xd63a370) with objectID '0xd635310 <x-coredata://70907366-8102-4131-9230-6F60D0508047/User/p617>'
with oldVersion = 9 and newVersion = 10
and old object snapshot = {\n    active = 1;\n ...\n} 
and new cached row = {\n    active = 0;\n ... \n}"
)}

回避策:

したがって、私の場合は、メインの管理対象オブジェクトコンテキストでこの特定のオブジェクトに変更が加えられたためです。Core Data Watcherクラスを実行している(コンテキスト保存通知をリッスンしている)ため、ユーザーの変更が正しく文書化されるように、新しいものにマージする前に、そのMOCへのすべての変更を保存する必要があります。私競合を停止するには遅すぎたmergeChangesFromContextDidSaveNotification呼び出しの直前に、NSManagedObjectContextDidSaveNotificationブロックでこの保存を実行します。それをNSManagedObjectContextWillSaveNotificationに移動することにより、mainMOCは変更を永続ストアに保存し、ウォッチャーはそれらの変更を登録します。その後、セカンダリストアは、後者がキューに入れていた可能性のある変更と競合することを心配せずに、変更をmainMOCに自由にマージできます。上。

これに対する警告として、着信同期コンテキストで更新するオブジェクトをフェッチする前に、メインコンテキストでそれらのオブジェクトへの保留中の変更を保存したことを確認する必要がありました。最終的に、保存する前にオブジェクトのスナップショットを撮っていたことが判明したため、あるコンテキストで行った変更は、別のコンテキストで準備された変更と同期していませんでした。マージが以前のように行われた理由についてはまだあいまいですが、オブジェクトを変更して再度マージする前に、オブジェクトの最新バージョンがあることを確認することで、マージエラーがなくなり、マージが行われました。プロセスは必要に応じて続行されました。

4

0 に答える 0