@@ -16,8 +16,10 @@ @interface ASFlowLayoutController() {
1616 std::pair<int , int > _visibleRangeStartPos;
1717 std::pair<int , int > _visibleRangeEndPos;
1818
19- std::pair<int , int > _rangeStartPos;
20- std::pair<int , int > _rangeEndPos;
19+ std::vector<std::pair<int , int >> _rangeStartPos;
20+ std::vector<std::pair<int , int >> _rangeEndPos;
21+
22+ std::vector<ASRangeTuningParameters> _tuningParameterMap;
2123}
2224
2325@end
@@ -31,13 +33,52 @@ - (instancetype)initWithScrollOption:(ASFlowLayoutDirection)layoutDirection {
3133
3234 _layoutDirection = layoutDirection;
3335
34- _tuningParameters.leadingBufferScreenfuls = 2 ;
35- _tuningParameters.trailingBufferScreenfuls = 1 ;
36+ _tuningParameterMap = {
37+ {
38+ // Render
39+ .leadingBufferScreenfuls = 1 ,
40+ .trailingBufferScreenfuls = 1
41+ },
42+ {
43+ // Preload
44+ .leadingBufferScreenfuls = 2 ,
45+ .trailingBufferScreenfuls = 2
46+ }
47+ };
3648
3749 return self;
3850}
3951
40- - (void )insertNodesAtIndexPaths : (NSArray *)indexPaths withSizes : (NSArray *)nodeSizes {
52+ #pragma mark - Tuning Parameters
53+
54+ - (ASRangeTuningParameters)tuningParametersForRange : (ASLayoutRange)range
55+ {
56+ ASDisplayNodeAssert (range < _tuningParameterMap.size (), @" Requesting a range that is OOB for the configured tuning parameters" );
57+ return _tuningParameterMap[range];
58+ }
59+
60+ - (void )setTuningParameters : (ASRangeTuningParameters)tuningParameters forRange : (ASLayoutRange)range
61+ {
62+ ASDisplayNodeAssert (range < _tuningParameterMap.size (), @" Requesting a range that is OOB for the configured tuning parameters" );
63+ _tuningParameterMap[range] = tuningParameters;
64+ }
65+
66+ // Support for the deprecated tuningParameters property
67+ - (ASRangeTuningParameters)tuningParameters
68+ {
69+ return [self tuningParametersForRange: ASLayoutRangeRender];
70+ }
71+
72+ // Support for the deprecated tuningParameters property
73+ - (void )setTuningParameters : (ASRangeTuningParameters)tuningParameters
74+ {
75+ [self setTuningParameters: tuningParameters forRange: ASLayoutRangeRender];
76+ }
77+
78+ #pragma mark - Editing
79+
80+ - (void )insertNodesAtIndexPaths : (NSArray *)indexPaths withSizes : (NSArray *)nodeSizes
81+ {
4182 ASDisplayNodeAssert (indexPaths.count == nodeSizes.count , @" Inconsistent index paths and node size" );
4283
4384 [indexPaths enumerateObjectsUsingBlock: ^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
@@ -46,14 +87,16 @@ - (void)insertNodesAtIndexPaths:(NSArray *)indexPaths withSizes:(NSArray *)nodeS
4687 }];
4788}
4889
49- - (void )deleteNodesAtIndexPaths : (NSArray *)indexPaths {
90+ - (void )deleteNodesAtIndexPaths : (NSArray *)indexPaths
91+ {
5092 [indexPaths enumerateObjectsWithOptions: NSEnumerationReverse usingBlock: ^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
5193 std::vector<CGSize> &v = _nodeSizes[indexPath.section];
5294 v.erase (v.begin () + indexPath.row );
5395 }];
5496}
5597
56- - (void )insertSections : (NSArray *)sections atIndexSet : (NSIndexSet *)indexSet {
98+ - (void )insertSections : (NSArray *)sections atIndexSet : (NSIndexSet *)indexSet
99+ {
57100 __block int cnt = 0 ;
58101 [indexSet enumerateIndexesUsingBlock: ^(NSUInteger idx, BOOL *stop) {
59102 NSArray *nodes = sections[cnt++];
@@ -69,57 +112,77 @@ - (void)insertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet {
69112}
70113
71114- (void )deleteSectionsAtIndexSet : (NSIndexSet *)indexSet {
72- [indexSet enumerateIndexesWithOptions: NSEnumerationReverse usingBlock: ^(NSUInteger idx, BOOL *stop) {
115+ [indexSet enumerateIndexesWithOptions: NSEnumerationReverse usingBlock: ^(NSUInteger idx, BOOL *stop)
116+ {
73117 _nodeSizes.erase (_nodeSizes.begin () +idx);
74118 }];
75119}
76120
77- - (BOOL )shouldUpdateForVisibleIndexPath : (NSArray *)indexPaths
78- viewportSize : (CGSize)viewportSize {
121+ #pragma mark - Visible Indices
122+
123+ - (BOOL )shouldUpdateForVisibleIndexPaths : (NSArray *)indexPaths viewportSize : (CGSize)viewportSize range : (ASLayoutRange)range
124+ {
79125 if (!indexPaths.count ) {
80126 return NO ;
81127 }
82128
129+ std::pair<int , int > rangeStartPos, rangeEndPos;
130+
131+ if (range < _rangeStartPos.size () && range < _rangeEndPos.size ()) {
132+ rangeStartPos = _rangeStartPos[range];
133+ rangeEndPos = _rangeEndPos[range];
134+ }
135+
83136 std::pair<int , int > startPos, endPos;
84137 ASFindIndexPathRange (indexPaths, startPos, endPos);
85138
86- if (_rangeStartPos >= startPos || _rangeEndPos <= endPos) {
139+ if (rangeStartPos >= startPos || rangeEndPos <= endPos) {
87140 return YES ;
88141 }
89142
90- return ASFlowLayoutDistance (startPos, _visibleRangeStartPos, _nodeSizes) > ASFlowLayoutDistance (_visibleRangeStartPos, _rangeStartPos, _nodeSizes) * kASFlowLayoutControllerRefreshingThreshold ||
91- ASFlowLayoutDistance (endPos, _visibleRangeEndPos, _nodeSizes) > ASFlowLayoutDistance (_visibleRangeEndPos, _rangeEndPos, _nodeSizes) * kASFlowLayoutControllerRefreshingThreshold ;
143+ return ASFlowLayoutDistance (startPos, _visibleRangeStartPos, _nodeSizes) > ASFlowLayoutDistance (_visibleRangeStartPos, rangeStartPos, _nodeSizes) * kASFlowLayoutControllerRefreshingThreshold ||
144+ ASFlowLayoutDistance (endPos, _visibleRangeEndPos, _nodeSizes) > ASFlowLayoutDistance (_visibleRangeEndPos, rangeEndPos, _nodeSizes) * kASFlowLayoutControllerRefreshingThreshold ;
145+ }
146+
147+ - (BOOL )shouldUpdateForVisibleIndexPath : (NSArray *)indexPaths
148+ viewportSize : (CGSize)viewportSize
149+ {
150+ return [self shouldUpdateForVisibleIndexPaths: indexPaths viewportSize: viewportSize range: ASLayoutRangeRender];
92151}
93152
94- - (void )setVisibleNodeIndexPaths : (NSArray *)indexPaths {
153+ - (void )setVisibleNodeIndexPaths : (NSArray *)indexPaths
154+ {
95155 ASFindIndexPathRange (indexPaths, _visibleRangeStartPos, _visibleRangeEndPos);
96156}
97157
98158/* *
99159 * IndexPath array for the element in the working range.
100160 */
101- - (NSSet *)indexPathsForScrolling : (enum ASScrollDirection)scrollDirection
102- viewportSize : (CGSize)viewportSize {
103- std::pair<int , int > startIter, endIter;
161+
162+ - (NSSet *)indexPathsForScrolling : (enum ASScrollDirection)scrollDirection viewportSize : (CGSize)viewportSize range : (ASLayoutRange)range
163+ {
164+ CGFloat viewportScreenMetric;
165+ ASScrollDirection leadingDirection;
104166
105167 if (_layoutDirection == ASFlowLayoutDirectionHorizontal) {
106168 ASDisplayNodeAssert (scrollDirection == ASScrollDirectionNone || scrollDirection == ASScrollDirectionLeft || scrollDirection == ASScrollDirectionRight, @" Invalid scroll direction" );
107169
108- CGFloat backScreens = scrollDirection == ASScrollDirectionLeft ? self.tuningParameters .leadingBufferScreenfuls : self.tuningParameters .trailingBufferScreenfuls ;
109- CGFloat frontScreens = scrollDirection == ASScrollDirectionLeft ? self.tuningParameters .trailingBufferScreenfuls : self.tuningParameters .leadingBufferScreenfuls ;
110-
111- startIter = ASFindIndexForRange (_nodeSizes, _visibleRangeStartPos, - backScreens * viewportSize.width , _layoutDirection);
112- endIter = ASFindIndexForRange (_nodeSizes, _visibleRangeEndPos, frontScreens * viewportSize.width , _layoutDirection);
170+ viewportScreenMetric = viewportSize.width ;
171+ leadingDirection = ASScrollDirectionLeft;
113172 } else {
114173 ASDisplayNodeAssert (scrollDirection == ASScrollDirectionNone || scrollDirection == ASScrollDirectionUp || scrollDirection == ASScrollDirectionDown, @" Invalid scroll direction" );
115174
116- CGFloat backScreens = scrollDirection == ASScrollDirectionUp ? self.tuningParameters .leadingBufferScreenfuls : self.tuningParameters .trailingBufferScreenfuls ;
117- CGFloat frontScreens = scrollDirection == ASScrollDirectionUp ? self.tuningParameters .trailingBufferScreenfuls : self.tuningParameters .leadingBufferScreenfuls ;
118-
119- startIter = ASFindIndexForRange (_nodeSizes, _visibleRangeStartPos, - backScreens * viewportSize.height , _layoutDirection);
120- endIter = ASFindIndexForRange (_nodeSizes, _visibleRangeEndPos, frontScreens * viewportSize.height , _layoutDirection);
175+ viewportScreenMetric = viewportSize.height ;
176+ leadingDirection = ASScrollDirectionUp;
121177 }
122178
179+ ASRangeTuningParameters tuningParameters = [self tuningParametersForRange: range];
180+ CGFloat backScreens = scrollDirection == leadingDirection ? tuningParameters.leadingBufferScreenfuls : tuningParameters.trailingBufferScreenfuls ;
181+ CGFloat frontScreens = scrollDirection == leadingDirection ? tuningParameters.trailingBufferScreenfuls : tuningParameters.leadingBufferScreenfuls ;
182+
183+ std::pair<int , int > startIter = ASFindIndexForRange (_nodeSizes, _visibleRangeStartPos, - backScreens * viewportSize.height , _layoutDirection);
184+ std::pair<int , int > endIter = ASFindIndexForRange (_nodeSizes, _visibleRangeEndPos, frontScreens * viewportSize.height , _layoutDirection);
185+
123186 NSMutableSet *indexPathSet = [[NSMutableSet alloc ] init ];
124187
125188 while (startIter != endIter) {
@@ -133,11 +196,21 @@ - (NSSet *)indexPathsForScrolling:(enum ASScrollDirection)scrollDirection
133196 }
134197
135198 [indexPathSet addObject: [NSIndexPath indexPathForRow: endIter.second inSection: endIter.first]];
136-
199+
137200 return indexPathSet;
138201}
139202
140- static void ASFindIndexPathRange (NSArray *indexPaths, std::pair<int , int > &startPos, std::pair<int , int > &endPos) {
203+ - (NSSet *)indexPathsForScrolling : (enum ASScrollDirection)scrollDirection
204+ viewportSize : (CGSize)viewportSize
205+ {
206+ return [self indexPathsForScrolling: scrollDirection viewportSize: viewportSize range: ASLayoutRangeRender];
207+ }
208+
209+ #pragma mark - Utility
210+
211+ static void ASFindIndexPathRange (NSArray *indexPaths, std::pair<int , int > &startPos, std::pair<int , int > &endPos)
212+
213+ {
141214 NSIndexPath *initialIndexPath = [indexPaths firstObject ];
142215 startPos = endPos = {initialIndexPath.section , initialIndexPath.row };
143216 [indexPaths enumerateObjectsUsingBlock: ^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
@@ -150,7 +223,8 @@ static void ASFindIndexPathRange(NSArray *indexPaths, std::pair<int, int> &start
150223static const std::pair<int , int > ASFindIndexForRange (const std::vector<std::vector<CGSize>> &nodes,
151224 const std::pair<int , int > &pos,
152225 CGFloat range,
153- ASFlowLayoutDirection layoutDirection) {
226+ ASFlowLayoutDirection layoutDirection)
227+ {
154228 std::pair<int , int > cur = pos, pre = pos;
155229
156230 if (range < 0.0 && cur.first >= 0 && cur.first < nodes.size () && cur.second >= 0 && cur.second < nodes[cur.first].size ()) {
@@ -190,7 +264,8 @@ static void ASFindIndexPathRange(NSArray *indexPaths, std::pair<int, int> &start
190264 return cur;
191265}
192266
193- static int ASFlowLayoutDistance (const std::pair<int , int > &start, const std::pair<int , int > &end, const std::vector<std::vector<CGSize>> &nodes) {
267+ static int ASFlowLayoutDistance (const std::pair<int , int > &start, const std::pair<int , int > &end, const std::vector<std::vector<CGSize>> &nodes)
268+ {
194269 if (start == end) {
195270 return 0 ;
196271 } else if (start > end) {
0 commit comments