我正在尝试在我的核心数据应用程序中实现 iCloud 同步。我在编程方面不是那么专业,这确实是我学到的一个高级主题......我发现了 Drew McCormack 的核心数据同步框架“Ensembles”。它似乎使 iCloud 同步更容易。
我将它集成到我的应用程序中,只要我将新对象添加到我的核心数据模型中,同步就可以很好地工作。但是当我删除一个对象时,它会创建重复项。然后从重复中复制。我最终有 3-4 次相同的条目(对象)......
这是为什么?我究竟做错了什么?我做了一些研究,我的猜测是全局标识符可以解决这个问题?
什么是全局标识符?我的猜测是它们有助于避免重复!?但是我该如何设置呢?我真的不知道,做了很多研究,但找不到答案。
感谢帮助!
更新: 感谢您的帮助!我阅读了自述文件和这本书,但由于我是初学者,所以对我来说并不是一切都清楚。
我想我现在了解在 Ensembles 中使用全局标识符,但我不知道我是否正确地使用它。
如果我理解正确,我必须为每个对象分配一个标识符。我可以通过将其存储在属性中来做到这一点。这个标识符可以是任何东西,只要它是唯一的并且是一个 NSString?
在我的应用程序中,用户可以存储不同的东西,比如姓名、文本、标题、日期等。该应用程序基于 Xcode 中的 Master-Detail-View 模板并使用 Core Data。我的核心数据模型只有一个具有一些属性的实体,大多数是字符串和 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!?我可以使用这个日期属性吗,这是否足够独特并且可以用作全局标识符?如果是的话,您能否给我一个代码示例,说明如何将其从日期转换为字符串?
与 Ensembles 同步效果很好。不再有重复项,您只需关闭 iCloud 并保留条目并再次打开它,它就会像应有的那样同步,而不会丢失本地存储的对象左右。合奏真的很酷!我看到一些小的奇怪行为,例如有时同步需要很长时间,有时它真的很快,如果我在两个不同的设备上在短时间内编辑东西,它会有点混乱,就像我刚刚删除的对象重新出现一样。但我想这很正常吗?如果我在不同设备上使用该应用程序之间需要一些时间,那么一切正常。
我是否理解正确,只有一种方法可以调用同步:
- (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 时,以及保存对对象的更改时。我还可以提供一个按钮,例如“立即同步”。这是一个好方法吗?我总是打电话吗?
[self syncWithCompletion:NULL];
另一个问题出现了。我可以从与 Ensembles 同步中排除对象吗?我的应用程序在第一次应用程序启动时将教程条目作为对象加载一次。如果可能的话,我不想同步它们?
非常感谢你的帮助!如果我可以帮助您进行德语本地化等任何事情,请告诉我!;)