Core Data アプリに iCloud 同期を実装しようとしています。私はプログラミングのプロではなく、これは実際に私が学んだ高度なトピックです... Drew McCormack による Core Data sync Framework "Ensembles" を見つけました。これにより、iCloud 同期がはるかに簡単になるようです。
アプリに統合しましたが、新しいオブジェクトを Core Data モデルに追加する限り、同期はうまく機能します。しかし、オブジェクトを削除すると、重複が作成されます。そして、重複からの重複。3〜4回のように同じエントリ(オブジェクト)を持つことになりました...
何故ですか?私は何を間違っていますか?私はいくつかの調査を行いましたが、グローバル識別子がこれを解決できると思いますか?
グローバル識別子とは何ですか? 私の推測では、重複を避けるのに役立つと思います!? しかし、どうすればこれを設定できますか?よくわからないので、いろいろ調べましたが、答えが見つかりませんでした。
手伝ってくれてありがとう!
更新: 助けてくれてありがとう! 私は readme と本を読みましたが、私は初心者なので、すべてがはっきりしているわけではありません。
Ensembles でのグローバル識別子の使用については理解できたと思いますが、それが正しく行われているかどうかはわかりません。
正しく理解できれば、各オブジェクトに識別子を割り当てる必要があります。属性に格納することでこれを行うことができます。この識別子は、一意であり、NSString である限り、何でもかまいません。
私のアプリでは、ユーザーは名前、テキスト、タイトル、日付など、さまざまなものを保存できます。このアプリは、Xcode の Master-Detail-View テンプレートに基づいており、Core Data を使用します。私の Core Data モデルには、いくつかの属性を持つエンティティが 1 つしかなく、ほとんどが文字列と NSDate です。関係も何もありません。ユーザーが「+」を押すと、新しいオブジェクトが作成され、ユーザーが入力したものを属性に保存します。
グローバル識別子を追加するために行ったことは、それを格納する新しい属性を追加することです。だから、新しいオブジェクトが作成されたとき、私はそうします
/// I did find that to use as identifier !?
NSString *taskUniqueStringKey = newManagedObject.objectID.URIRepresentation.absoluteString;
/// and store it in the attribute.
[newManagedObject setValue:taskUniqueStringKey forKey:@"coreDataObjectID"];
それから私はこれを使用します:
- (NSArray *)persistentStoreEnsemble:(CDEPersistentStoreEnsemble *)ensemble globalIdentifiersForManagedObjects:(NSArray *)objects
{
return [objects valueForKeyPath:@"coreDataObjectID"];;
}
これは私にとってはうまくいくようです。しかし、私はそれを正しくやっていますか?これは、グローバル識別子を割り当てる適切な場所ですか? 私は awakeFromInsert を持っていません!?
これが機能する場合、次の問題が発生しました。私のアプリは既に稼働しており、更新前にユーザーが保存した古いエントリにはグローバル識別子がありません。それについて私は何ができますか?私がすでに持っているものとユニークなものと私が考えることができる唯一のものは、オブジェクトが作成されたときに [NSDate date] を保存する属性だと思いました。
これを使用しようとしましたが、Ensembles は NSString のみを受け入れ、NSDate を受け入れないため失敗しました!? この日付属性を使用できますか?これは十分に一意であり、gloabl 識別子として機能しますか? はいの場合、これを日付から文字列に変換する方法のコード例を教えてください。
Ensembles との同期は非常にうまく機能します。重複はもうありません。iCloud をオフにするだけでエントリが保持され、再度オンにすると、ローカルに保存されたオブジェクトなどを失うことなく、本来のように同期されます。アンサンブルは本当にかっこいいです!同期に時間がかかることもあれば、非常に速いこともあり、2 つの異なるデバイスで短期間に編集すると、削除したばかりのオブジェクトが再び表示されるように少し混乱するなど、いくつかのマイナーな奇妙な動作が見られます。でも、それが普通だと思いませんか?異なるデバイスでアプリを使用するまでに時間がかかると、すべて正常に動作します。
私はそれを正しく理解していますか?同期のために呼び出すメソッドは1つだけです:
- (void)syncWithCompletion:(void(^)(void))completion
{
if (self.ensemble.isMerging) return;
if (!self.ensemble.isLeeched) {
[self.ensemble leechPersistentStoreWithCompletion:^(NSError *error) {
if (error) NSLog(@"Error in leech: %@", error);
if (completion) completion();
}];
}
else {
[self.ensemble mergeWithCompletion:^(NSError *error) {
if (completion) completion();
}];
}
必要に応じて呼び出すだけですか?前にリーチせずにマージを行う、または「これが実際のステータスです。今のように保存します」のような方法は他にありませんか?
アプリには、同期したいさまざまなポイントがあります。アプリの開始時と終了時が良い点になります。私のアプリでは、オブジェクトを追加して Core Data に保存するときと、オブジェクトへの変更を保存するときの 2 つの時点で同期する必要があると思います。「今すぐ同期」などのボタンを提供することもできます。これは良いアプローチですか、私はいつも電話するだけですか
[self syncWithCompletion:NULL];
出てきた別の質問。アンサンブルとの同期からオブジェクトを除外できますか? 私のアプリは、最初のアプリの起動時にチュートリアル エントリをオブジェクトとして 1 回読み込みます。どうにかしてそれが可能な場合、それらを同期したくありませんか?
助けてくれてどうもありがとう!ドイツ語のローカライズなどでお手伝いできることがあれば、お知らせください。;)