Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 351f4a9

Browse files
author
Scott Goodson
committed
Utilize NSMutableOrderedSet in ASRangeControllerBeta to ensure visible items are prioritized.
This also adopts Objective-C generics for the various collections in this class.
1 parent 344b3a4 commit 351f4a9

1 file changed

Lines changed: 20 additions & 15 deletions

File tree

AsyncDisplayKit/Details/ASRangeControllerBeta.mm

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ @interface ASRangeControllerBeta ()
2222
BOOL _rangeIsValid;
2323
BOOL _queuedRangeUpdate;
2424
ASScrollDirection _scrollDirection;
25-
NSSet *_allPreviousIndexPaths;
25+
NSSet<NSIndexPath *> *_allPreviousIndexPaths;
2626
}
2727

2828
@end
@@ -65,7 +65,7 @@ - (void)_updateVisibleNodeIndexPaths
6565
}
6666

6767
// FIXME: Consider if we need to check this separately from the range calculation below.
68-
NSArray *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self];
68+
NSArray<NSIndexPath *> *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self];
6969

7070
if (visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)...
7171
_queuedRangeUpdate = NO;
@@ -80,19 +80,22 @@ - (void)_updateVisibleNodeIndexPaths
8080
[_layoutController setVisibleNodeIndexPaths:visibleNodePaths];
8181
}
8282

83-
NSArray *allNodes = [_dataSource completedNodes];
84-
NSArray *currentSectionNodes = nil;
83+
NSArray<NSArray *> *allNodes = [_dataSource completedNodes]; // 2D array: section arrays, each containing nodes.
84+
NSArray<ASDisplayNode *> *currentSectionNodes = nil;
8585
NSInteger currentSectionIndex = -1; // Will be unequal to any indexPath.section, so we set currentSectionNodes.
8686

8787
NSUInteger numberOfSections = [allNodes count];
8888
NSUInteger numberOfNodesInSection = 0;
8989

90-
NSSet *visibleIndexPaths = [NSSet setWithArray:visibleNodePaths];
90+
NSSet<NSIndexPath *> *visibleIndexPaths = [NSSet setWithArray:visibleNodePaths];
9191
// = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:ASLayoutRangeTypeVisible];
92-
NSSet *displayIndexPaths = nil;
93-
NSSet *fetchDataIndexPaths = nil;
94-
NSMutableSet *allIndexPaths = nil;
95-
NSMutableArray *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
92+
NSSet<NSIndexPath *> *displayIndexPaths = nil;
93+
NSSet<NSIndexPath *> *fetchDataIndexPaths = nil;
94+
NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
95+
96+
// Prioritize the order in which we visit each. Visible nodes should be updated first so they are enqueued on
97+
// the network or display queues before offscreen, preloading nodes are.
98+
NSMutableOrderedSet<NSIndexPath *> *allIndexPaths = [[NSMutableOrderedSet alloc] initWithSet:visibleIndexPaths];
9699

97100
ASInterfaceState selfInterfaceState = [_dataSource interfaceStateForRangeController:self];
98101

@@ -102,20 +105,22 @@ - (void)_updateVisibleNodeIndexPaths
102105
displayIndexPaths = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:ASLayoutRangeTypeDisplay];
103106

104107
// Typically the fetchDataIndexPaths will be the largest, and be a superset of the others, though it may be disjoint.
105-
allIndexPaths = [fetchDataIndexPaths mutableCopy];
108+
// Because allIndexPaths is an NSMutableOrderedSet, this adds the non-duplicate items /after/ the existing items.
109+
// This means that during iteration, we will first visit visible, then display, then fetch data nodes.
110+
// Nodes within the visible range may be getting their first display and fetch data call too, so enqueue them first.
106111
[allIndexPaths unionSet:displayIndexPaths];
107-
[allIndexPaths unionSet:visibleIndexPaths];
108-
} else {
109-
allIndexPaths = [visibleIndexPaths mutableCopy];
112+
[allIndexPaths unionSet:fetchDataIndexPaths];
110113
}
111114

112115
// Sets are magical. Add anything we had applied interfaceState to in the last update, so we can clear any
113116
// range flags it still has enabled. Most of the time, all but a few elements are equal; a large programmatic
114117
// scroll or major main thread stall could cause entirely disjoint sets, but we must visit all.
115-
NSSet *allCurrentIndexPaths = [allIndexPaths copy];
118+
119+
// Calling set on NSMutableOrderedSet just references the underlying data store, so we must copy it.
120+
NSSet<NSIndexPath *> *allCurrentIndexPaths = [[allIndexPaths set] copy];
116121
[allIndexPaths unionSet:_allPreviousIndexPaths];
117122
_allPreviousIndexPaths = allCurrentIndexPaths;
118-
123+
119124
for (NSIndexPath *indexPath in allIndexPaths) {
120125
// Before a node / indexPath is exposed to ASRangeController, ASDataController should have already measured it.
121126
// For consistency, make sure each node knows that it should measure itself if something changes.

0 commit comments

Comments
 (0)