diff --git a/AsyncDisplayKit/Private/NSArray+Diffing.h b/AsyncDisplayKit/Private/NSArray+Diffing.h index 374096f92f..a549d45f49 100644 --- a/AsyncDisplayKit/Private/NSArray+Diffing.h +++ b/AsyncDisplayKit/Private/NSArray+Diffing.h @@ -11,8 +11,19 @@ @interface NSArray (Diffing) /** - * Uses a bottom-up memoized longest common subsequence solution to identify differences. Runs in O(mn) complexity. + * @abstract Compares two arrays, providing the insertion and deletion indexes needed to transform into the target array. + * @discussion This compares the equality of each object with `isEqual:`. + * This diffing algorithm uses a bottom-up memoized longest common subsequence solution to identify differences. + * It runs in O(mn) complexity. */ - (void)asdk_diffWithArray:(NSArray *)array insertions:(NSIndexSet **)insertions deletions:(NSIndexSet **)deletions; +/** + * @abstract Compares two arrays, providing the insertion and deletion indexes needed to transform into the target array. + * @discussion The `compareBlock` is used to identify the equality of the objects within the arrays. + * This diffing algorithm uses a bottom-up memoized longest common subsequence solution to identify differences. + * It runs in O(mn) complexity. + */ +- (void)asdk_diffWithArray:(NSArray *)array insertions:(NSIndexSet **)insertions deletions:(NSIndexSet **)deletions compareBlock:(BOOL (^)(id lhs, id rhs))comparison; + @end diff --git a/AsyncDisplayKit/Private/NSArray+Diffing.m b/AsyncDisplayKit/Private/NSArray+Diffing.m index 0cd9ad040b..00893d1416 100644 --- a/AsyncDisplayKit/Private/NSArray+Diffing.m +++ b/AsyncDisplayKit/Private/NSArray+Diffing.m @@ -12,13 +12,20 @@ - (void)asdk_diffWithArray:(NSArray *)array insertions:(NSIndexSet **)insertions deletions:(NSIndexSet **)deletions { - NSIndexSet *commonIndexes = [self _asdk_commonIndexesWithArray:array]; + [self asdk_diffWithArray:array insertions:insertions deletions:deletions compareBlock:^BOOL(id lhs, id rhs) { + return [lhs isEqual:rhs]; + }]; +} + +- (void)asdk_diffWithArray:(NSArray *)array insertions:(NSIndexSet **)insertions deletions:(NSIndexSet **)deletions compareBlock:(BOOL (^)(id lhs, id rhs))comparison +{ + NSIndexSet *commonIndexes = [self _asdk_commonIndexesWithArray:array compareBlock:comparison]; if (insertions) { NSArray *commonObjects = [self objectsAtIndexes:commonIndexes]; NSMutableIndexSet *insertionIndexes = [NSMutableIndexSet indexSet]; for (NSInteger i = 0, j = 0; i < commonObjects.count || j < array.count;) { - if (i < commonObjects.count && j < array.count && [commonObjects[i] isEqual:array[j]]) { + if (i < commonObjects.count && j < array.count && comparison(commonObjects[i], array[j])) { i++; j++; } else { [insertionIndexes addIndex:j]; @@ -39,7 +46,7 @@ } } -- (NSIndexSet *)_asdk_commonIndexesWithArray:(NSArray *)array +- (NSIndexSet *)_asdk_commonIndexesWithArray:(NSArray *)array compareBlock:(BOOL (^)(id lhs, id rhs))comparison { NSInteger lengths[self.count+1][array.count+1]; for (NSInteger i = self.count; i >= 0; i--) { @@ -56,7 +63,7 @@ NSMutableIndexSet *common = [NSMutableIndexSet indexSet]; for (NSInteger i = 0, j = 0; i < self.count && j < array.count;) { - if ([self[i] isEqual:array[j]]) { + if (comparison(self[i], array[j])) { [common addIndex:i]; i++; j++; } else if (lengths[i+1][j] >= lengths[i][j+1]) {