系统检测同步冲突的方式
- 版本号机制:iCloud 会为每个数据项维护版本号。当不同设备对数据进行修改时,版本号会递增。如果多个设备同时修改数据,设备上传的版本号不一致,iCloud 就会检测到冲突。
- 时间戳:记录数据修改的时间。如果两个修改的时间非常接近,且来自不同设备,可能产生冲突。iCloud 通过比较时间戳来判断修改顺序,进而发现冲突。
代码层面处理冲突的方法
- 自动解决冲突
- (BOOL)iCloudKeyValueStore:(ICKeyValueStore *)store
resolveConflictForRecordWithID:(NSUUID *)recordID
recordChange:(ICRecord *)recordChange
serverChange:(ICRecord *)serverRecordChange
{
if ([recordChange.modificationDate compare:serverRecordChange.modificationDate] == NSOrderedDescending) {
// 本地修改时间更新,使用本地记录
[store setCloudRecord:recordChange forRecordID:recordID];
} else {
// 服务器修改时间更新,使用服务器记录
[store setCloudRecord:serverRecordChange forRecordID:recordID];
}
return YES;
}
- **合并策略**:对于某些类型的数据,如数组或字典,可以进行合并。例如,假设数据是一个字典,不同设备添加了不同的键值对。
- (BOOL)iCloudKeyValueStore:(ICKeyValueStore *)store
resolveConflictForRecordWithID:(NSUUID *)recordID
recordChange:(ICRecord *)recordChange
serverChange:(ICRecord *)serverRecordChange
{
NSMutableDictionary *localDict = [recordChange.value mutableCopy];
NSMutableDictionary *serverDict = [serverRecordChange.value mutableCopy];
[localDict addEntriesFromDictionary:serverDict];
ICValue *mergedValue = [ICValue valueWithDictionary:localDict];
ICRecord *mergedRecord = [ICRecord recordWithValue:mergedValue recordID:recordID];
[store setCloudRecord:mergedRecord forRecordID:recordID];
return YES;
}
- 手动解决冲突
- 用户提示:弹出提示框告知用户存在冲突,并展示不同版本的数据,让用户选择使用哪个版本。
- (BOOL)iCloudKeyValueStore:(ICKeyValueStore *)store
resolveConflictForRecordWithID:(NSUUID *)recordID
recordChange:(ICRecord *)recordChange
serverChange:(ICRecord *)serverRecordChange
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"同步冲突"
message:@"检测到同步冲突,请选择要保留的数据"
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"使用本地数据" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[store setCloudRecord:recordChange forRecordID:recordID];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"使用服务器数据" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[store setCloudRecord:serverRecordChange forRecordID:recordID];
}]];
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootViewController presentViewController:alertController animated:YES completion:nil];
return NO;
}