mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-03-28 07:38:44 +08:00
Reduce block invocations, other small performance bumps
This commit is contained in:
@@ -303,9 +303,9 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
|
||||
- (void)removeControls
|
||||
{
|
||||
NSArray *controls = [_cachedControls allValues];
|
||||
[controls enumerateObjectsUsingBlock:^(ASDisplayNode *_Nonnull node, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
for (ASDisplayNode *node in controls) {
|
||||
[node removeFromSupernode];
|
||||
}];
|
||||
}
|
||||
|
||||
[self cleanCachedControls];
|
||||
}
|
||||
|
||||
@@ -117,16 +117,18 @@
|
||||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection
|
||||
{
|
||||
for (NSString *kind in [self supplementaryKinds]) {
|
||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], [NSIndexSet indexSetWithIndex:section]);
|
||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths([self editingNodesOfKind:kind], indexPaths);
|
||||
NSMutableArray *editingNodes = [self editingNodesOfKind:kind];
|
||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(editingNodes, [NSIndexSet indexSetWithIndex:section]);
|
||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(editingNodes, indexPaths);
|
||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
|
||||
// update the section of indexpaths
|
||||
NSIndexPath *sectionIndexPath = [[NSIndexPath alloc] initWithIndex:newSection];
|
||||
NSMutableArray *updatedIndexPaths = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
|
||||
[indexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
|
||||
[updatedIndexPaths addObject:[sectionIndexPath indexPathByAddingIndex:[indexPath indexAtPosition:indexPath.length - 1]]];
|
||||
}];
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
NSUInteger newItem = [indexPath indexAtPosition:indexPath.length - 1];
|
||||
NSIndexPath *mappedIndexPath = [NSIndexPath indexPathForItem:newItem inSection:newSection];
|
||||
[updatedIndexPaths addObject:mappedIndexPath];
|
||||
}
|
||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
}
|
||||
}
|
||||
@@ -204,12 +206,13 @@
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
|
||||
[sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||
NSUInteger rowNum = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:idx];
|
||||
NSIndexPath *sectionIndex = [[NSIndexPath alloc] initWithIndex:idx];
|
||||
for (NSUInteger i = 0; i < rowNum; i++) {
|
||||
NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i];
|
||||
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection];
|
||||
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) {
|
||||
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec];
|
||||
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -224,12 +227,13 @@
|
||||
[sections addIndex:indexPath.section];
|
||||
}
|
||||
|
||||
[sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||
NSUInteger rowNum = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:idx];
|
||||
NSIndexPath *sectionIndex = [[NSIndexPath alloc] initWithIndex:idx];
|
||||
for (NSUInteger i = 0; i < rowNum; i++) {
|
||||
NSIndexPath *indexPath = [sectionIndex indexPathByAddingIndex:i];
|
||||
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection];
|
||||
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) {
|
||||
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec];
|
||||
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -302,8 +302,9 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
_editingNodes[kind] = editingNodes;
|
||||
|
||||
[_mainSerialQueue performBlockOnMainThread:^{
|
||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(_completedNodes[kind], indexPaths);
|
||||
ASDeleteElementsInMultidimensionalArrayAtIndexPaths(_completedNodes[kind], indexPaths);
|
||||
NSMutableArray *allNodes = _completedNodes[kind];
|
||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(allNodes, indexPaths);
|
||||
ASDeleteElementsInMultidimensionalArrayAtIndexPaths(allNodes, indexPaths);
|
||||
if (completionBlock) {
|
||||
completionBlock(nodes, indexPaths);
|
||||
}
|
||||
@@ -512,17 +513,19 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||
[indexSet enumerateIndexesUsingBlock:^(NSUInteger sectionIndex, BOOL *stop) {
|
||||
NSUInteger rowNum = [_dataSource dataController:self rowsInSection:sectionIndex];
|
||||
for (NSUInteger i = 0; i < rowNum; i++) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sectionIndex];
|
||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath];
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock
|
||||
indexPath:indexPath
|
||||
constrainedSize:constrainedSize
|
||||
environmentTraitCollection:environmentTraitCollection]];
|
||||
[indexSet enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger sectionIndex = range.location; sectionIndex < NSMaxRange(range); sectionIndex++) {
|
||||
NSUInteger itemCount = [_dataSource dataController:self rowsInSection:sectionIndex];
|
||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sectionIndex];
|
||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath];
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock
|
||||
indexPath:indexPath
|
||||
constrainedSize:constrainedSize
|
||||
environmentTraitCollection:environmentTraitCollection]];
|
||||
}
|
||||
}
|
||||
}];
|
||||
return contexts;
|
||||
@@ -564,10 +567,12 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
// Running these commands may result in blocking on an _editingTransactionQueue operation that started even before -beginUpdates.
|
||||
// Each subsequent command in the queue will also wait on the full asynchronous completion of the prior command's edit transaction.
|
||||
LOG(@"endUpdatesWithCompletion - %zd blocks to run", _pendingEditCommandBlocks.count);
|
||||
[_pendingEditCommandBlocks enumerateObjectsUsingBlock:^(dispatch_block_t block, NSUInteger idx, BOOL *stop) {
|
||||
LOG(@"endUpdatesWithCompletion - running block #%zd", idx);
|
||||
NSUInteger i = 0;
|
||||
for (dispatch_block_t block in _pendingEditCommandBlocks) {
|
||||
LOG(@"endUpdatesWithCompletion - running block #%zd", i);
|
||||
block();
|
||||
}];
|
||||
i += 1;
|
||||
}
|
||||
[_pendingEditCommandBlocks removeAllObjects];
|
||||
|
||||
[_editingTransactionQueue addOperationWithBlock:^{
|
||||
@@ -861,8 +866,8 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
|
||||
[_editingTransactionQueue addOperationWithBlock:^{
|
||||
LOG(@"Edit Transaction - moveRow: %@ > %@", indexPath, newIndexPath);
|
||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(_editingNodes[ASDataControllerRowNodeKind], @[indexPath]);
|
||||
NSArray *indexPaths = @[indexPath];
|
||||
NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(_editingNodes[ASDataControllerRowNodeKind], indexPaths);
|
||||
[self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions];
|
||||
|
||||
// Don't re-calculate size for moving
|
||||
@@ -876,12 +881,13 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
|
||||
- (NSArray *)indexPathsForEditingNodesOfKind:(NSString *)kind
|
||||
{
|
||||
return _editingNodes[kind] != nil ? ASIndexPathsForTwoDimensionalArray(_editingNodes[kind]) : nil;
|
||||
NSArray *nodes = _editingNodes[kind];
|
||||
return nodes != nil ? ASIndexPathsForTwoDimensionalArray(nodes) : nil;
|
||||
}
|
||||
|
||||
- (NSMutableArray *)editingNodesOfKind:(NSString *)kind
|
||||
{
|
||||
return _editingNodes[kind] != nil ? _editingNodes[kind] : [NSMutableArray array];
|
||||
return _editingNodes[kind] ? : [NSMutableArray array];
|
||||
}
|
||||
|
||||
- (NSMutableArray *)completedNodesOfKind:(NSString *)kind
|
||||
@@ -958,7 +964,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
- (void)dealloc
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[_completedNodes enumerateKeysAndObjectsUsingBlock:^(NSString *kind, NSMutableArray *sections, BOOL *stop) {
|
||||
for (NSMutableArray *sections in [_completedNodes objectEnumerator]) {
|
||||
for (NSArray *section in sections) {
|
||||
for (ASCellNode *node in section) {
|
||||
if (node.isNodeLoaded) {
|
||||
@@ -970,7 +976,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -113,11 +113,11 @@
|
||||
range.start = currentIndexPath;
|
||||
range.end = currentIndexPath;
|
||||
|
||||
[indexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
currentIndexPath = [indexPath ASIndexPathValue];
|
||||
range.start = ASIndexPathMinimum(range.start, currentIndexPath);
|
||||
range.end = ASIndexPathMaximum(range.end, currentIndexPath);
|
||||
}];
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
- (NSIndexSet *)as_indexesByMapping:(NSUInteger (^)(NSUInteger))block
|
||||
{
|
||||
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
|
||||
[self enumerateIndexesUsingBlock:^(NSUInteger idx, __unused BOOL * _Nonnull stop) {
|
||||
NSUInteger newIndex = block(idx);
|
||||
if (newIndex != NSNotFound) {
|
||||
[result addIndex:newIndex];
|
||||
[self enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger i = range.location; i < NSMaxRange(range); i++) {
|
||||
NSUInteger newIndex = block(i);
|
||||
if (newIndex != NSNotFound) {
|
||||
[result addIndex:newIndex];
|
||||
}
|
||||
}
|
||||
}];
|
||||
return result;
|
||||
@@ -49,11 +51,13 @@
|
||||
- (NSUInteger)as_indexChangeByInsertingItemsBelowIndex:(NSUInteger)index
|
||||
{
|
||||
__block NSUInteger newIndex = index;
|
||||
[self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (idx <= newIndex) {
|
||||
newIndex += 1;
|
||||
} else {
|
||||
*stop = YES;
|
||||
[self enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger i = range.location; i < NSMaxRange(range); i++) {
|
||||
if (i <= newIndex) {
|
||||
newIndex += 1;
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}
|
||||
}];
|
||||
return newIndex - index;
|
||||
@@ -64,9 +68,9 @@
|
||||
NSMutableString *result = [NSMutableString stringWithString:@"{ "];
|
||||
[self enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
if (range.length == 1) {
|
||||
[result appendFormat:@"%lu ", (unsigned long)range.location];
|
||||
[result appendFormat:@"%zu ", range.location];
|
||||
} else {
|
||||
[result appendFormat:@"%lu-%lu ", (unsigned long)range.location, (unsigned long)NSMaxRange(range)];
|
||||
[result appendFormat:@"%zu-%zu ", range.location, NSMaxRange(range) - 1];
|
||||
}
|
||||
}];
|
||||
[result appendString:@"}"];
|
||||
|
||||
@@ -148,9 +148,11 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
|
||||
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
|
||||
|
||||
_children.clear();
|
||||
[children enumerateObjectsUsingBlock:^(id<ASLayoutable> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
_children[idx] = [self layoutableToAddFromLayoutable:obj];
|
||||
}];
|
||||
NSUInteger i = 0;
|
||||
for (id<ASLayoutable> child in children) {
|
||||
_children[i] = [self layoutableToAddFromLayoutable:child];
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)childForIndex:(NSUInteger)index
|
||||
|
||||
@@ -171,8 +171,10 @@ NSArray *ASFindElementsInMultidimensionalArrayAtIndexPaths(NSMutableArray *mutab
|
||||
NSArray *ASIndexPathsForMultidimensionalArrayAtIndexSet(NSArray *multidimensionalArray, NSIndexSet *indexSet)
|
||||
{
|
||||
NSMutableArray *res = [NSMutableArray array];
|
||||
[indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
|
||||
ASRecursivelyFindIndexPathsForMultidimensionalArray(multidimensionalArray[idx], [NSIndexPath indexPathWithIndex:idx], res);
|
||||
[indexSet enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger i = range.location; i < NSMaxRange(range); i++) {
|
||||
ASRecursivelyFindIndexPathsForMultidimensionalArray(multidimensionalArray[i], [NSIndexPath indexPathWithIndex:i], res);
|
||||
}
|
||||
}];
|
||||
|
||||
return res;
|
||||
|
||||
@@ -314,8 +314,10 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
NSMutableIndexSet *allIndexes = [NSMutableIndexSet new];
|
||||
|
||||
for (_ASHierarchySectionChange *change in changes) {
|
||||
[change.indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, __unused BOOL *stop) {
|
||||
animationOptions[@(idx)] = @(change.animationOptions);
|
||||
[change.indexSet enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger i = range.location; i < NSMaxRange(range); i++) {
|
||||
animationOptions[@(i)] = @(change.animationOptions);
|
||||
}
|
||||
}];
|
||||
[allIndexes addIndexes:change.indexSet];
|
||||
}
|
||||
@@ -326,24 +328,30 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
__block ASDataControllerAnimationOptions currentOptions = 0;
|
||||
NSMutableIndexSet *currentIndexes = [NSMutableIndexSet indexSet];
|
||||
|
||||
NSEnumerationOptions options = type == _ASHierarchyChangeTypeDelete ? NSEnumerationReverse : kNilOptions;
|
||||
BOOL reverse = type == _ASHierarchyChangeTypeDelete;
|
||||
NSEnumerationOptions options = reverse ? NSEnumerationReverse : kNilOptions;
|
||||
|
||||
[allIndexes enumerateIndexesWithOptions:options usingBlock:^(NSUInteger idx, __unused BOOL * stop) {
|
||||
ASDataControllerAnimationOptions options = [animationOptions[@(idx)] integerValue];
|
||||
|
||||
// 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];
|
||||
[currentIndexes removeAllIndexes];
|
||||
[allIndexes enumerateRangesWithOptions:options usingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
NSInteger increment = reverse ? -1 : 1;
|
||||
NSUInteger start = reverse ? NSMaxRange(range) - 1 : range.location;
|
||||
NSInteger limit = reverse ? range.location - 1 : NSMaxRange(range);
|
||||
for (NSInteger i = start; i != limit; i += increment) {
|
||||
ASDataControllerAnimationOptions options = [animationOptions[@(i)] integerValue];
|
||||
|
||||
// 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];
|
||||
[currentIndexes removeAllIndexes];
|
||||
}
|
||||
|
||||
// Start a new group if needed.
|
||||
if (currentIndexes.count == 0) {
|
||||
currentOptions = options;
|
||||
}
|
||||
|
||||
[currentIndexes addIndex:i];
|
||||
}
|
||||
|
||||
// Start a new group if needed.
|
||||
if (currentIndexes.count == 0) {
|
||||
currentOptions = options;
|
||||
}
|
||||
|
||||
[currentIndexes addIndex:idx];
|
||||
}];
|
||||
|
||||
// Finish up the last group.
|
||||
|
||||
Reference in New Issue
Block a user