[ASDisplayNode] Add Convenience Interface State Accessors (#2168)

* Finish renaming fetchData range, add convenience accessors

* Update example

* Update new tests
This commit is contained in:
Adlai Holler
2016-09-01 16:44:16 -07:00
committed by GitHub
parent 5e3627a9cd
commit 33a680255c
16 changed files with 171 additions and 136 deletions

View File

@@ -55,7 +55,7 @@ typedef ASLayoutSpec * _Nonnull(^ASLayoutSpecBlock)(ASDisplayNode * _Nonnull nod
/**
Interface state is available on ASDisplayNode and ASViewController, and
allows checking whether a node is in an interface situation where it is prudent to trigger certain
actions: measurement, data fetching, display, and visibility (the latter for animations or other onscreen-only effects).
actions: measurement, data loading, display, and visibility (the latter for animations or other onscreen-only effects).
*/
typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
@@ -65,7 +65,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
/** The element may be added to a view soon that could become visible. Measure the layout, including size calculation. */
ASInterfaceStateMeasureLayout = 1 << 0,
/** The element is likely enough to come onscreen that disk and/or network data required for display should be fetched. */
ASInterfaceStateFetchData = 1 << 1,
ASInterfaceStatePreload = 1 << 1,
/** The element is very likely to become visible, and concurrent rendering should be executed for any -setNeedsDisplay. */
ASInterfaceStateDisplay = 1 << 2,
/** The element is physically onscreen by at least 1 pixel.
@@ -78,7 +78,7 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
* Currently we only set `interfaceState` to other values for
* nodes contained in table views or collection views.
*/
ASInterfaceStateInHierarchy = ASInterfaceStateMeasureLayout | ASInterfaceStateFetchData | ASInterfaceStateDisplay | ASInterfaceStateVisible,
ASInterfaceStateInHierarchy = ASInterfaceStateMeasureLayout | ASInterfaceStatePreload | ASInterfaceStateDisplay | ASInterfaceStateVisible,
};
/**
@@ -214,6 +214,27 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, readonly, strong) CALayer * _Nonnull layer;
/**
* Returns YES if the node is at least partially visible in a window.
*
* @see didEnterVisibleState and didExitVisibleState
*/
@property (readonly, getter=isVisible) BOOL visible;
/**
* Returns YES if the node is in the preloading interface state.
*
* @see didEnterPreloadState and didExitPreloadState
*/
@property (readonly, getter=isInPreloadState) BOOL inPreloadState;
/**
* Returns YES if the node is in the displaying interface state.
*
* @see didEnterDisplayState and didExitDisplayState
*/
@property (readonly, getter=isInDisplayState) BOOL inDisplayState;
/**
* @abstract Returns the Interface State of the node.
*
@@ -221,7 +242,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @see ASInterfaceState
*/
@property (nonatomic, readonly) ASInterfaceState interfaceState;
@property (readonly) ASInterfaceState interfaceState;
/** @name Managing dimensions */
@@ -500,7 +521,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)recursivelyFetchData;
/**
* @abstract Triggers a recursive call to fetchData when the node has an interfaceState of ASInterfaceStateFetchData
* @abstract Triggers a recursive call to fetchData when the node has an interfaceState of ASInterfaceStatePreload
*/
- (void)setNeedsDataFetch;

View File

@@ -2451,7 +2451,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
- (void)setNeedsDataFetch
{
if (ASInterfaceStateIncludesFetchData(_interfaceState)) {
if (self.isInPreloadState) {
[self recursivelyFetchData];
}
}
@@ -2516,6 +2516,24 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
return ASHierarchyStateIncludesRangeManaged(_hierarchyState);
}
- (BOOL)isVisible
{
ASDN::MutexLocker l(__instanceLock__);
return ASInterfaceStateIncludesVisible(_interfaceState);
}
- (BOOL)isInDisplayState
{
ASDN::MutexLocker l(__instanceLock__);
return ASInterfaceStateIncludesDisplay(_interfaceState);
}
- (BOOL)isInPreloadState
{
ASDN::MutexLocker l(__instanceLock__);
return ASInterfaceStateIncludesPreload(_interfaceState);
}
- (ASInterfaceState)interfaceState
{
ASDN::MutexLocker l(__instanceLock__);
@@ -2548,11 +2566,11 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
// Still, the interfaceState should be updated to the current state of the node; just don't act on the transition.
// Entered or exited data loading state.
BOOL nowFetchData = ASInterfaceStateIncludesFetchData(newState);
BOOL wasFetchData = ASInterfaceStateIncludesFetchData(oldState);
BOOL nowPreload = ASInterfaceStateIncludesPreload(newState);
BOOL wasPreload = ASInterfaceStateIncludesPreload(oldState);
if (nowFetchData != wasFetchData) {
if (nowFetchData) {
if (nowPreload != wasPreload) {
if (nowPreload) {
[self didEnterPreloadState];
} else {
[self didExitPreloadState];

View File

@@ -26,9 +26,9 @@ ASDISPLAYNODE_INLINE BOOL ASInterfaceStateIncludesDisplay(ASInterfaceState inter
return ((interfaceState & ASInterfaceStateDisplay) == ASInterfaceStateDisplay);
}
ASDISPLAYNODE_INLINE BOOL ASInterfaceStateIncludesFetchData(ASInterfaceState interfaceState)
ASDISPLAYNODE_INLINE BOOL ASInterfaceStateIncludesPreload(ASInterfaceState interfaceState)
{
return ((interfaceState & ASInterfaceStateFetchData) == ASInterfaceStateFetchData);
return ((interfaceState & ASInterfaceStatePreload) == ASInterfaceStatePreload);
}
ASDISPLAYNODE_INLINE BOOL ASInterfaceStateIncludesMeasureLayout(ASInterfaceState interfaceState)
@@ -45,8 +45,8 @@ ASDISPLAYNODE_INLINE NSString * _Nonnull NSStringFromASInterfaceState(ASInterfac
if (ASInterfaceStateIncludesMeasureLayout(interfaceState)) {
[states addObject:@"MeasureLayout"];
}
if (ASInterfaceStateIncludesFetchData(interfaceState)) {
[states addObject:@" | FetchData"];
if (ASInterfaceStateIncludesPreload(interfaceState)) {
[states addObject:@" | Preload"];
}
if (ASInterfaceStateIncludesDisplay(interfaceState)) {
[states addObject:@" | Display"];

View File

@@ -428,8 +428,8 @@
// If our bounds.size is different from our current snapshot size, then let's request a new image from MKMapSnapshotter.
if (_needsMapReloadOnBoundsChange) {
[self setSnapshotSizeWithReloadIfNeeded:self.bounds.size];
// FIXME: Adding a check for FetchData here seems to cause intermittent map load failures, but shouldn't.
// if (ASInterfaceStateIncludesFetchData(self.interfaceState)) {
// FIXME: Adding a check for Preload here seems to cause intermittent map load failures, but shouldn't.
// if (ASInterfaceStateIncludesPreload(self.interfaceState)) {
}
}
}

View File

@@ -396,9 +396,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
_imageIdentifiers = [[NSArray alloc] initWithArray:imageIdentifiers copyItems:YES];
}
if (self.interfaceState & ASInterfaceStateFetchData) {
[self fetchData];
}
[self setNeedsDataFetch];
}
- (void)reloadImageIdentifierSources

View File

@@ -143,9 +143,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
});
}
if (self.interfaceState & ASInterfaceStateFetchData) {
[self fetchData];
}
[self setNeedsDataFetch];
}
- (NSURL *)URL

View File

@@ -81,12 +81,12 @@
ASRangeTuningParameters minimumRenderParams = { .leadingBufferScreenfuls = 0.0, .trailingBufferScreenfuls = 0.0 };
ASRangeTuningParameters minimumPreloadParams = { .leadingBufferScreenfuls = 1.0, .trailingBufferScreenfuls = 1.0 };
[self setTuningParameters:minimumRenderParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeDisplay];
[self setTuningParameters:minimumPreloadParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeFetchData];
[self setTuningParameters:minimumPreloadParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypePreload];
ASRangeTuningParameters fullRenderParams = { .leadingBufferScreenfuls = 1.0, .trailingBufferScreenfuls = 1.0 };
ASRangeTuningParameters fullPreloadParams = { .leadingBufferScreenfuls = 2.0, .trailingBufferScreenfuls = 2.0 };
[self setTuningParameters:fullRenderParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeDisplay];
[self setTuningParameters:fullPreloadParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeFetchData];
[self setTuningParameters:fullPreloadParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypePreload];
}
#pragma mark - Getters / Setters

View File

@@ -62,7 +62,7 @@
scrollDirection:(ASScrollDirection)direction
rangeMode:(ASLayoutRangeMode)mode
displayTuningParameters:(ASRangeTuningParameters)displayTuningParameters
fetchDataTuningParameters:(ASRangeTuningParameters)fetchDataTuningParameters
preloadTuningParameters:(ASRangeTuningParameters)preloadTuningParameters
interfaceState:(ASInterfaceState)interfaceState;
@end

View File

@@ -217,7 +217,7 @@ static BOOL __enableHitTestDebug = NO;
scrollDirection:(ASScrollDirection)direction
rangeMode:(ASLayoutRangeMode)mode
displayTuningParameters:(ASRangeTuningParameters)displayTuningParameters
fetchDataTuningParameters:(ASRangeTuningParameters)fetchDataTuningParameters
preloadTuningParameters:(ASRangeTuningParameters)preloadTuningParameters
interfaceState:(ASInterfaceState)interfaceState;
@end
@@ -233,8 +233,8 @@ static BOOL __enableHitTestDebug = NO;
- (void)updateWithVisibleRatio:(CGFloat)visibleRatio
displayRatio:(CGFloat)displayRatio
leadingDisplayRatio:(CGFloat)leadingDisplayRatio
fetchDataRatio:(CGFloat)fetchDataRatio
leadingFetchDataRatio:(CGFloat)leadingFetchDataRatio
preloadRatio:(CGFloat)preloadRatio
leadingpreloadRatio:(CGFloat)leadingpreloadRatio
direction:(ASScrollDirection)direction;
@end
@@ -268,7 +268,7 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
scrollDirection:(ASScrollDirection)direction
rangeMode:(ASLayoutRangeMode)mode
displayTuningParameters:(ASRangeTuningParameters)displayTuningParameters
fetchDataTuningParameters:(ASRangeTuningParameters)fetchDataTuningParameters
preloadTuningParameters:(ASRangeTuningParameters)preloadTuningParameters
interfaceState:(ASInterfaceState)interfaceState
{
[[_ASRangeDebugOverlayView sharedInstance] updateRangeController:controller
@@ -276,7 +276,7 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
scrollDirection:direction
rangeMode:mode
displayTuningParameters:displayTuningParameters
fetchDataTuningParameters:fetchDataTuningParameters
preloadTuningParameters:preloadTuningParameters
interfaceState:interfaceState];
}
@@ -438,7 +438,7 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
scrollDirection:(ASScrollDirection)scrollDirection
rangeMode:(ASLayoutRangeMode)rangeMode
displayTuningParameters:(ASRangeTuningParameters)displayTuningParameters
fetchDataTuningParameters:(ASRangeTuningParameters)fetchDataTuningParameters
preloadTuningParameters:(ASRangeTuningParameters)preloadTuningParameters
interfaceState:(ASInterfaceState)interfaceState;
{
_ASRangeDebugBarView *viewToUpdate = [self barViewForRangeController:controller];
@@ -446,65 +446,65 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
CGRect boundsRect = self.bounds;
CGRect visibleRect = CGRectExpandToRangeWithScrollableDirections(boundsRect, ASRangeTuningParametersZero, scrollableDirections, scrollDirection);
CGRect displayRect = CGRectExpandToRangeWithScrollableDirections(boundsRect, displayTuningParameters, scrollableDirections, scrollDirection);
CGRect fetchDataRect = CGRectExpandToRangeWithScrollableDirections(boundsRect, fetchDataTuningParameters, scrollableDirections, scrollDirection);
CGRect preloadRect = CGRectExpandToRangeWithScrollableDirections(boundsRect, preloadTuningParameters, scrollableDirections, scrollDirection);
// figure out which is biggest and assume that is full bounds
BOOL displayRangeLargerThanFetch = NO;
BOOL displayRangeLargerThanPreload = NO;
CGFloat visibleRatio = 0;
CGFloat displayRatio = 0;
CGFloat fetchDataRatio = 0;
CGFloat preloadRatio = 0;
CGFloat leadingDisplayTuningRatio = 0;
CGFloat leadingFetchDataTuningRatio = 0;
CGFloat leadingPreloadTuningRatio = 0;
if (!((displayTuningParameters.leadingBufferScreenfuls + displayTuningParameters.trailingBufferScreenfuls) == 0)) {
leadingDisplayTuningRatio = displayTuningParameters.leadingBufferScreenfuls / (displayTuningParameters.leadingBufferScreenfuls + displayTuningParameters.trailingBufferScreenfuls);
}
if (!((fetchDataTuningParameters.leadingBufferScreenfuls + fetchDataTuningParameters.trailingBufferScreenfuls) == 0)) {
leadingFetchDataTuningRatio = fetchDataTuningParameters.leadingBufferScreenfuls / (fetchDataTuningParameters.leadingBufferScreenfuls + fetchDataTuningParameters.trailingBufferScreenfuls);
if (!((preloadTuningParameters.leadingBufferScreenfuls + preloadTuningParameters.trailingBufferScreenfuls) == 0)) {
leadingPreloadTuningRatio = preloadTuningParameters.leadingBufferScreenfuls / (preloadTuningParameters.leadingBufferScreenfuls + preloadTuningParameters.trailingBufferScreenfuls);
}
if (ASScrollDirectionContainsVerticalDirection(scrollDirection)) {
if (displayRect.size.height >= fetchDataRect.size.height) {
displayRangeLargerThanFetch = YES;
if (displayRect.size.height >= preloadRect.size.height) {
displayRangeLargerThanPreload = YES;
} else {
displayRangeLargerThanFetch = NO;
displayRangeLargerThanPreload = NO;
}
if (displayRangeLargerThanFetch) {
if (displayRangeLargerThanPreload) {
visibleRatio = visibleRect.size.height / displayRect.size.height;
displayRatio = 1.0;
fetchDataRatio = fetchDataRect.size.height / displayRect.size.height;
preloadRatio = preloadRect.size.height / displayRect.size.height;
} else {
visibleRatio = visibleRect.size.height / fetchDataRect.size.height;
displayRatio = displayRect.size.height / fetchDataRect.size.height;
fetchDataRatio = 1.0;
visibleRatio = visibleRect.size.height / preloadRect.size.height;
displayRatio = displayRect.size.height / preloadRect.size.height;
preloadRatio = 1.0;
}
} else {
if (displayRect.size.width >= fetchDataRect.size.width) {
displayRangeLargerThanFetch = YES;
if (displayRect.size.width >= preloadRect.size.width) {
displayRangeLargerThanPreload = YES;
} else {
displayRangeLargerThanFetch = NO;
displayRangeLargerThanPreload = NO;
}
if (displayRangeLargerThanFetch) {
if (displayRangeLargerThanPreload) {
visibleRatio = visibleRect.size.width / displayRect.size.width;
displayRatio = 1.0;
fetchDataRatio = fetchDataRect.size.width / displayRect.size.width;
preloadRatio = preloadRect.size.width / displayRect.size.width;
} else {
visibleRatio = visibleRect.size.width / fetchDataRect.size.width;
displayRatio = displayRect.size.width / fetchDataRect.size.width;
fetchDataRatio = 1.0;
visibleRatio = visibleRect.size.width / preloadRect.size.width;
displayRatio = displayRect.size.width / preloadRect.size.width;
preloadRatio = 1.0;
}
}
[viewToUpdate updateWithVisibleRatio:visibleRatio
displayRatio:displayRatio
leadingDisplayRatio:leadingDisplayTuningRatio
fetchDataRatio:fetchDataRatio
leadingFetchDataRatio:leadingFetchDataTuningRatio
preloadRatio:preloadRatio
leadingpreloadRatio:leadingPreloadTuningRatio
direction:scrollDirection];
[self setNeedsLayout];
@@ -574,12 +574,12 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
ASTextNode *_rightDebugText;
ASImageNode *_visibleRect;
ASImageNode *_displayRect;
ASImageNode *_fetchDataRect;
ASImageNode *_preloadRect;
CGFloat _visibleRatio;
CGFloat _displayRatio;
CGFloat _fetchDataRatio;
CGFloat _preloadRatio;
CGFloat _leadingDisplayRatio;
CGFloat _leadingFetchDataRatio;
CGFloat _leadingpreloadRatio;
ASScrollDirection _scrollDirection;
BOOL _firstLayoutOfRects;
}
@@ -593,7 +593,7 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
_debugText = [self createDebugTextNode];
_leftDebugText = [self createDebugTextNode];
_rightDebugText = [self createDebugTextNode];
_fetchDataRect = [self createRangeNodeWithColor:[UIColor orangeColor]];
_preloadRect = [self createRangeNodeWithColor:[UIColor orangeColor]];
_displayRect = [self createRangeNodeWithColor:[UIColor yellowColor]];
_visibleRect = [self createRangeNodeWithColor:[UIColor greenColor]];
}
@@ -626,29 +626,29 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
CGFloat visibleDimension = (boundsSize.width - 2 * HORIZONTAL_INSET) * _visibleRatio;
CGFloat displayDimension = (boundsSize.width - 2 * HORIZONTAL_INSET) * _displayRatio;
CGFloat fetchDataDimension = (boundsSize.width - 2 * HORIZONTAL_INSET) * _fetchDataRatio;
CGFloat preloadDimension = (boundsSize.width - 2 * HORIZONTAL_INSET) * _preloadRatio;
CGFloat visiblePoint = 0;
CGFloat displayPoint = 0;
CGFloat fetchDataPoint = 0;
CGFloat preloadPoint = 0;
BOOL displayLargerThanFetchData = (_displayRatio == 1.0) ? YES : NO;
BOOL displayLargerThanPreload = (_displayRatio == 1.0) ? YES : NO;
if (ASScrollDirectionContainsLeft(_scrollDirection) || ASScrollDirectionContainsUp(_scrollDirection)) {
if (displayLargerThanFetchData) {
if (displayLargerThanPreload) {
visiblePoint = (displayDimension - visibleDimension) * _leadingDisplayRatio;
fetchDataPoint = visiblePoint - (fetchDataDimension - visibleDimension) * _leadingFetchDataRatio;
preloadPoint = visiblePoint - (preloadDimension - visibleDimension) * _leadingpreloadRatio;
} else {
visiblePoint = (fetchDataDimension - visibleDimension) * _leadingFetchDataRatio;
visiblePoint = (preloadDimension - visibleDimension) * _leadingpreloadRatio;
displayPoint = visiblePoint - (displayDimension - visibleDimension) * _leadingDisplayRatio;
}
} else if (ASScrollDirectionContainsRight(_scrollDirection) || ASScrollDirectionContainsDown(_scrollDirection)) {
if (displayLargerThanFetchData) {
if (displayLargerThanPreload) {
visiblePoint = (displayDimension - visibleDimension) * (1 - _leadingDisplayRatio);
fetchDataPoint = visiblePoint - (fetchDataDimension - visibleDimension) * (1 - _leadingFetchDataRatio);
preloadPoint = visiblePoint - (preloadDimension - visibleDimension) * (1 - _leadingpreloadRatio);
} else {
visiblePoint = (fetchDataDimension - visibleDimension) * (1 - _leadingFetchDataRatio);
visiblePoint = (preloadDimension - visibleDimension) * (1 - _leadingpreloadRatio);
displayPoint = visiblePoint - (displayDimension - visibleDimension) * (1 - _leadingDisplayRatio);
}
}
@@ -657,13 +657,13 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
[UIView animateWithDuration:animate ? 0.3 : 0.0 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
_visibleRect.frame = CGRectMake(HORIZONTAL_INSET + visiblePoint, rect.origin.y, visibleDimension, subCellHeight);
_displayRect.frame = CGRectMake(HORIZONTAL_INSET + displayPoint, rect.origin.y, displayDimension, subCellHeight);
_fetchDataRect.frame = CGRectMake(HORIZONTAL_INSET + fetchDataPoint, rect.origin.y, fetchDataDimension, subCellHeight);
_preloadRect.frame = CGRectMake(HORIZONTAL_INSET + preloadPoint, rect.origin.y, preloadDimension, subCellHeight);
} completion:^(BOOL finished) {}];
if (!animate) {
_visibleRect.alpha = _displayRect.alpha = _fetchDataRect.alpha = 0;
_visibleRect.alpha = _displayRect.alpha = _preloadRect.alpha = 0;
[UIView animateWithDuration:0.3 animations:^{
_visibleRect.alpha = _displayRect.alpha = _fetchDataRect.alpha = 1;
_visibleRect.alpha = _displayRect.alpha = _preloadRect.alpha = 1;
}];
}
@@ -673,15 +673,15 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
- (void)updateWithVisibleRatio:(CGFloat)visibleRatio
displayRatio:(CGFloat)displayRatio
leadingDisplayRatio:(CGFloat)leadingDisplayRatio
fetchDataRatio:(CGFloat)fetchDataRatio
leadingFetchDataRatio:(CGFloat)leadingFetchDataRatio
preloadRatio:(CGFloat)preloadRatio
leadingpreloadRatio:(CGFloat)leadingpreloadRatio
direction:(ASScrollDirection)scrollDirection
{
_visibleRatio = visibleRatio;
_displayRatio = displayRatio;
_leadingDisplayRatio = leadingDisplayRatio;
_fetchDataRatio = fetchDataRatio;
_leadingFetchDataRatio = leadingFetchDataRatio;
_preloadRatio = preloadRatio;
_leadingpreloadRatio = leadingpreloadRatio;
_scrollDirection = scrollDirection;
[self setNeedsLayout];
@@ -689,8 +689,8 @@ static BOOL __shouldShowRangeDebugOverlay = NO;
- (void)setBarSubviewOrder
{
if (_fetchDataRatio == 1.0) {
[self sendSubviewToBack:_fetchDataRect.view];
if (_preloadRatio == 1.0) {
[self sendSubviewToBack:_preloadRect.view];
} else {
[self sendSubviewToBack:_displayRect.view];
}

View File

@@ -39,7 +39,7 @@ extern BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningPar
.leadingBufferScreenfuls = 1.0,
.trailingBufferScreenfuls = 0.5
};
_tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeFetchData] = {
_tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypePreload] = {
.leadingBufferScreenfuls = 2.5,
.trailingBufferScreenfuls = 1.5
};
@@ -48,7 +48,7 @@ extern BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningPar
.leadingBufferScreenfuls = 0.25,
.trailingBufferScreenfuls = 0.25
};
_tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeFetchData] = {
_tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypePreload] = {
.leadingBufferScreenfuls = 0.5,
.trailingBufferScreenfuls = 0.25
};
@@ -57,7 +57,7 @@ extern BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningPar
.leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0
};
_tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypeFetchData] = {
_tuningParameters[ASLayoutRangeModeVisibleOnly][ASLayoutRangeTypePreload] = {
.leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0
};
@@ -69,7 +69,7 @@ extern BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningPar
.leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0
};
_tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypeFetchData] = {
_tuningParameters[ASLayoutRangeModeLowMemory][ASLayoutRangeTypePreload] = {
.leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0
};

View File

@@ -52,9 +52,9 @@ typedef NS_ENUM(NSUInteger, ASLayoutRangeMode) {
typedef NS_ENUM(NSInteger, ASLayoutRangeType) {
ASLayoutRangeTypeDisplay,
ASLayoutRangeTypeFetchData,
ASLayoutRangeTypePreload,
ASLayoutRangeTypeCount
};
#define ASLayoutRangeTypeRender ASLayoutRangeTypeDisplay
#define ASLayoutRangeTypePreload ASLayoutRangeTypeFetchData
#define ASLayoutRangeTypePreload ASLayoutRangeTypePreload

View File

@@ -205,7 +205,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
NSSet<NSIndexPath *> *visibleIndexPaths = [NSSet setWithArray:visibleNodePaths];
NSSet<NSIndexPath *> *displayIndexPaths = nil;
NSSet<NSIndexPath *> *fetchDataIndexPaths = nil;
NSSet<NSIndexPath *> *preloadIndexPaths = nil;
// Prioritize the order in which we visit each. Visible nodes should be updated first so they are enqueued on
// the network or display queues before preloading (offscreen) nodes are enqueued.
@@ -219,14 +219,14 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
rangeMode = [ASRangeController rangeModeForInterfaceState:selfInterfaceState currentRangeMode:_currentRangeMode];
}
ASRangeTuningParameters parametersFetchData = [_layoutController tuningParametersForRangeMode:rangeMode
rangeType:ASLayoutRangeTypeFetchData];
if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersFetchData, ASRangeTuningParametersZero)) {
fetchDataIndexPaths = visibleIndexPaths;
ASRangeTuningParameters parametersPreload = [_layoutController tuningParametersForRangeMode:rangeMode
rangeType:ASLayoutRangeTypePreload];
if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersPreload, ASRangeTuningParametersZero)) {
preloadIndexPaths = visibleIndexPaths;
} else {
fetchDataIndexPaths = [_layoutController indexPathsForScrolling:scrollDirection
preloadIndexPaths = [_layoutController indexPathsForScrolling:scrollDirection
rangeMode:rangeMode
rangeType:ASLayoutRangeTypeFetchData];
rangeType:ASLayoutRangeTypePreload];
}
ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeMode:rangeMode
@@ -235,19 +235,19 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
displayIndexPaths = [NSSet set];
} else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, ASRangeTuningParametersZero)) {
displayIndexPaths = visibleIndexPaths;
} else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, parametersFetchData)) {
displayIndexPaths = fetchDataIndexPaths;
} else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, parametersPreload)) {
displayIndexPaths = preloadIndexPaths;
} else {
displayIndexPaths = [_layoutController indexPathsForScrolling:scrollDirection
rangeMode:rangeMode
rangeType:ASLayoutRangeTypeDisplay];
}
// Typically the fetchDataIndexPaths will be the largest, and be a superset of the others, though it may be disjoint.
// Typically the preloadIndexPaths will be the largest, and be a superset of the others, though it may be disjoint.
// Because allIndexPaths is an NSMutableOrderedSet, this adds the non-duplicate items /after/ the existing items.
// This means that during iteration, we will first visit visible, then display, then fetch data nodes.
[allIndexPaths unionSet:displayIndexPaths];
[allIndexPaths unionSet:fetchDataIndexPaths];
[allIndexPaths unionSet:preloadIndexPaths];
// Add anything we had applied interfaceState to in the last update, but is no longer in range, so we can clear any
// range flags it still has enabled. Most of the time, all but a few elements are equal; a large programmatic
@@ -276,10 +276,10 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
if (ASInterfaceStateIncludesVisible(selfInterfaceState)) {
if ([visibleIndexPaths containsObject:indexPath]) {
interfaceState |= (ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData);
interfaceState |= (ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload);
} else {
if ([fetchDataIndexPaths containsObject:indexPath]) {
interfaceState |= ASInterfaceStateFetchData;
if ([preloadIndexPaths containsObject:indexPath]) {
interfaceState |= ASInterfaceStatePreload;
}
if ([displayIndexPaths containsObject:indexPath]) {
interfaceState |= ASInterfaceStateDisplay;
@@ -295,12 +295,12 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
// our overall container object is itself not visible yet. The moment it becomes visible, we will run the condition above
// Set Layout, Fetch Data
interfaceState |= ASInterfaceStateFetchData;
interfaceState |= ASInterfaceStatePreload;
if (rangeMode != ASLayoutRangeModeLowMemory) {
// Add Display.
// We might be looking at an indexPath that was previously in-range, but now we need to clear it.
// In that case we'll just set it back to MeasureLayout. Only set Display | FetchData if in allCurrentIndexPaths.
// In that case we'll just set it back to MeasureLayout. Only set Display | Preload if in allCurrentIndexPaths.
interfaceState |= ASInterfaceStateDisplay;
}
}
@@ -357,7 +357,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
scrollDirection:scrollDirection
rangeMode:rangeMode
displayTuningParameters:parametersDisplay
fetchDataTuningParameters:parametersFetchData
preloadTuningParameters:parametersPreload
interfaceState:selfInterfaceState];
}
@@ -499,8 +499,8 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
{
for (NSArray *section in [_dataSource completedNodes]) {
for (ASDisplayNode *node in section) {
if (ASInterfaceStateIncludesFetchData(node.interfaceState)) {
[node exitInterfaceState:ASInterfaceStateFetchData];
if (ASInterfaceStateIncludesPreload(node.interfaceState)) {
[node exitInterfaceState:ASInterfaceStatePreload];
}
}
}
@@ -610,8 +610,8 @@ static ASLayoutRangeMode __rangeModeForMemoryWarnings = ASLayoutRangeModeVisible
ASInterfaceState interfaceState = node.interfaceState;
BOOL inVisible = ASInterfaceStateIncludesVisible(interfaceState);
BOOL inDisplay = ASInterfaceStateIncludesDisplay(interfaceState);
BOOL inFetchData = ASInterfaceStateIncludesFetchData(interfaceState);
[description appendFormat:@"indexPath %@, Visible: %d, Display: %d, FetchData: %d\n", indexPath, inVisible, inDisplay, inFetchData];
BOOL inPreload = ASInterfaceStateIncludesPreload(interfaceState);
[description appendFormat:@"indexPath %@, Visible: %d, Display: %d, Preload: %d\n", indexPath, inVisible, inDisplay, inPreload];
}
return description;
}

View File

@@ -204,18 +204,18 @@
ASRangeTuningParameters fullPreloadParams = { .leadingBufferScreenfuls = 1, .trailingBufferScreenfuls = 0.5 };
[collectionView setTuningParameters:minimumRenderParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeDisplay];
[collectionView setTuningParameters:minimumPreloadParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeFetchData];
[collectionView setTuningParameters:minimumPreloadParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypePreload];
[collectionView setTuningParameters:fullRenderParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeDisplay];
[collectionView setTuningParameters:fullPreloadParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeFetchData];
[collectionView setTuningParameters:fullPreloadParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypePreload];
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(minimumRenderParams,
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeDisplay]));
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(minimumPreloadParams,
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeFetchData]));
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypePreload]));
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(fullRenderParams,
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeDisplay]));
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(fullPreloadParams,
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeFetchData]));
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypePreload]));
}
- (void)testTuningParameters
@@ -227,10 +227,10 @@
ASRangeTuningParameters preloadParams = { .leadingBufferScreenfuls = 4.3, .trailingBufferScreenfuls = 2.3 };
[collectionView setTuningParameters:renderParams forRangeType:ASLayoutRangeTypeDisplay];
[collectionView setTuningParameters:preloadParams forRangeType:ASLayoutRangeTypeFetchData];
[collectionView setTuningParameters:preloadParams forRangeType:ASLayoutRangeTypePreload];
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(renderParams, [collectionView tuningParametersForRangeType:ASLayoutRangeTypeDisplay]));
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(preloadParams, [collectionView tuningParametersForRangeType:ASLayoutRangeTypeFetchData]));
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(preloadParams, [collectionView tuningParametersForRangeType:ASLayoutRangeTypePreload]));
}
/**

View File

@@ -1733,9 +1733,9 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point
// Simulate range handler updating cell node.
[cellNode addSubnode:node];
[cellNode enterInterfaceState:ASInterfaceStateFetchData];
[cellNode enterInterfaceState:ASInterfaceStatePreload];
XCTAssert(node.hasFetchedData);
XCTAssert(node.interfaceState == ASInterfaceStateFetchData);
XCTAssert(node.interfaceState == ASInterfaceStatePreload);
// If the node goes into a view it should not adopt the `InHierarchy` state.
ASTestWindow *window = [ASTestWindow new];
@@ -1749,7 +1749,7 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point
ASCellNode *cellNode = [ASCellNode new];
ASTestDisplayNode *node = [ASTestDisplayNode new];
[cellNode addSubnode:node];
[cellNode enterInterfaceState:ASInterfaceStateFetchData];
[cellNode enterInterfaceState:ASInterfaceStatePreload];
node.hasFetchedData = NO;
[cellNode setNeedsDataFetch];
XCTAssert(node.hasFetchedData);
@@ -1763,10 +1763,10 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point
[cellNode setHierarchyState:ASHierarchyStateRangeManaged];
// Simulate enter range, fetch data, exit range
[cellNode enterInterfaceState:ASInterfaceStateFetchData];
[cellNode exitInterfaceState:ASInterfaceStateFetchData];
[cellNode enterInterfaceState:ASInterfaceStatePreload];
[cellNode exitInterfaceState:ASInterfaceStatePreload];
node.hasFetchedData = NO;
[cellNode enterInterfaceState:ASInterfaceStateFetchData];
[cellNode enterInterfaceState:ASInterfaceStatePreload];
XCTAssert(node.hasFetchedData);
}
@@ -1891,25 +1891,25 @@ static bool stringContainsPointer(NSString *description, id p) {
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
[node recursivelySetInterfaceState:ASInterfaceStateDisplay];
[node recursivelySetInterfaceState:ASInterfaceStateFetchData];
[node recursivelySetInterfaceState:ASInterfaceStatePreload];
XCTAssert([node displayRangeStateChangedToNO]);
}
- (void)testDidEnterPreloadIsCalledWhenNodesEnterFetchDataRange
- (void)testDidEnterPreloadIsCalledWhenNodesEnterPreloadRange
{
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
[node recursivelySetInterfaceState:ASInterfaceStateFetchData];
[node recursivelySetInterfaceState:ASInterfaceStatePreload];
XCTAssert([node preloadStateChangedToYES]);
}
- (void)testDidExitPreloadIsCalledWhenNodesExitFetchDataRange
- (void)testDidExitPreloadIsCalledWhenNodesExitPreloadRange
{
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
[node recursivelySetInterfaceState:ASInterfaceStateFetchData];
[node recursivelySetInterfaceState:ASInterfaceStatePreload];
[node recursivelySetInterfaceState:ASInterfaceStateDisplay];
XCTAssert([node preloadStateChangedToNO]);
@@ -1977,11 +1977,11 @@ static bool stringContainsPointer(NSString *description, id p) {
[node view]; // Node needs to be loaded
[node enterInterfaceState:ASInterfaceStateFetchData];
[node enterInterfaceState:ASInterfaceStatePreload];
XCTAssertTrue((node.interfaceState & ASInterfaceStateFetchData) == ASInterfaceStateFetchData);
XCTAssertTrue((subnode.interfaceState & ASInterfaceStateFetchData) == ASInterfaceStateFetchData);
XCTAssertTrue((node.interfaceState & ASInterfaceStatePreload) == ASInterfaceStatePreload);
XCTAssertTrue((subnode.interfaceState & ASInterfaceStatePreload) == ASInterfaceStatePreload);
XCTAssertTrue(node.hasFetchedData);
XCTAssertTrue(subnode.hasFetchedData);
}

View File

@@ -73,7 +73,7 @@
- (void)doOnPlayIfVideoIsNotReadyInitializeSpinnerAndAddAsSubnodeWithUrl
{
_videoNode.interfaceState = ASInterfaceStateFetchData;
_videoNode.interfaceState = ASInterfaceStatePreload;
[_videoNode play];
}
@@ -92,7 +92,7 @@
- (void)doOnPauseSpinnerIsPausedIfPresentWithURL
{
_videoNode.interfaceState = ASInterfaceStateFetchData;
_videoNode.interfaceState = ASInterfaceStatePreload;
[_videoNode play];
[_videoNode pause];
@@ -114,7 +114,7 @@
- (void)doOnVideoReadySpinnerIsStoppedAndRemovedWithURL
{
_videoNode.interfaceState = ASInterfaceStateFetchData;
_videoNode.interfaceState = ASInterfaceStatePreload;
[_videoNode play];
[_videoNode observeValueForKeyPath:@"status" ofObject:[_videoNode currentItem] change:@{NSKeyValueChangeNewKey : @(AVPlayerItemStatusReadyToPlay)} context:NULL];
@@ -144,7 +144,7 @@
[[[videoNodeMock expect] andForwardToRealObject] prepareToPlayAsset:assetMock withKeys:_requestedKeys];
_videoNode.asset = assetMock;
_videoNode.interfaceState = ASInterfaceStateFetchData;
_videoNode.interfaceState = ASInterfaceStatePreload;
[videoNodeMock verifyWithDelay:1.0f];
@@ -162,7 +162,7 @@
[[[videoNodeMock expect] andForwardToRealObject] prepareToPlayAsset:assetMock withKeys:_requestedKeys];
_videoNode.asset = assetMock;
_videoNode.interfaceState = ASInterfaceStateFetchData;
_videoNode.interfaceState = ASInterfaceStatePreload;
[videoNodeMock verifyWithDelay:1.0f];
@@ -311,7 +311,7 @@
_videoNode.shouldAutorepeat = NO;
[_videoNode didLoad];
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData];
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload];
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
[_videoNode play];
@@ -332,7 +332,7 @@
_videoNode.shouldAutorepeat = YES;
[_videoNode didLoad];
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData];
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload];
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
[_videoNode play];
@@ -348,7 +348,7 @@
_videoNode.asset = assetMock;
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStateFetchData];
[_videoNode setInterfaceState:ASInterfaceStateVisible | ASInterfaceStateDisplay | ASInterfaceStatePreload];
[_videoNode prepareToPlayAsset:assetMock withKeys:_requestedKeys];
[_videoNode pause];
_videoNode.shouldBePlaying = YES;

View File

@@ -59,10 +59,10 @@ static const CGFloat kVerticalSectionPadding = 20.0f;
_collectionView.backgroundColor = [UIColor grayColor];
_collectionView.leadingScreensForBatching = 2;
ASRangeTuningParameters fetchDataTuning;
fetchDataTuning.leadingBufferScreenfuls = 2;
fetchDataTuning.trailingBufferScreenfuls = 1;
[_collectionView setTuningParameters:fetchDataTuning forRangeType:ASLayoutRangeTypeFetchData];
ASRangeTuningParameters preloadTuning;
preloadTuning.leadingBufferScreenfuls = 2;
preloadTuning.trailingBufferScreenfuls = 1;
[_collectionView setTuningParameters:preloadTuning forRangeType:ASLayoutRangeTypePreload];
ASRangeTuningParameters preRenderTuning;
preRenderTuning.leadingBufferScreenfuls = 1;