概要
私の問題は、 Ensemblesを使用して iCloud と同期するCore Data ベースの iOS プロジェクトでほぼ重複するものを取り除きたいということです。
- 私のアプリでは、iCloud との同期は基本的にうまく機能します。
- 問題は、永続ストアが (iCloud に接続された) Ensembles によってリーチされる前に、ユーザーが複数のデバイスで同様のオブジェクトを作成する場合です。
- これにより、事実上正しいほぼ重複が生成されます。
- これらの重複を削除する私のアプローチはうまくいかないようです。
詳細な問題
ユーザーはNSManagedObjects
、iCloud に接続する前に、さまざまなデバイスで作成できます。彼が と"対多" の関係を持つ名前付きに対して "対 1" の関係を持つNSManagedObject
名前を持っているとしましょう。これは次のようになります。
Car
NSManagedObject
Person
Car
ユーザーが 2 つのデバイスを持っていてNSManagedObjects
、各デバイスに 2 つ作成するとします。Car
「アウディ」という名前Person
と「ラファエル」という名前。両方が関係を通じて接続されました。もう一方のデバイスで、彼はCar
「BMW」という名前のデバイスPerson
と「Raphael」という名前の別のデバイスを作成します。また、相互に接続されています。これで、ユーザーは各デバイスに 2 つの類似したオブジェクトを持ちます:Person
両方とも「Raphael」という名前の 2 つのオブジェクト。
私の問題は、ユーザーがPerson
同期した後、各デバイスに「Raphael」という名前のオブジェクトが 2 つあることです。
ユーザーが永続ストアをリーチすると、オブジェクトは (アンサンブル内のオブジェクトを識別するために) uniqueIdentifiers を取得するため、これは実際には正しいです。オブジェクトは実際には異なります。しかし、これは私が修正したいものです。
私のアプローチ
このデリゲート メソッドを実装し、reparationContext の重複を削除しました。
- (BOOL)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble
shouldSaveMergedChangesInManagedObjectContext:(NSManagedObjectContext*)savingContext
reparationManagedObjectContext(NSManagedObjectContext *)reparationContext {
[reparationContext performBlockAndWait:^{
// Find duplicates
// Change relationships and only use the inserted Person object (the one from iCloud)
// Delete local Person object
[reparationContext save:nil];
}
return YES;
}
基本的に、これは最初のデバイスからのデータをマージする 2 番目のデバイスでうまく機能するようです。残念ながら、reparationContext で削除された場合でも、ローカルの人はまだ iCloud に同期されているようです。
これは、最初のデバイスが 2 番目のデバイスからの変更をマージし、2 番目のデバイスで既に削除された人を再び置き換えるため、壊れた状態につながります。後でいくつかの同期を行うと、車の関係でその人が最終的に行方不明になり、アプリは同期エラーをスローします。
問題を再現する手順
ステップ 1 (デバイス 1)
- オブジェクトを作成する
- データ: 車「アウディ」 -> 人「ラファエル (デバイス 1)」
ステップ 2 (デバイス 2)
- オブジェクトを作成する
- データ: 車「BMW」 -> 人物「ラファエル (デバイス 2)」
ステップ 3 (デバイス 1)
- ストアからのリーチ データ
- iCloudに接続
- iCloudにデータを送る
- データ: 車「アウディ」 -> 人「ラファエル (デバイス 1)」
ステップ 4 (デバイス 2)
- ストアからのリーチ データ
- iCloudに接続
- iCloud からのデータをマージする
- デバイス 2 のローカルの人をデバイス 1 の挿入された人に置き換えます
- デバイス 2 からローカルの人を削除する
- iCloudにデータを送る
- データ:
車 "Audi" -> 人物 "Raphael (Device 1)"
車 "BMW" -> 人物 "Raphael (Device 1)"
ステップ 5 (デバイス 1)
- iCloud からのデータをマージする
- デバイス 1 のローカルの人をデバイス 2 の挿入された人に置き換えます (これは発生しないはずです)。
- デバイス 1 からローカルの人を削除します (これは発生しないはずです)。
- iCloudにデータを送る
- 期待されるデータ:
車 "Audi" -> 人 "Raphael (Device 1)"
車 "BMW" -> 人 "Raphael (Device 1)" - 実際のデータ:
車 "Audi" -> 人物 "Raphael (Device 2)"
車 "BMW" -> 人物 "Raphael (Device 2)"
実際にはステップ 4 でローカル人物オブジェクト「Raphael (Device 2)」が削除されましたが、ステップ 5 でデリゲート メソッド savingContext.insertedObjects
から挿入としてポップアップされるため、iCloud に送信されたままになっているようです。shouldSaveMergedChangesInManagedObjectContext
私が理解している限り、Ensembles は最初に iCloud から変更を取得し、デリゲート メソッドを介してすべてが期待どおりかどうかをユーザーに尋ね、次に永続ストアにマージし、マージ後にデルタを iCloud に送信します。
私は何か間違ったことをしていますか?それとも、これは Ensembles のバグですか?