受Neil Fraser,差异同步启发。
// Deprecated!
+(NSDictionary *)diffShadowAndClient:(NSArray *)client shadow:(NSArray *)shadow;
// Use below
+(NSDictionary *)diffWins:(NSArray *)wins andLoses:(NSArray *)loses;
[DS diffWins: shadow andLoses: client];
This method doesn't find out duplicate objs.
+(NSDictionary *)diffWins:(NSArray *)wins
loses:(NSArray *)loses;
// ** Now if there is no any add, delete, replace in the diff, diff will be nil. **
NSDictionary *diff = [DS diffWins: ["A"] loses: ["A"]];
// diff is nil.
// primaryKey is for finding duplicate objs.
+(NSDictionary *)diffWins:(NSArray *)wins
loses:(NSArray *)loses
primaryKey:(NSString *)key;
// This method will find out duplicate objs and pass out to you.
// You can choose which value you want to keep. return YES if you want to keep newValue.
+(NSArray *)mergeInto:(NSArray *)array
applyDiff:(NSDictionary *)diff
primaryKey:(NSString *)key
shouldReplace:(BOOL(^)(id oldValue, id newValue))shouldReplace;
差异同步逐步
您可以将此示例与Tests.m文件中的第148行测试3.1进行参考。
NSArray *remote = @[@"A", @"B", @"C"];
NSArray *client = @[@"A", @"B", @"C", @"D"]; // client add "D"
NSArray *shadow = @[@"A", @"B", @"C"]; // last synchronized result == remote
// obtain a diff from client and shadow.
NSDictionary *diff_client_shadow = [DS diffShadowAndClient: client shadow: shadow];
// create a newClient and make it equal to remote
NSArray *newClient = remote;
// obtain a new client that applied diff_remote_client and diff_client_shadow.
newClient = [DS mergeInto: newClient applyDiff: diff_client_shadow];
// obtain a diff from remote and newClient.
NSDictionary *need_to_apply_to_remote = [DS diffShadowAndClient: newClient shadow: shadow];
// assuming push diff to remote.
NSArray *newRemote = [DS mergeInto: remote applyDiff: need_to_apply_to_remote];
// assuming push successfully. save newRemote in shadow
shadow = newRemote
// shadow == newRemote == newClient = @[@"A", @"B", @"C", @"D"];
/**
Get a array that from diff and find duplicate.
@param array into the array that will be patched by diff.
@param diff diff the diff object between two dictionaries. it contains keys ("add", "delete", "replace")
@param key primaryKey
@param shouldReplace shouldReplace block sent a oldValue and newValue data and return a Boolean that you can choose that whether you want to replace it or not.
@return return array that old data merge new diff.
*/
+(NSArray *)mergeInto:(NSArray *)array
applyDiff:(NSDictionary *)diff
primaryKey:(NSString *)key
shouldReplace:(BOOL(^)(id oldValue, id newValue))shouldReplace;
您可以将此示例与DuplicateTests.m文件中的第41行测试Spec: "commitId通过,remoteHash通过,README.md中的示例"进行参考。
describe(@"commitId passed, remoteHash passed, example in README.md", ^{
NSArray *remote = @[
@{@"name": @"A", @"url": @"A"},
@{@"name": @"B", @"url": @"B"},
@{@"name": @"C", @"url": @"C"}
];
// client add "D", change A' url to A1
NSArray *client = @[
@{@"name": @"A", @"url": @"A1"},
@{@"name": @"C", @"url": @"C"},
@{@"name": @"D", @"url": @"D"}
];
// last synchronized result == remote
NSArray *shadow = @[
@{@"name": @"A", @"url": @"A"},
@{@"name": @"B", @"url": @"B"},
@{@"name": @"C", @"url": @"C"}
];
// diff
// add : [@{@"name": @"D", @"url": @"D"}]
// delete : [@{@"name": @"B", @"url": @"B"}, @{@"name": @"A", @"url": @"A"}]
// replace: [@{@"name": @A", @"url": @"A1"}]
NSDictionary *diff_client_shadow = [DS diffWins: client loses: shadow primaryKey: @"name"];
/*
// shadow @[@{@"name": @"A", @"url": @"A"},
@{@"name": @"B", @"url": @"B"},
@{@"name": @"C", @"url": @"C"}]
// diff
// add : [@{@"name": @"D", @"url": @"D"}],
// delete : [@{@"name": @"B", @"url": @"B"}, @{@"name": @"A", @"url": @"A"}]
// replace: [@{@"name": @A", @"url": @"A1"}]
*/
NSArray *newClient = remote;
newClient = [DS mergeInto: newClient
applyDiff: diff_client_shadow
primaryKey: @"name"
shouldReplace:^BOOL(id oldValue, id newValue) {
return YES;
}];
// diff newClient and remote
NSDictionary *need_to_apply_to_remote = [DS diffWins: newClient loses: remote primaryKey: @"name"];
// push diff_newClient_Remote to remote
NSArray *newRemote = [DS mergeInto: remote applyDiff: need_to_apply_to_remote];
it(@"client == remote", ^{
expect([newClient dictSort]).to.equal([newRemote dictSort]);
expect([newClient dictSort]).to.equal(@[
@{@"name": @"A", @"url": @"A1"},
@{@"name": @"C", @"url": @"C"},
@{@"name": @"D", @"url": @"D"}
]);
});
});
要运行示例项目,先从仓库克隆,然后在示例目录中运行pod install
命令。
DS通过CocoaPods提供。要安装它,只需将以下行添加到Podfile中。
将DS.h/DS.m拖动到您的项目中。
lyc2345,[email protected]
DS可在MIT许可证下使用。有关更多信息,请查看LICENSE文件。