diff --git a/Simperium/SPChangeProcessor.m b/Simperium/SPChangeProcessor.m index 5e0509d0..2b1b8af2 100644 --- a/Simperium/SPChangeProcessor.m +++ b/Simperium/SPChangeProcessor.m @@ -313,7 +313,10 @@ - (BOOL)_processRemoteModifyWithKey:(NSString *)simperiumKey if (oldDiff.count) { // The local client version changed in the meantime, so transform the diff before applying it SPLogVerbose(@"Simperium applying transform to diff: %@", diff); - diff = [bucket.differ transform:object diff:oldDiff oldDiff:diff oldGhost:oldGhost error:&theError]; + NSDictionary *diffPreferingLocalData = [bucket.differ transform:object diff:oldDiff oldDiff:diff oldGhost:oldGhost error:&theError]; + + diff = [bucket.differ diffByMergingDiff:diff intoDiff:diffPreferingLocalData overwrite:NO]; + if (theError) { SPLogError(@"Simperium error during diff transform: %@", theError.localizedDescription); if (error) { @@ -325,7 +328,7 @@ - (BOOL)_processRemoteModifyWithKey:(NSString *)simperiumKey // Load from the ghost data so the subsequent diff is applied to the correct data // Do an extra check in case there was a problem with the transform/diff, e.g. if a client's own change was misinterpreted // as another client's change, in other words not properly acknowledged. - if (diff.count) { + if (diffPreferingLocalData.count) { [object loadMemberData:object.ghost.memberData]; [self enqueueObjectForMoreChanges:simperiumKey bucket:bucket]; } else { diff --git a/Simperium/SPDiffer.h b/Simperium/SPDiffer.h index e8dbdbae..eefd2b92 100644 --- a/Simperium/SPDiffer.h +++ b/Simperium/SPDiffer.h @@ -29,5 +29,5 @@ - (BOOL)applyDiffFromDictionary:(NSDictionary *)diff toObject:(id)object error:(NSError **)error; - (BOOL)applyGhostDiffFromDictionary:(NSDictionary *)diff toObject:(id)object error:(NSError **)error; - (NSDictionary *)transform:(id)object diff:(NSDictionary *)diff oldDiff:(NSDictionary *)oldDiff oldGhost:(SPGhost *)oldGhost error:(NSError **)error; - +- (NSDictionary *)diffByMergingDiff:(NSDictionary *)diff2 intoDiff:(NSDictionary *)diff1 overwrite:(BOOL)overwrite; @end diff --git a/Simperium/SPDiffer.m b/Simperium/SPDiffer.m index a0067b8f..c8eba4d6 100644 --- a/Simperium/SPDiffer.m +++ b/Simperium/SPDiffer.m @@ -248,7 +248,6 @@ - (NSDictionary *)transform:(id)object diff:(NSDictionary *)diff old if (!ghostValue) { SPLogError(@"Simperium error: transform diff for a ghost member (ghost %@, memberData %@) that doesn't exist (%@): %@", oldGhost, oldGhost.memberData, key, [change description]); - continue; } // Could handle some weird cases here related to dynamically adding/removing members; ignore for now @@ -289,4 +288,16 @@ - (NSDictionary *)transform:(id)object diff:(NSDictionary *)diff old return newDiff; } +- (NSDictionary *)diffByMergingDiff:(NSDictionary *)diff2 intoDiff:(NSDictionary *)diff1 overwrite:(BOOL)overwrite{ + //if overwite == NO, then only add value from diff2 if it doesn't exist in diff1 + NSMutableDictionary *combinedDiff = [diff1 mutableCopy] ?: [[NSMutableDictionary alloc] init]; + for (NSString *key in diff2) { + if (overwrite || (!overwrite && !diff1[key])) { + combinedDiff[key] = diff2[key]; + } + } + + return [combinedDiff copy]; +} + @end