Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions AsyncDisplayKit/Private/_ASHierarchyChangeSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ typedef NS_ENUM(NSInteger, _ASHierarchyChangeType) {

@interface _ASHierarchyChangeSet : NSObject

/// @precondition The change set must be completed.
@property (nonatomic, strong, readonly) NSIndexSet *deletedSections;
/// @precondition The change set must be completed.
@property (nonatomic, strong, readonly) NSIndexSet *insertedSections;
/// @precondition The change set must be completed.
@property (nonatomic, strong, readonly) NSIndexSet *reloadedSections;
@property (nonatomic, strong, readonly) NSArray *insertedItems;
@property (nonatomic, strong, readonly) NSArray *deletedItems;
@property (nonatomic, strong, readonly) NSArray *reloadedItems;

/**
Get the section index after the update for the given section before the update.

@precondition The change set must be completed.
@returns The new section index, or NSNotFound if the given section was deleted.
*/
- (NSInteger)newSectionForOldSection:(NSInteger)oldSection;

@property (nonatomic, readonly) BOOL completed;

Expand Down
157 changes: 93 additions & 64 deletions AsyncDisplayKit/Private/_ASHierarchyChangeSet.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ - (instancetype)initWithChangeType:(_ASHierarchyChangeType)changeType indexSet:(
Assumes: `changes` is [_ASHierarchySectionChange] all with the same changeType
*/
+ (void)sortAndCoalesceChanges:(NSMutableArray *)changes;

/// Returns all the indexes from all the `indexSet`s of the given `_ASHierarchySectionChange` objects.
+ (NSMutableIndexSet *)allIndexesInChanges:(NSArray *)changes;
@end

@interface _ASHierarchyItemChange ()
Expand All @@ -40,26 +43,12 @@ @interface _ASHierarchyChangeSet ()

@end

@implementation _ASHierarchyChangeSet {
NSMutableIndexSet *_deletedSections;
NSMutableIndexSet *_insertedSections;
NSMutableIndexSet *_reloadedSections;
NSMutableArray *_insertedItems;
NSMutableArray *_deletedItems;
NSMutableArray *_reloadedItems;
}
@implementation _ASHierarchyChangeSet

- (instancetype)init
{
self = [super init];
if (self) {
_deletedSections = [NSMutableIndexSet new];
_insertedSections = [NSMutableIndexSet new];
_reloadedSections = [NSMutableIndexSet new];

_deletedItems = [NSMutableArray new];
_insertedItems = [NSMutableArray new];
_reloadedItems = [NSMutableArray new];

_insertItemChanges = [NSMutableArray new];
_deleteItemChanges = [NSMutableArray new];
Expand Down Expand Up @@ -110,6 +99,17 @@ - (NSArray *)itemChangesOfType:(_ASHierarchyChangeType)changeType
}
}

- (NSInteger)newSectionForOldSection:(NSInteger)oldSection
{
[self _ensureCompleted];
if ([_deletedSections containsIndex:oldSection]) {
return NSNotFound;
}

NSInteger indexAfterDeletes = oldSection - [_deletedSections countOfIndexesInRange:NSMakeRange(0, oldSection)];
return indexAfterDeletes + [_insertedSections countOfIndexesInRange:NSMakeRange(0, indexAfterDeletes)];
}

- (void)deleteItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options
{
[self _ensureNotCompleted];
Expand Down Expand Up @@ -172,9 +172,32 @@ - (void)_sortAndCoalesceChangeArrays
[_ASHierarchySectionChange sortAndCoalesceChanges:_deleteSectionChanges];
[_ASHierarchySectionChange sortAndCoalesceChanges:_insertSectionChanges];
[_ASHierarchySectionChange sortAndCoalesceChanges:_reloadSectionChanges];
[_ASHierarchyItemChange sortAndCoalesceChanges:_deleteItemChanges ignoringChangesInSections:_deletedSections];
[_ASHierarchyItemChange sortAndCoalesceChanges:_reloadItemChanges ignoringChangesInSections:_reloadedSections];
[_ASHierarchyItemChange sortAndCoalesceChanges:_insertItemChanges ignoringChangesInSections:_insertedSections];

_deletedSections = [[_ASHierarchySectionChange allIndexesInChanges:_deleteSectionChanges] copy];
_insertedSections = [[_ASHierarchySectionChange allIndexesInChanges:_insertSectionChanges] copy];
_reloadedSections = [[_ASHierarchySectionChange allIndexesInChanges:_reloadSectionChanges] copy];

// These are invalid old section indexes.
NSMutableIndexSet *deletedOrReloaded = [_deletedSections mutableCopy];
[deletedOrReloaded addIndexes:_reloadedSections];

// These are invalid new section indexes.
NSMutableIndexSet *insertedOrReloaded = [_insertedSections mutableCopy];

// Get the new section that each reloaded section index corresponds to.
[_reloadedSections enumerateIndexesUsingBlock:^(NSUInteger oldIndex, __unused BOOL * stop) {
NSUInteger newIndex = [self newSectionForOldSection:oldIndex];
if (newIndex != NSNotFound) {
[insertedOrReloaded addIndex:newIndex];
}
}];

// Ignore item reloads/deletes in reloaded/deleted sections.
[_ASHierarchyItemChange sortAndCoalesceChanges:_deleteItemChanges ignoringChangesInSections:deletedOrReloaded];
[_ASHierarchyItemChange sortAndCoalesceChanges:_reloadItemChanges ignoringChangesInSections:deletedOrReloaded];

// Ignore item inserts in reloaded(new)/inserted sections.
[_ASHierarchyItemChange sortAndCoalesceChanges:_insertItemChanges ignoringChangesInSections:insertedOrReloaded];
}
}

Expand Down Expand Up @@ -218,38 +241,46 @@ + (void)sortAndCoalesceChanges:(NSMutableArray *)changes
NSMutableArray *result = [NSMutableArray new];

__block ASDataControllerAnimationOptions currentOptions = 0;
__block NSMutableIndexSet *currentIndexes = nil;
NSUInteger lastIndex = allIndexes.lastIndex;

NSMutableIndexSet *currentIndexes = [NSMutableIndexSet indexSet];

NSEnumerationOptions options = type == _ASHierarchyChangeTypeDelete ? NSEnumerationReverse : kNilOptions;

[allIndexes enumerateIndexesWithOptions:options usingBlock:^(NSUInteger idx, __unused BOOL * stop) {
ASDataControllerAnimationOptions options = [animationOptions[@(idx)] integerValue];
BOOL endingCurrentGroup = NO;

if (currentIndexes == nil) {
// Starting a new group
currentIndexes = [NSMutableIndexSet indexSetWithIndex:idx];
currentOptions = options;
} else if (options == currentOptions) {
// Continuing the current group
[currentIndexes addIndex:idx];
} else {
endingCurrentGroup = YES;
}

BOOL endingLastGroup = (currentIndexes != nil && lastIndex == idx);

if (endingCurrentGroup || endingLastGroup) {
_ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:type indexSet:currentIndexes animationOptions:currentOptions];

// End the previous group if needed.
if (options != currentOptions && currentIndexes.count > 0) {
_ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:type indexSet:[currentIndexes copy] animationOptions:currentOptions];
[result addObject:change];
currentOptions = 0;
currentIndexes = nil;
[currentIndexes removeAllIndexes];
}

// Start a new group if needed.
if (currentIndexes.count == 0) {
currentOptions = options;
}

[currentIndexes addIndex:idx];
}];


// Finish up the last group.
if (currentIndexes.count > 0) {
_ASHierarchySectionChange *change = [[_ASHierarchySectionChange alloc] initWithChangeType:type indexSet:[currentIndexes copy] animationOptions:currentOptions];
[result addObject:change];
}

[changes setArray:result];
}

+ (NSMutableIndexSet *)allIndexesInChanges:(NSArray *)changes
{
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
for (_ASHierarchySectionChange *change in changes) {
[indexes addIndexes:change.indexSet];
}
return indexes;
}

@end

@implementation _ASHierarchyItemChange
Expand Down Expand Up @@ -301,36 +332,34 @@ + (void)sortAndCoalesceChanges:(NSMutableArray *)changes ignoringChangesInSectio

// Create new changes by grouping sorted changes by animation option
NSMutableArray *result = [NSMutableArray new];

ASDataControllerAnimationOptions currentOptions = 0;
NSMutableArray *currentIndexPaths = nil;
NSIndexPath *lastIndexPath = allIndexPaths.lastObject;

NSMutableArray *currentIndexPaths = [NSMutableArray array];

for (NSIndexPath *indexPath in allIndexPaths) {
ASDataControllerAnimationOptions options = [animationOptions[indexPath] integerValue];
BOOL endingCurrentGroup = NO;

if (currentIndexPaths == nil) {
// Starting a new group
currentIndexPaths = [NSMutableArray arrayWithObject:indexPath];
currentOptions = options;
} else if (options == currentOptions) {
// Continuing the current group
[currentIndexPaths addObject:indexPath];
} else {
endingCurrentGroup = YES;
}

BOOL endingLastGroup = (currentIndexPaths != nil && (NSOrderedSame == [lastIndexPath compare:indexPath]));

if (endingCurrentGroup || endingLastGroup) {
_ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:type indexPaths:currentIndexPaths animationOptions:currentOptions presorted:YES];
// End the previous group if needed.
if (options != currentOptions && currentIndexPaths.count > 0) {
_ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:type indexPaths:[currentIndexPaths copy] animationOptions:currentOptions presorted:YES];
[result addObject:change];
currentOptions = 0;
currentIndexPaths = nil;
[currentIndexPaths removeAllObjects];
}

// Start a new group if needed.
if (currentIndexPaths.count == 0) {
currentOptions = options;
}

[currentIndexPaths addObject:indexPath];
}


// Finish up the last group.
if (currentIndexPaths.count > 0) {
_ASHierarchyItemChange *change = [[_ASHierarchyItemChange alloc] initWithChangeType:type indexPaths:[currentIndexPaths copy] animationOptions:currentOptions presorted:YES];
[result addObject:change];
}

[changes setArray:result];
}

Expand Down