Range controller registers to rendering engine and extern to full range if needed

This commit is contained in:
Huy Nguyen
2016-02-01 23:42:13 -08:00
parent 1145b6e40e
commit 69e674c1c8
8 changed files with 143 additions and 76 deletions

View File

@@ -29,6 +29,7 @@
#import "ASCellNode.h" #import "ASCellNode.h"
NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority; NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority;
NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification = @"ASRenderingEngineDidDisplayScheduledNodes";
@interface _ASDisplayNodePosition : NSObject @interface _ASDisplayNodePosition : NSObject
@@ -279,6 +280,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
for (ASDisplayNode *node in displayingNodes) { for (ASDisplayNode *node in displayingNodes) {
[node __recursivelyTriggerDisplayAndBlock:NO]; [node __recursivelyTriggerDisplayAndBlock:NO];
} }
[[NSNotificationCenter defaultCenter] postNotificationName:ASRenderingEngineDidDisplayScheduledNodesNotification
object:nil];
}); });
} }
} }

View File

@@ -11,8 +11,7 @@
#include <vector> #include <vector>
@interface ASAbstractLayoutController () { @interface ASAbstractLayoutController () {
std::vector<ASRangeTuningParameters> _tuningParameters; std::vector<std::vector<ASRangeTuningParameters>> _tuningParameters;
std::vector<ASRangeTuningParameters> _minimumTuningParameters;
CGSize _viewportSize; CGSize _viewportSize;
} }
@end @end
@@ -25,33 +24,33 @@
return nil; return nil;
} }
_tuningParameters = std::vector<ASRangeTuningParameters>(ASLayoutRangeTypeCount); _tuningParameters = std::vector<std::vector<ASRangeTuningParameters>> (ASLayoutRangeModeCount, std::vector<ASRangeTuningParameters> (ASLayoutRangeTypeCount));
_tuningParameters[ASLayoutRangeTypeVisible] = {
_tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeVisible] = {
.leadingBufferScreenfuls = 0, .leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0 .trailingBufferScreenfuls = 0
}; };
_tuningParameters[ASLayoutRangeTypeDisplay] = { _tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeDisplay] = {
.leadingBufferScreenfuls = 1.5,
.trailingBufferScreenfuls = 0.75
};
_tuningParameters[ASLayoutRangeTypeFetchData] = {
.leadingBufferScreenfuls = 3,
.trailingBufferScreenfuls = 2
};
_minimumTuningParameters = std::vector<ASRangeTuningParameters>(ASLayoutRangeTypeCount);
_minimumTuningParameters[ASLayoutRangeTypeVisible] = {
.leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0
};
_minimumTuningParameters[ASLayoutRangeTypeDisplay] = {
.leadingBufferScreenfuls = 0.25, .leadingBufferScreenfuls = 0.25,
.trailingBufferScreenfuls = 0.25 .trailingBufferScreenfuls = 0.25
}; };
_minimumTuningParameters[ASLayoutRangeTypeFetchData] = { _tuningParameters[ASLayoutRangeModeMinimum][ASLayoutRangeTypeFetchData] = {
.leadingBufferScreenfuls = 1, .leadingBufferScreenfuls = 1,
.trailingBufferScreenfuls = 1 .trailingBufferScreenfuls = 1
}; };
_tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeVisible] = {
.leadingBufferScreenfuls = 0,
.trailingBufferScreenfuls = 0
};
_tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeDisplay] = {
.leadingBufferScreenfuls = 1.5,
.trailingBufferScreenfuls = 0.75
};
_tuningParameters[ASLayoutRangeModeFull][ASLayoutRangeTypeFetchData] = {
.leadingBufferScreenfuls = 3,
.trailingBufferScreenfuls = 2
};
return self; return self;
} }
@@ -60,33 +59,28 @@
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType - (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType
{ {
ASDisplayNodeAssert(rangeType < _tuningParameters.size(), @"Requesting a range that is OOB for the configured tuning parameters"); return [self tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:rangeType];
return _tuningParameters[rangeType];
} }
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType
{ {
ASDisplayNodeAssert(rangeType < _tuningParameters.size(), @"Requesting a range that is OOB for the configured tuning parameters"); return [self setTuningParameters:tuningParameters forRangeMode:ASLayoutRangeModeFull rangeType:rangeType];
ASDisplayNodeAssert(rangeType != ASLayoutRangeTypeVisible, @"Must not set Visible range tuning parameters (always 0, 0)");
_tuningParameters[rangeType] = tuningParameters;
} }
- (ASRangeTuningParameters)minimumTuningParametersForRangeType:(ASLayoutRangeType)rangeType - (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
{ {
ASDisplayNodeAssert(rangeType < _minimumTuningParameters.size(), @"Requesting a range that is OOB for the configured minimum tuning parameters"); ASDisplayNodeAssert(rangeMode < _tuningParameters.size() && rangeType < _tuningParameters[rangeMode].size(),
return _minimumTuningParameters[rangeType]; @"Requesting a range that is OOB for the configured tuning parameters");
return _tuningParameters[rangeMode][rangeType];
} }
- (void)setMinimumTuningParameters:(ASRangeTuningParameters)minimumTuningParameters forRangeType:(ASLayoutRangeType)rangeType - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
{ {
ASDisplayNodeAssert(rangeType < _minimumTuningParameters.size(), @"Requesting a range that is OOB for the configured minimum tuning parameters"); ASDisplayNodeAssert(rangeMode < _tuningParameters.size() && rangeType < _tuningParameters[rangeMode].size(),
ASDisplayNodeAssert(rangeType != ASLayoutRangeTypeVisible, @"Must not set Visible range minimum tuning parameters (always 0, 0)"); @"Setting a range that is OOB for the configured tuning parameters");
_minimumTuningParameters[rangeType] = minimumTuningParameters; ASDisplayNodeAssert(rangeType != ASLayoutRangeTypeVisible,
} @"Must not set Visible range minimum tuning parameters (always 0, 0)");
_tuningParameters[rangeMode][rangeType] = tuningParameters;
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType isFullRange:(BOOL)isFullRange
{
return isFullRange ? [self tuningParametersForRangeType:rangeType] : [self minimumTuningParametersForRangeType:rangeType];
} }
#pragma mark - Abstract Index Path Range Support #pragma mark - Abstract Index Path Range Support
@@ -98,7 +92,7 @@
return NO; return NO;
} }
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeType:(ASLayoutRangeType)rangeType shouldUseFullRange:(BOOL)shouldUseFullRange - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
{ {
ASDisplayNodeAssertNotSupported(); ASDisplayNodeAssertNotSupported();
return nil; return nil;

View File

@@ -66,9 +66,9 @@ typedef struct ASRangeGeometry ASRangeGeometry;
return self; return self;
} }
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeType:(ASLayoutRangeType)rangeType shouldUseFullRange:(BOOL)shouldUseFullRange - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
{ {
ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeType:rangeType isFullRange:shouldUseFullRange]; ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType];
ASRangeGeometry rangeGeometry = [self rangeGeometryWithScrollDirection:scrollDirection tuningParameters:tuningParameters]; ASRangeGeometry rangeGeometry = [self rangeGeometryWithScrollDirection:scrollDirection tuningParameters:tuningParameters];
_updateRangeBoundsIndexedByRangeType[rangeType] = rangeGeometry.updateBounds; _updateRangeBoundsIndexedByRangeType[rangeType] = rangeGeometry.updateBounds;
return [self indexPathsForItemsWithinRangeBounds:rangeGeometry.rangeBounds]; return [self indexPathsForItemsWithinRangeBounds:rangeGeometry.rangeBounds];
@@ -133,9 +133,9 @@ typedef struct ASRangeGeometry ASRangeGeometry;
@implementation ASCollectionViewLayoutControllerBeta @implementation ASCollectionViewLayoutControllerBeta
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeType:(ASLayoutRangeType)rangeType shouldUseFullRange:(BOOL)shouldUseFullRange - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
{ {
ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeType:rangeType isFullRange:shouldUseFullRange]; ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType];
CGRect rangeBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:tuningParameters]; CGRect rangeBounds = [self rangeBoundsWithScrollDirection:scrollDirection rangeTuningParameters:tuningParameters];
return [self indexPathsForItemsWithinRangeBounds:rangeBounds]; return [self indexPathsForItemsWithinRangeBounds:rangeBounds];
} }

View File

@@ -74,7 +74,7 @@ static const CGFloat kASFlowLayoutControllerRefreshingThreshold = 0.3;
* IndexPath array for the element in the working range. * IndexPath array for the element in the working range.
*/ */
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeType:(ASLayoutRangeType)rangeType shouldUseFullRange:(BOOL)shouldUseFullRange - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
{ {
CGFloat viewportScreenMetric; CGFloat viewportScreenMetric;
ASScrollDirection leadingDirection; ASScrollDirection leadingDirection;
@@ -92,7 +92,7 @@ static const CGFloat kASFlowLayoutControllerRefreshingThreshold = 0.3;
leadingDirection = ASScrollDirectionUp; leadingDirection = ASScrollDirectionUp;
} }
ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeType:rangeType isFullRange:shouldUseFullRange]; ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType];
CGFloat backScreens = scrollDirection == leadingDirection ? tuningParameters.leadingBufferScreenfuls : tuningParameters.trailingBufferScreenfuls; CGFloat backScreens = scrollDirection == leadingDirection ? tuningParameters.leadingBufferScreenfuls : tuningParameters.trailingBufferScreenfuls;
CGFloat frontScreens = scrollDirection == leadingDirection ? tuningParameters.trailingBufferScreenfuls : tuningParameters.leadingBufferScreenfuls; CGFloat frontScreens = scrollDirection == leadingDirection ? tuningParameters.trailingBufferScreenfuls : tuningParameters.leadingBufferScreenfuls;

View File

@@ -16,6 +16,12 @@ NS_ASSUME_NONNULL_BEGIN
@class ASCellNode; @class ASCellNode;
typedef NS_ENUM(NSUInteger, ASLayoutRangeMode) {
ASLayoutRangeModeMinimum = 0,
ASLayoutRangeModeFull,
ASLayoutRangeModeCount
};
typedef struct { typedef struct {
CGFloat leadingBufferScreenfuls; CGFloat leadingBufferScreenfuls;
CGFloat trailingBufferScreenfuls; CGFloat trailingBufferScreenfuls;
@@ -24,23 +30,30 @@ typedef struct {
@protocol ASLayoutController <NSObject> @protocol ASLayoutController <NSObject>
/** /**
* Tuning parameters for the range. * Tuning parameters for the range type in full mode. This method is deprecated.
* Instead, use -setTuningParameters:forRangeMode:rangeType:
*
* @see setTuningParameters:forRangeMode:rangeType:
*/ */
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType; - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED;
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType; /**
* Get tuning parameters for the range type in full mode. This method is deprecated.
* Instead, use -tuningParametersForRangeMode:rangeType:
*
* @see tuningParametersForRangeMode:rangeType:
*/
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED;
- (void)setMinimumTuningParameters:(ASRangeTuningParameters)minimumTuningParameters forRangeType:(ASLayoutRangeType)rangeType; - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
- (ASRangeTuningParameters)minimumTuningParametersForRangeType:(ASLayoutRangeType)rangeType; - (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType isFullRange:(BOOL)isFullRange;
// FIXME: This method can be removed once ASRangeControllerBeta becomes the main version. // FIXME: This method can be removed once ASRangeControllerBeta becomes the main version.
// TODO: Now that it is the main version, can we remove this now? // TODO: Now that it is the main version, can we remove this now?
- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray<NSIndexPath *> *)indexPaths rangeType:(ASLayoutRangeType)rangeType; - (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray<NSIndexPath *> *)indexPaths rangeType:(ASLayoutRangeType)rangeType;
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeType:(ASLayoutRangeType)rangeType shouldUseFullRange:(BOOL)shouldUseFullRange; - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
@optional @optional

View File

@@ -153,7 +153,9 @@
id<ASRangeHandler> rangeHandler = _rangeTypeHandlers[rangeKey]; id<ASRangeHandler> rangeHandler = _rangeTypeHandlers[rangeKey];
if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths rangeType:rangeType]) { if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths rangeType:rangeType]) {
NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:rangeType shouldUseFullRange:YES]; NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection
rangeMode:ASLayoutRangeModeFull
rangeType:rangeType];
// Notify to remove indexpaths that are leftover that are not visible or included in the _layoutController calculated paths // Notify to remove indexpaths that are leftover that are not visible or included in the _layoutController calculated paths
NSMutableSet *removedIndexPaths = _rangeIsValid ? [_rangeTypeIndexPaths[rangeKey] mutableCopy] : [NSMutableSet set]; NSMutableSet *removedIndexPaths = _rangeIsValid ? [_rangeTypeIndexPaths[rangeKey] mutableCopy] : [NSMutableSet set];

View File

@@ -10,6 +10,7 @@
#import "ASAssert.h" #import "ASAssert.h"
#import "ASDisplayNodeExtras.h" #import "ASDisplayNodeExtras.h"
#import "ASDisplayNodeInternal.h"
#import "ASMultiDimensionalArrayUtils.h" #import "ASMultiDimensionalArrayUtils.h"
#import "ASRangeHandlerVisible.h" #import "ASRangeHandlerVisible.h"
#import "ASRangeHandlerRender.h" #import "ASRangeHandlerRender.h"
@@ -17,12 +18,6 @@
#import "ASInternalHelpers.h" #import "ASInternalHelpers.h"
#import "ASDisplayNode+FrameworkPrivate.h" #import "ASDisplayNode+FrameworkPrivate.h"
typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
ASRangeTypeUsedNone,
ASRangeTypeUsedMinimum,
ASRangeTypeUsedFull,
};
@interface ASRangeControllerBeta () @interface ASRangeControllerBeta ()
{ {
BOOL _rangeIsValid; BOOL _rangeIsValid;
@@ -30,7 +25,8 @@ typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
BOOL _layoutControllerImplementsSetVisibleIndexPaths; BOOL _layoutControllerImplementsSetVisibleIndexPaths;
ASScrollDirection _scrollDirection; ASScrollDirection _scrollDirection;
NSSet<NSIndexPath *> *_allPreviousIndexPaths; NSSet<NSIndexPath *> *_allPreviousIndexPaths;
ASRangeTypeUsed _rangeTypeUsed; ASLayoutRangeMode _currentRangeMode;
BOOL _didRegisterForNotifications;
} }
@end @end
@@ -44,13 +40,41 @@ typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
} }
_rangeIsValid = YES; _rangeIsValid = YES;
_rangeTypeUsed = ASRangeTypeUsedNone; _currentRangeMode = ASLayoutRangeModeCount;
return self; return self;
} }
- (void)dealloc
{
if (_didRegisterForNotifications) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
#pragma mark - Core visible node range managment API #pragma mark - Core visible node range managment API
+ (ASLayoutRangeMode)rangeModeForInterfaceState:(ASInterfaceState)interfaceState
scrollDirection:(ASScrollDirection)scrollDirection
currentRangeMode:(ASLayoutRangeMode)currentRangeMode
{
// If we used full mode, don't switch to minimum mode. That will destroy all the hard work done before.
if (currentRangeMode == ASLayoutRangeModeFull) {
return ASLayoutRangeModeFull;
}
BOOL isVisible = (ASInterfaceStateIncludesVisible(interfaceState));
BOOL isScrolling = (scrollDirection != ASScrollDirectionNone);
BOOL isUsingMinimumRangeMode = (currentRangeMode == ASLayoutRangeModeMinimum);
// If we are already visible and scrolling, get busy! Better get started on preloading before the user scrolls more...
// If we are already visible and finished displaying minimum mode, extend to full mode
if (isVisible && (isScrolling || isUsingMinimumRangeMode)) {
return ASLayoutRangeModeFull;
}
return ASLayoutRangeModeMinimum;
}
- (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection - (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection
{ {
_scrollDirection = scrollDirection; _scrollDirection = scrollDirection;
@@ -62,7 +86,7 @@ typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
if (_queuedRangeUpdate) { if (_queuedRangeUpdate) {
return; return;
} }
// coalesce these events -- handling them multiple times per runloop is noisy and expensive // coalesce these events -- handling them multiple times per runloop is noisy and expensive
_queuedRangeUpdate = YES; _queuedRangeUpdate = YES;
@@ -117,25 +141,25 @@ typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
NSMutableOrderedSet<NSIndexPath *> *allIndexPaths = [[NSMutableOrderedSet alloc] initWithSet:visibleIndexPaths]; NSMutableOrderedSet<NSIndexPath *> *allIndexPaths = [[NSMutableOrderedSet alloc] initWithSet:visibleIndexPaths];
ASInterfaceState selfInterfaceState = [_dataSource interfaceStateForRangeController:self]; ASInterfaceState selfInterfaceState = [_dataSource interfaceStateForRangeController:self];
BOOL selfIsVisible = (ASInterfaceStateIncludesVisible(selfInterfaceState)); ASLayoutRangeMode rangeMode = [ASRangeControllerBeta rangeModeForInterfaceState:selfInterfaceState
BOOL selfIsScrolling = (_scrollDirection != ASScrollDirectionNone); scrollDirection:_scrollDirection
BOOL didUseMinimumRange = (_rangeTypeUsed == ASRangeTypeUsedMinimum); currentRangeMode:_currentRangeMode];
BOOL didUseFullRange = (_rangeTypeUsed == ASRangeTypeUsedFull);
// If we are already visible and scrolling, get busy! Better get started on preloading before the user scrolls more...
// If we are already visible and did finish displaying minimum range, extend to full range
// If we used full range, don't switch to minimum range now. That will destroy all the hard work done before.
BOOL useFullRange = ((selfIsVisible && (selfIsScrolling || didUseMinimumRange)) || didUseFullRange);
NSLog(@"%@ range: %@", useFullRange ? @"Full" : @"Minimum", [((ASCollectionView *)_delegate).asyncDelegate description]);
fetchDataIndexPaths = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:ASLayoutRangeTypeFetchData shouldUseFullRange:useFullRange]; fetchDataIndexPaths = [_layoutController indexPathsForScrolling:_scrollDirection
rangeMode:rangeMode
rangeType:ASLayoutRangeTypeFetchData];
ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeType:ASLayoutRangeTypeDisplay isFullRange:useFullRange]; ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeMode:rangeMode
ASRangeTuningParameters parametersFetchData = [_layoutController tuningParametersForRangeType:ASLayoutRangeTypeFetchData isFullRange:useFullRange]; rangeType:ASLayoutRangeTypeDisplay];
ASRangeTuningParameters parametersFetchData = [_layoutController tuningParametersForRangeMode:rangeMode
rangeType:ASLayoutRangeTypeFetchData];
if (parametersDisplay.leadingBufferScreenfuls == parametersFetchData.leadingBufferScreenfuls && if (parametersDisplay.leadingBufferScreenfuls == parametersFetchData.leadingBufferScreenfuls &&
parametersDisplay.trailingBufferScreenfuls == parametersFetchData.trailingBufferScreenfuls) { parametersDisplay.trailingBufferScreenfuls == parametersFetchData.trailingBufferScreenfuls) {
displayIndexPaths = fetchDataIndexPaths; displayIndexPaths = fetchDataIndexPaths;
} else { } else {
displayIndexPaths = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:ASLayoutRangeTypeDisplay shouldUseFullRange:useFullRange]; 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 fetchDataIndexPaths will be the largest, and be a superset of the others, though it may be disjoint.
@@ -151,11 +175,13 @@ typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
NSSet<NSIndexPath *> *allCurrentIndexPaths = [[allIndexPaths set] copy]; NSSet<NSIndexPath *> *allCurrentIndexPaths = [[allIndexPaths set] copy];
[allIndexPaths unionSet:_allPreviousIndexPaths]; [allIndexPaths unionSet:_allPreviousIndexPaths];
_allPreviousIndexPaths = allCurrentIndexPaths; _allPreviousIndexPaths = allCurrentIndexPaths;
_rangeTypeUsed = useFullRange ? ASRangeTypeUsedFull : ASRangeTypeUsedMinimum; _currentRangeMode = rangeMode;
if (!_rangeIsValid) { if (!_rangeIsValid) {
[allIndexPaths addObjectsFromArray:ASIndexPathsForMultidimensionalArray(allNodes)]; [allIndexPaths addObjectsFromArray:ASIndexPathsForMultidimensionalArray(allNodes)];
} }
[self registerForNotificationsIfNeeded];
// This array is only used if logging is enabled. // This array is only used if logging is enabled.
NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil); NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
@@ -240,6 +266,33 @@ typedef NS_ENUM(NSUInteger, ASRangeTypeUsed) {
#endif #endif
} }
#pragma mark - Notification observers
- (void)registerForNotificationsIfNeeded
{
if (!_didRegisterForNotifications) {
BOOL selfInterfaceState = [_dataSource interfaceStateForRangeController:self];
ASLayoutRangeMode nextRangeMode = [ASRangeControllerBeta rangeModeForInterfaceState:selfInterfaceState
scrollDirection:_scrollDirection
currentRangeMode:_currentRangeMode];
if (_currentRangeMode != nextRangeMode) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(scheduledNodesDidDisplay)
name:ASRenderingEngineDidDisplayScheduledNodesNotification
object:nil];
_didRegisterForNotifications = YES;
}
}
}
- (void)scheduledNodesDidDisplay
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
_didRegisterForNotifications = NO;
[self scheduleRangeUpdate];
}
#pragma mark - Cell node view handling #pragma mark - Cell node view handling
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node - (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node

View File

@@ -37,6 +37,8 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides)
@class _ASPendingState; @class _ASPendingState;
@class _ASDisplayNodePosition; @class _ASDisplayNodePosition;
FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification;
// Allow 2^n increments of begin disabling hierarchy notifications // Allow 2^n increments of begin disabling hierarchy notifications
#define VISIBILITY_NOTIFICATIONS_DISABLED_BITS 4 #define VISIBILITY_NOTIFICATIONS_DISABLED_BITS 4