Skip to content

Commit 9c877c5

Browse files
committed
Support for dynamic ranges
This refactors how we do ranges and implements tuning parameters for a "Render" range and a "Preload" range
1 parent 43be329 commit 9c877c5

9 files changed

Lines changed: 199 additions & 48 deletions

AsyncDisplayKit/ASCollectionView.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#import <AsyncDisplayKit/ASRangeController.h>
1212
#import <AsyncDisplayKit/ASCollectionViewProtocols.h>
13+
#import <AsyncDisplayKit/ASBaseDefines.h>
1314

1415

1516
@class ASCellNode;
@@ -29,11 +30,24 @@
2930
@property (nonatomic, weak) id<ASCollectionViewDelegate> asyncDelegate;
3031

3132
/**
32-
* Tuning parameters for the working range.
33+
* Tuning parameters for a range.
3334
*
34-
* Defaults to a trailing buffer of one screenful and a leading buffer of two screenfuls.
35+
* @param range The range to get the tuning parameters for.
36+
*
37+
* @returns A tuning parameter value for the given range.
38+
*
39+
* Defaults to the render range having one sceenful both leading and trailing and the preload range having two
40+
* screenfuls in both directions.
41+
*/
42+
- (ASRangeTuningParameters)tuningParametersForRange:(ASLayoutRange)range;
43+
44+
/**
45+
* Set the tuning parameters for a range.
46+
*
47+
* @param tuningParameters The tuning parameters to store for a range.
48+
* @param range The range to set the tuning parameters for.
3549
*/
36-
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters;
50+
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRange:(ASLayoutRange)range;
3751

3852
/**
3953
* Initializer.
@@ -153,3 +167,9 @@
153167
- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNodeForItemAtIndexPath:(NSIndexPath*)indexPath;
154168

155169
@end
170+
171+
@interface ASCollectionView (Deprecated)
172+
173+
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED;
174+
175+
@end

AsyncDisplayKit/ASCollectionView.mm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,24 @@ - (void)setAsyncDelegate:(id<ASCollectionViewDelegate>)asyncDelegate
199199
super.delegate = (id<UICollectionViewDelegate>)_proxyDelegate;
200200
}
201201

202+
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRange:(ASLayoutRange)range
203+
{
204+
[_layoutController setTuningParameters:tuningParameters forRange:range];
205+
}
206+
207+
- (ASRangeTuningParameters)tuningParametersForRange:(ASLayoutRange)range
208+
{
209+
return [_layoutController tuningParametersForRange:range];
210+
}
211+
202212
- (ASRangeTuningParameters)rangeTuningParameters
203213
{
204-
return _layoutController.tuningParameters;
214+
return [self tuningParametersForRange:ASLayoutRangeRender];
205215
}
206216

207217
- (void)setRangeTuningParameters:(ASRangeTuningParameters)tuningParameters
208218
{
209-
_layoutController.tuningParameters = tuningParameters;
219+
[self setTuningParameters:tuningParameters forRange:ASLayoutRangeRender];
210220
}
211221

212222
- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath

AsyncDisplayKit/ASTableView.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#import <AsyncDisplayKit/ASRangeController.h>
1212
#import <AsyncDisplayKit/ASTableViewProtocols.h>
13+
#import <AsyncDisplayKit/ASBaseDefines.h>
1314

1415

1516
@class ASCellNode;
@@ -29,11 +30,24 @@
2930
@property (nonatomic, weak) id<ASTableViewDelegate> asyncDelegate;
3031

3132
/**
32-
* Tuning parameters for the working range.
33+
* Tuning parameters for a range.
3334
*
34-
* Defaults to a trailing buffer of one screenful and a leading buffer of two screenfuls.
35+
* @param range The range to get the tuning parameters for.
36+
*
37+
* @returns A tuning parameter value for the given range.
38+
*
39+
* Defaults to the render range having one sceenful both leading and trailing and the preload range having two
40+
* screenfuls in both directions.
41+
*/
42+
- (ASRangeTuningParameters)tuningParametersForRange:(ASLayoutRange)range;
43+
44+
/**
45+
* Set the tuning parameters for a range.
46+
*
47+
* @param tuningParameters The tuning parameters to store for a range.
48+
* @param range The range to set the tuning parameters for.
3549
*/
36-
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters;
50+
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRange:(ASLayoutRange)range;
3751

3852
/**
3953
* initializer.
@@ -158,3 +172,9 @@
158172
- (void)tableView:(ASTableView *)tableView didEndDisplayingNodeForRowAtIndexPath:(NSIndexPath*)indexPath;
159173

160174
@end
175+
176+
@interface ASTableView (Deprecated)
177+
178+
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED;
179+
180+
@end

AsyncDisplayKit/ASTableView.mm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,24 @@ - (void)reloadData
201201
[_dataController reloadDataWithAnimationOption:UITableViewRowAnimationNone];
202202
}
203203

204+
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRange:(ASLayoutRange)range
205+
{
206+
[_layoutController setTuningParameters:tuningParameters forRange:range];
207+
}
208+
209+
- (ASRangeTuningParameters)tuningParametersForRange:(ASLayoutRange)range
210+
{
211+
return [_layoutController tuningParametersForRange:range];
212+
}
213+
204214
- (ASRangeTuningParameters)rangeTuningParameters
205215
{
206-
return _layoutController.tuningParameters;
216+
return [self tuningParametersForRange:ASLayoutRangeRender];
207217
}
208218

209219
- (void)setRangeTuningParameters:(ASRangeTuningParameters)tuningParameters
210220
{
211-
_layoutController.tuningParameters = tuningParameters;
221+
[self setTuningParameters:tuningParameters forRange:ASLayoutRangeRender];
212222
}
213223

214224
- (ASCellNode *)nodeForRowAtIndexPath:(NSIndexPath *)indexPath

AsyncDisplayKit/Details/ASFlowLayoutController.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2004-present Facebook. All Rights Reserved.
22

33
#import <AsyncDisplayKit/ASLayoutController.h>
4+
#import <AsyncDisplayKit/ASBaseDefines.h>
45

56

67
typedef NS_ENUM(NSUInteger, ASFlowLayoutDirection) {
@@ -13,10 +14,14 @@ typedef NS_ENUM(NSUInteger, ASFlowLayoutDirection) {
1314
*/
1415
@interface ASFlowLayoutController : NSObject <ASLayoutController>
1516

16-
@property (nonatomic, assign) ASRangeTuningParameters tuningParameters;
17+
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRange:(ASLayoutRange)range;
18+
19+
- (ASRangeTuningParameters)tuningParametersForRange:(ASLayoutRange)range;
1720

1821
@property (nonatomic, readonly, assign) ASFlowLayoutDirection layoutDirection;
1922

2023
- (instancetype)initWithScrollOption:(ASFlowLayoutDirection)layoutDirection;
2124

25+
@property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED;
26+
2227
@end

AsyncDisplayKit/Details/ASFlowLayoutController.mm

Lines changed: 106 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -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
150223
static 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

Comments
 (0)