From 5d474bcb1a12ee14de4b191796a9de1753d900f7 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Sun, 7 Feb 2016 14:17:42 -0800 Subject: [PATCH 1/7] Remove ASDisplayNode -shouldUseNewRenderingRange method and ASRangeControllerStable class --- AsyncDisplayKit.xcodeproj/project.pbxproj | 12 - AsyncDisplayKit/ASCollectionView.mm | 7 +- AsyncDisplayKit/ASDisplayNode+Beta.h | 3 - AsyncDisplayKit/ASDisplayNode.mm | 15 +- AsyncDisplayKit/ASTableView.mm | 3 +- .../ASCollectionViewLayoutController.h | 3 - .../ASCollectionViewLayoutController.mm | 80 ------ AsyncDisplayKit/Details/ASRangeController.h | 3 - AsyncDisplayKit/Details/ASRangeController.mm | 241 +----------------- .../Details/ASRangeHandlerRender.mm | 60 +---- .../Private/ASDisplayNode+UIViewBridge.mm | 12 +- AsyncDisplayKitTestHost/AppDelegate.mm | 1 - 12 files changed, 13 insertions(+), 427 deletions(-) diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 001681acc7..9695be1a49 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -495,10 +495,6 @@ DECBD6E81BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; DECBD6E91BE56E1900CF4905 /* ASButtonNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */; }; DECBD6EA1BE56E1900CF4905 /* ASButtonNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */; }; - DECC2ECD1C35C1C600388446 /* ASRangeControllerBeta.h in Headers */ = {isa = PBXBuildFile; fileRef = DECC2ECB1C35C1C600388446 /* ASRangeControllerBeta.h */; }; - DECC2ECE1C35C1C600388446 /* ASRangeControllerBeta.h in Headers */ = {isa = PBXBuildFile; fileRef = DECC2ECB1C35C1C600388446 /* ASRangeControllerBeta.h */; }; - DECC2ECF1C35C1C600388446 /* ASRangeControllerBeta.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECC2ECC1C35C1C600388446 /* ASRangeControllerBeta.mm */; }; - DECC2ED01C35C1C600388446 /* ASRangeControllerBeta.mm in Sources */ = {isa = PBXBuildFile; fileRef = DECC2ECC1C35C1C600388446 /* ASRangeControllerBeta.mm */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -817,8 +813,6 @@ DEC146B51C37A16A004A0EE7 /* ASCollectionInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASCollectionInternal.m; path = Details/ASCollectionInternal.m; sourceTree = ""; }; DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASButtonNode.h; sourceTree = ""; }; DECBD6E61BE56E1900CF4905 /* ASButtonNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASButtonNode.mm; sourceTree = ""; }; - DECC2ECB1C35C1C600388446 /* ASRangeControllerBeta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeControllerBeta.h; sourceTree = ""; }; - DECC2ECC1C35C1C600388446 /* ASRangeControllerBeta.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRangeControllerBeta.mm; sourceTree = ""; }; EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FB07EABBCF28656C6297BC2D /* Pods-AsyncDisplayKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1097,8 +1091,6 @@ 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */, 055F1A3619ABD413004DAFF1 /* ASRangeController.h */, 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */, - DECC2ECB1C35C1C600388446 /* ASRangeControllerBeta.h */, - DECC2ECC1C35C1C600388446 /* ASRangeControllerBeta.mm */, 292C599C1A956527007E5DD6 /* ASRangeHandler.h */, 258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */, 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */, @@ -1399,7 +1391,6 @@ 9C65A72A1BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h in Headers */, 292C599F1A956527007E5DD6 /* ASLayoutRangeType.h in Headers */, 257754B61BEE44CD00737CA5 /* ASEqualityHashHelpers.h in Headers */, - DECC2ECD1C35C1C600388446 /* ASRangeControllerBeta.h in Headers */, ACF6ED261B17843500DA7C62 /* ASLayoutSpec.h in Headers */, ACF6ED4D1B17847A00DA7C62 /* ASLayoutSpecUtilities.h in Headers */, AC026B6F1BD57DBF00BBC17E /* _ASHierarchyChangeSet.h in Headers */, @@ -1462,7 +1453,6 @@ B350623E1B010EFD0018CF92 /* _ASAsyncTransactionContainer+Private.h in Headers */, B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */, B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */, - DECC2ECE1C35C1C600388446 /* ASRangeControllerBeta.h in Headers */, 254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */, B35062411B010EFD0018CF92 /* _ASAsyncTransactionGroup.h in Headers */, B35062491B010EFD0018CF92 /* _ASCoreAnimationExtras.h in Headers */, @@ -1853,7 +1843,6 @@ 257754BE1BEE458E00737CA5 /* ASTextKitHelpers.mm in Sources */, 257754A91BEE44CD00737CA5 /* ASTextKitContext.mm in Sources */, ACF6ED501B17847A00DA7C62 /* ASStackPositionedLayout.mm in Sources */, - DECC2ECF1C35C1C600388446 /* ASRangeControllerBeta.mm in Sources */, ACF6ED521B17847A00DA7C62 /* ASStackUnpositionedLayout.mm in Sources */, 257754A61BEE44CD00737CA5 /* ASTextKitAttributes.mm in Sources */, ACF6ED321B17843500DA7C62 /* ASStaticLayoutSpec.mm in Sources */, @@ -1990,7 +1979,6 @@ 9C8221981BA237B80037F19A /* ASStackBaselinePositionedLayout.mm in Sources */, 34EFC7721B701D0300AD841F /* ASStackLayoutSpec.mm in Sources */, 34EFC7761B701D2A00AD841F /* ASStackPositionedLayout.mm in Sources */, - DECC2ED01C35C1C600388446 /* ASRangeControllerBeta.mm in Sources */, 34EFC7781B701D3100AD841F /* ASStackUnpositionedLayout.mm in Sources */, AC026B6C1BD57D6F00BBC17E /* ASChangeSetDataController.m in Sources */, 34EFC7741B701D0A00AD841F /* ASStaticLayoutSpec.mm in Sources */, diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 4a3f05c25b..e60d494a47 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -167,12 +167,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; self.strongCollectionNode = collectionNode; } - _layoutController = [ASDisplayNode shouldUseNewRenderingRange] ? - [[ASCollectionViewLayoutControllerBeta alloc] initWithCollectionView:self] : - [[ASCollectionViewLayoutControllerStable alloc] initWithCollectionView:self]; + _layoutController = [[ASCollectionViewLayoutControllerBeta alloc] initWithCollectionView:self]; - _rangeController = [ASDisplayNode shouldUseNewRenderingRange] ? [[ASRangeControllerBeta alloc] init] - : [[ASRangeControllerStable alloc] init]; + _rangeController = [[ASRangeControllerBeta alloc] init]; _rangeController.dataSource = self; _rangeController.delegate = self; _rangeController.layoutController = _layoutController; diff --git a/AsyncDisplayKit/ASDisplayNode+Beta.h b/AsyncDisplayKit/ASDisplayNode+Beta.h index d31ee49504..7cd124a7ae 100644 --- a/AsyncDisplayKit/ASDisplayNode+Beta.h +++ b/AsyncDisplayKit/ASDisplayNode+Beta.h @@ -8,9 +8,6 @@ @interface ASDisplayNode (Beta) -+ (BOOL)shouldUseNewRenderingRange; -+ (void)setShouldUseNewRenderingRange:(BOOL)shouldUseNewRenderingRange; - + (BOOL)usesImplicitHierarchyManagement; + (void)setUsesImplicitHierarchyManagement:(BOOL)enabled; diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index b9d1655163..b479b27498 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -256,7 +256,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) + (void)scheduleNodeForRecursiveDisplay:(ASDisplayNode *)node { ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert([ASDisplayNode shouldUseNewRenderingRange], @"+scheduleNodeForRecursiveDisplay: should never be called without the new rendering range enabled"); static NSMutableSet *nodesToDisplay = nil; static BOOL displayScheduled = NO; static ASDN::RecursiveMutex displaySchedulerLock; @@ -1666,18 +1665,6 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) return _flags.shouldBypassEnsureDisplay; } -static BOOL ShouldUseNewRenderingRange = YES; - -+ (BOOL)shouldUseNewRenderingRange -{ - return ShouldUseNewRenderingRange; -} - -+ (void)setShouldUseNewRenderingRange:(BOOL)shouldUseNewRenderingRange -{ - ShouldUseNewRenderingRange = shouldUseNewRenderingRange; -} - #pragma mark - For Subclasses - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize @@ -1922,7 +1909,7 @@ static BOOL ShouldUseNewRenderingRange = YES; } else { // NOTE: This case isn't currently supported as setInterfaceState: isn't exposed externally, and all // internal use cases are range-managed. When a node is visible, don't mess with display - CA will start it. - if ([ASDisplayNode shouldUseNewRenderingRange] && !ASInterfaceStateIncludesVisible(newState)) { + if (!ASInterfaceStateIncludesVisible(newState)) { // Check __implementsDisplay purely for efficiency - it's faster even than calling -asyncLayer. if ([self __implementsDisplay]) { if (nowDisplay) { diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 9cc2921edb..eeb1042fa7 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -148,8 +148,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; { _layoutController = [[ASFlowLayoutController alloc] initWithScrollOption:ASFlowLayoutDirectionVertical]; - _rangeController = [ASDisplayNode shouldUseNewRenderingRange] ? [[ASRangeControllerBeta alloc] init] - : [[ASRangeControllerStable alloc] init]; + _rangeController = [[ASRangeControllerBeta alloc] init]; _rangeController.layoutController = _layoutController; _rangeController.dataSource = self; _rangeController.delegate = self; diff --git a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h index 3f14672dcf..58745c8af4 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h +++ b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h @@ -19,9 +19,6 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface ASCollectionViewLayoutControllerStable : ASCollectionViewLayoutController -@end - @interface ASCollectionViewLayoutControllerBeta : ASCollectionViewLayoutController @end diff --git a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm index bf591b2d93..4515a9f3da 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm +++ b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm @@ -51,86 +51,6 @@ typedef struct ASRangeGeometry ASRangeGeometry; @end -@implementation ASCollectionViewLayoutControllerStable -{ - std::vector _updateRangeBoundsIndexedByRangeType; -} - -- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView -{ - if (!(self = [super initWithCollectionView:collectionView])) { - return nil; - } - - _updateRangeBoundsIndexedByRangeType = std::vector(ASLayoutRangeTypeCount); - return self; -} - -- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType -{ - ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType]; - ASRangeGeometry rangeGeometry = [self rangeGeometryWithScrollDirection:scrollDirection tuningParameters:tuningParameters]; - _updateRangeBoundsIndexedByRangeType[rangeType] = rangeGeometry.updateBounds; - return [self indexPathsForItemsWithinRangeBounds:rangeGeometry.rangeBounds]; -} - -- (NSSet *)indexPathsForItemsWithinRangeBounds:(CGRect)rangeBounds -{ - NSMutableSet *indexPathSet = [[NSMutableSet alloc] init]; - NSArray *layoutAttributes = [_collectionViewLayout layoutAttributesForElementsInRect:rangeBounds]; - for (UICollectionViewLayoutAttributes *la in layoutAttributes) { - if (la.representedElementCategory == UICollectionElementCategoryCell) { - [indexPathSet addObject:la.indexPath]; - } - } - return indexPathSet; -} - -- (ASRangeGeometry)rangeGeometryWithScrollDirection:(ASScrollDirection)scrollDirection - tuningParameters:(ASRangeTuningParameters)tuningParameters -{ - CGRect rangeBounds = _collectionView.bounds; - CGRect updateBounds = _collectionView.bounds; - - // Scrollable directions can change for non-flow layouts - if ([_collectionViewLayout asdk_isFlowLayout] == NO) { - _scrollableDirections = [_collectionView scrollableDirections]; - } - - rangeBounds = CGRectExpandToRangeWithScrollableDirections(rangeBounds, tuningParameters, _scrollableDirections, scrollDirection); - - ASRangeTuningParameters updateTuningParameters = tuningParameters; - updateTuningParameters.leadingBufferScreenfuls = MIN(updateTuningParameters.leadingBufferScreenfuls * 0.5, 0.95); - updateTuningParameters.trailingBufferScreenfuls = MIN(updateTuningParameters.trailingBufferScreenfuls * 0.5, 0.95); - - updateBounds = CGRectExpandToRangeWithScrollableDirections(updateBounds, updateTuningParameters, _scrollableDirections, scrollDirection); - - return {rangeBounds, updateBounds}; -} - -- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths rangeType:(ASLayoutRangeType)rangeType -{ - CGSize viewportSize = [self viewportSize]; - CGRect updateRangeBounds = _updateRangeBoundsIndexedByRangeType[rangeType]; - if (CGRectIsEmpty(updateRangeBounds)) { - return YES; - } - - CGRect currentBounds = _collectionView.bounds; - if (CGRectIsEmpty(currentBounds)) { - currentBounds = CGRectMake(0, 0, viewportSize.width, viewportSize.height); - } - - if (CGRectContainsRect(updateRangeBounds, currentBounds)) { - return NO; - } else { - return YES; - } -} - -@end - - @implementation ASCollectionViewLayoutControllerBeta - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index 6a4fde0b23..f624551107 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -77,9 +77,6 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface ASRangeControllerStable : ASRangeController -@end - @interface ASRangeControllerBeta : ASRangeController @end diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index fbcddb2351..dba59fd1df 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -38,243 +38,4 @@ return [_layoutController tuningParametersForRangeMode:rangeMode rangeType:rangeType]; } -@end - -@interface ASRangeControllerStable () -{ - BOOL _rangeIsValid; - - // keys should be ASLayoutRangeTypes and values NSSets containing NSIndexPaths - NSMutableDictionary *_rangeTypeIndexPaths; - NSDictionary *_rangeTypeHandlers; - BOOL _queuedRangeUpdate; - - ASScrollDirection _scrollDirection; -} - -@end - -@implementation ASRangeControllerStable - -- (instancetype)init -{ - if (!(self = [super init])) { - return nil; - } - - _rangeIsValid = YES; - _rangeTypeIndexPaths = [NSMutableDictionary dictionary]; - _rangeTypeHandlers = @{ - @(ASLayoutRangeTypeDisplay) : [[ASRangeHandlerRender alloc] init], - @(ASLayoutRangeTypeFetchData): [[ASRangeHandlerPreload alloc] init], - }; - - return self; -} - -#pragma mark - Cell node view handling - -- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node -{ - if (node.view.superview == contentView) { - // this content view is already correctly configured - return; - } - - // clean the content view - for (UIView *view in contentView.subviews) { - [view removeFromSuperview]; - } - - [self moveCellNode:node toView:contentView]; -} - -- (void)moveCellNode:(ASCellNode *)node toView:(UIView *)view -{ - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(node, @"Cannot move a nil node to a view"); - ASDisplayNodeAssert(view, @"Cannot move a node to a non-existent view"); - - // force any nodes that are about to come into view to have display enabled - if (node.displaySuspended) { - [node recursivelySetDisplaySuspended:NO]; - } - - [view addSubview:node.view]; -} - -#pragma mark - Core visible node range managment API - -- (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection -{ - _scrollDirection = scrollDirection; - - if (_queuedRangeUpdate) { - return; - } - - // coalesce these events -- handling them multiple times per runloop is noisy and expensive - _queuedRangeUpdate = YES; - - [self performSelector:@selector(_updateVisibleNodeIndexPaths) - withObject:nil - afterDelay:0 - inModes:@[ NSRunLoopCommonModes ]]; -} - -- (void)_updateVisibleNodeIndexPaths -{ - if (!_queuedRangeUpdate) { - return; - } - - NSArray *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self]; - - if (visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)... - _queuedRangeUpdate = NO; - return ; // don't do anything for this update, but leave _rangeIsValid to make sure we update it later - } - - NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths]; - CGSize viewportSize = [_dataSource viewportSizeForRangeController:self]; - [_layoutController setViewportSize:viewportSize]; - - // the layout controller needs to know what the current visible indices are to calculate range offsets - if ([_layoutController respondsToSelector:@selector(setVisibleNodeIndexPaths:)]) { - [_layoutController setVisibleNodeIndexPaths:visibleNodePaths]; - } - - for (NSInteger i = 0; i < ASLayoutRangeTypeCount; i++) { - ASLayoutRangeType rangeType = (ASLayoutRangeType)i; - id rangeKey = @(rangeType); - - // this delegate decide what happens when a node is added or removed from a range - id rangeHandler = _rangeTypeHandlers[rangeKey]; - - if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths rangeType:rangeType]) { - 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 - NSMutableSet *removedIndexPaths = _rangeIsValid ? [_rangeTypeIndexPaths[rangeKey] mutableCopy] : [NSMutableSet set]; - [removedIndexPaths minusSet:indexPaths]; - [removedIndexPaths minusSet:visibleNodePathsSet]; - - if (removedIndexPaths.count) { - NSArray *removedNodes = [_dataSource rangeController:self nodesAtIndexPaths:[removedIndexPaths allObjects]]; - for (ASCellNode *node in removedNodes) { - // since this class usually manages large or infinite data sets, the working range - // directly bounds memory usage by requiring redrawing any content that falls outside the range. - [rangeHandler node:node exitedRangeOfType:rangeType]; - } - } - - // Notify to add index paths that are not currently in _rangeTypeIndexPaths - NSMutableSet *addedIndexPaths = [indexPaths mutableCopy]; - [addedIndexPaths minusSet:_rangeTypeIndexPaths[rangeKey]]; - - // The preload range (for example) should include nodes that are visible - // TODO: remove this once we have removed the dependency on Core Animation's -display - if ([self shouldSkipVisibleNodesForRangeType:rangeType]) { - [addedIndexPaths minusSet:visibleNodePathsSet]; - } - - if (addedIndexPaths.count) { - NSArray *addedNodes = [_dataSource rangeController:self nodesAtIndexPaths:[addedIndexPaths allObjects]]; - for (ASCellNode *node in addedNodes) { - [rangeHandler node:node enteredRangeOfType:rangeType]; - } - } - - // set the range indexpaths so that we can remove/add on the next update pass - _rangeTypeIndexPaths[rangeKey] = indexPaths; - } - } - - _rangeIsValid = YES; - _queuedRangeUpdate = NO; -} - -- (BOOL)shouldSkipVisibleNodesForRangeType:(ASLayoutRangeType)rangeType -{ - return rangeType == ASLayoutRangeTypeDisplay; -} - -#pragma mark - ASDataControllerDelegete - -- (void)dataControllerBeginUpdates:(ASDataController *)dataController -{ - ASPerformBlockOnMainThread(^{ - [_delegate didBeginUpdatesInRangeController:self]; - }); -} - -- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion -{ - ASPerformBlockOnMainThread(^{ - [_delegate rangeController:self didEndUpdatesAnimated:animated completion:completion]; - }); -} - -- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASDisplayNodeAssert(nodes.count == indexPaths.count, @"Invalid index path"); - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - [_delegate rangeController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; - }); -} - -- (void)dataController:(ASDataController *)dataController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - - // When removing nodes we need to make sure that removed indexPaths are not left in _rangeTypeIndexPaths, - // otherwise _updateVisibleNodeIndexPaths may try to retrieve nodes from dataSource that aren't there anymore - for (NSInteger i = 0; i < ASLayoutRangeTypeCount; i++) { - id rangeKey = @((ASLayoutRangeType)i); - NSMutableSet *rangePaths = [_rangeTypeIndexPaths[rangeKey] mutableCopy]; - for (NSIndexPath *path in indexPaths) { - [rangePaths removeObject:path]; - } - _rangeTypeIndexPaths[rangeKey] = rangePaths; - } - - [_delegate rangeController:self didDeleteNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; - }); -} - -- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASDisplayNodeAssert(sections.count == indexSet.count, @"Invalid sections"); - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - [_delegate rangeController:self didInsertSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; - }); -} - -- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - - // When removing nodes we need to make sure that removed indexPaths are not left in _rangeTypeIndexPaths, - // otherwise _updateVisibleNodeIndexPaths may try to retrieve nodes from dataSource that aren't there anymore - for (NSInteger i = 0; i < ASLayoutRangeTypeCount; i++) { - id rangeKey = @((ASLayoutRangeType)i); - NSMutableSet *rangePaths = [_rangeTypeIndexPaths[rangeKey] mutableCopy]; - for (NSIndexPath *path in _rangeTypeIndexPaths[rangeKey]) { - if ([indexSet containsIndex:path.section]) { - [rangePaths removeObject:path]; - } - } - _rangeTypeIndexPaths[rangeKey] = rangePaths; - } - - [_delegate rangeController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; - }); -} - -@end +@end \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm index 25859bd417..df7b4acb93 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm +++ b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm @@ -18,36 +18,6 @@ @end @implementation ASRangeHandlerRender -@synthesize workingWindow = _workingWindow; - -- (UIWindow *)workingWindow -{ - ASDisplayNodeAssertMainThread(); - - // we add nodes' views to this invisible window to start async rendering - // TODO: Replace this with directly triggering display https://github.com/facebook/AsyncDisplayKit/issues/315 - // Update: Latest attempt is at https://github.com/facebook/AsyncDisplayKit/pull/828 - - if (!_workingWindow && ![ASDisplayNode shouldUseNewRenderingRange]) { - _workingWindow = [[UIWindow alloc] initWithFrame:CGRectZero]; - _workingWindow.windowLevel = UIWindowLevelNormal - 1000; - _workingWindow.userInteractionEnabled = NO; - _workingWindow.hidden = YES; - _workingWindow.alpha = 0.0; - } - - return _workingWindow; -} - -- (void)dealloc -{ - if (![ASDisplayNode shouldUseNewRenderingRange]) { - for (CALayer *layer in [self.workingWindow.layer.sublayers copy]) { - ASDisplayNode *node = layer.asyncdisplaykit_node; - [self node:node exitedRangeOfType:ASLayoutRangeTypeDisplay]; - } - } -} - (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType { @@ -65,16 +35,7 @@ // ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled"); - if ([ASDisplayNode shouldUseNewRenderingRange]) { - [node recursivelyEnsureDisplaySynchronously:NO]; - } else { - // Add the node's layer to an off-screen window to trigger display and mark its contents as non-volatile. - // Use the layer directly to avoid the substantial overhead of UIView heirarchy manipulations. - // Any view-backed nodes will still create their views in order to assemble the layer heirarchy, and they will - // also assemble a view subtree for the node, but we avoid the much more significant expense triggered by a view - // being added or removed from an onscreen window (responder chain setup, will/DidMoveToWindow: recursive calls, etc) - [[[self workingWindow] layer] addSublayer:node.layer]; - } + [node recursivelyEnsureDisplaySynchronously:NO]; } - (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType @@ -103,24 +64,9 @@ [node exitInterfaceState:ASInterfaceStateDisplay]; // ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled"); - - if ([ASDisplayNode shouldUseNewRenderingRange]) { - if (![node isLayerBacked]) { - [node.view removeFromSuperview]; - } else { - [node.layer removeFromSuperlayer]; - } + if (![node isLayerBacked]) { + [node.view removeFromSuperview]; } else { - if (node.layer.superlayer != [[self workingWindow] layer]) { - // In this case, the node has previously passed through the working range (or it is zero), and it has now fallen outside the working range. - if (![node isLayerBacked]) { - // If the node is view-backed, we need to make sure to remove the view (which is now present in the containing cell contentsView). - // Layer-backed nodes will be fully handled by the unconditional removal below. - [node.view removeFromSuperview]; - } - } - - // At this point, the node's layer may validly be present either in the workingWindow, or in the contentsView of a cell. [node.layer removeFromSuperlayer]; } } diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index 29e9b64af8..63afebb2ed 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -290,13 +290,11 @@ _messageToViewOrLayer(setNeedsDisplay); - if ([ASDisplayNode shouldUseNewRenderingRange]) { - BOOL nowDisplay = ASInterfaceStateIncludesDisplay(_interfaceState); - // FIXME: This should not need to recursively display, so create a non-recursive variant. - // The semantics of setNeedsDisplay (as defined by CALayer behavior) are not recursive. - if (_layer && !_flags.synchronous && nowDisplay && [self __implementsDisplay]) { - [ASDisplayNode scheduleNodeForRecursiveDisplay:self]; - } + BOOL nowDisplay = ASInterfaceStateIncludesDisplay(_interfaceState); + // FIXME: This should not need to recursively display, so create a non-recursive variant. + // The semantics of setNeedsDisplay (as defined by CALayer behavior) are not recursive. + if (_layer && !_flags.synchronous && nowDisplay && [self __implementsDisplay]) { + [ASDisplayNode scheduleNodeForRecursiveDisplay:self]; } } } diff --git a/AsyncDisplayKitTestHost/AppDelegate.mm b/AsyncDisplayKitTestHost/AppDelegate.mm index 02b188967c..79640a07a8 100644 --- a/AsyncDisplayKitTestHost/AppDelegate.mm +++ b/AsyncDisplayKitTestHost/AppDelegate.mm @@ -14,7 +14,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [ASDisplayNode setShouldUseNewRenderingRange:YES]; return YES; } From 026761c610c115860876b7815fe32fb6c0637083 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Sun, 7 Feb 2016 14:39:01 -0800 Subject: [PATCH 2/7] Rename ASRangeControllerBeta to ASRangeController and use exclusively --- AsyncDisplayKit/ASCollectionView.mm | 2 +- AsyncDisplayKit/ASTableView.mm | 2 +- AsyncDisplayKit/Details/ASRangeController.h | 3 - AsyncDisplayKit/Details/ASRangeController.mm | 347 +++++++++++++++- .../Details/ASRangeControllerBeta.h | 20 - .../Details/ASRangeControllerBeta.mm | 374 ------------------ 6 files changed, 347 insertions(+), 401 deletions(-) delete mode 100644 AsyncDisplayKit/Details/ASRangeControllerBeta.h delete mode 100644 AsyncDisplayKit/Details/ASRangeControllerBeta.mm diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index e60d494a47..25a51674ef 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -169,7 +169,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _layoutController = [[ASCollectionViewLayoutControllerBeta alloc] initWithCollectionView:self]; - _rangeController = [[ASRangeControllerBeta alloc] init]; + _rangeController = [[ASRangeController alloc] init]; _rangeController.dataSource = self; _rangeController.delegate = self; _rangeController.layoutController = _layoutController; diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index eeb1042fa7..474d2d79d7 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -148,7 +148,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; { _layoutController = [[ASFlowLayoutController alloc] initWithScrollOption:ASFlowLayoutDirectionVertical]; - _rangeController = [[ASRangeControllerBeta alloc] init]; + _rangeController = [[ASRangeController alloc] init]; _rangeController.layoutController = _layoutController; _rangeController.dataSource = self; _rangeController.delegate = self; diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index f624551107..d5288f40e2 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -77,9 +77,6 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface ASRangeControllerBeta : ASRangeController -@end - /** * Data source for ASRangeController. * diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index dba59fd1df..3b6966d9c6 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -10,22 +10,315 @@ #import "ASAssert.h" #import "ASDisplayNodeExtras.h" +#import "ASDisplayNodeInternal.h" #import "ASMultiDimensionalArrayUtils.h" #import "ASRangeHandlerVisible.h" #import "ASRangeHandlerRender.h" #import "ASRangeHandlerPreload.h" #import "ASInternalHelpers.h" -#import "ASLayoutController.h" -#import "ASLayoutRangeType.h" +#import "ASDisplayNode+FrameworkPrivate.h" + +@interface ASRangeController () +{ + BOOL _rangeIsValid; + BOOL _queuedRangeUpdate; + BOOL _layoutControllerImplementsSetVisibleIndexPaths; + ASScrollDirection _scrollDirection; + NSSet *_allPreviousIndexPaths; + ASLayoutRangeMode _currentRangeMode; + BOOL _didRegisterForNotifications; + CFAbsoluteTime _pendingDisplayNodesTimestamp; +} + +@end @implementation ASRangeController +- (instancetype)init +{ + if (!(self = [super init])) { + return nil; + } + + _rangeIsValid = YES; + _currentRangeMode = ASLayoutRangeModeInvalid; + + return self; +} + +- (void)dealloc +{ + if (_didRegisterForNotifications) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil]; + } +} + +#pragma mark - Core visible node range managment API + ++ (ASLayoutRangeMode)rangeModeForInterfaceState:(ASInterfaceState)interfaceState + currentRangeMode:(ASLayoutRangeMode)currentRangeMode +{ + BOOL isVisible = (ASInterfaceStateIncludesVisible(interfaceState)); + BOOL isFirstRangeUpdate = (currentRangeMode == ASLayoutRangeModeInvalid); + if (!isVisible || isFirstRangeUpdate) { + return ASLayoutRangeModeMinimum; + } + + return ASLayoutRangeModeFull; +} + - (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection { + _scrollDirection = scrollDirection; + [self scheduleRangeUpdate]; } +- (void)scheduleRangeUpdate +{ + if (_queuedRangeUpdate) { + return; + } + + // coalesce these events -- handling them multiple times per runloop is noisy and expensive + _queuedRangeUpdate = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + [self _updateVisibleNodeIndexPaths]; + }); +} + +- (void)setLayoutController:(id)layoutController +{ + _layoutController = layoutController; + _layoutControllerImplementsSetVisibleIndexPaths = [_layoutController respondsToSelector:@selector(setVisibleNodeIndexPaths:)]; +} + +- (void)_updateVisibleNodeIndexPaths +{ + ASDisplayNodeAssert(_layoutController, @"An ASLayoutController is required by ASRangeController"); + if (!_queuedRangeUpdate || !_layoutController) { + return; + } + + // TODO: Consider if we need to use this codepath, or can rely on something more similar to the data & display ranges + // Example: ... = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:ASLayoutRangeTypeVisible]; + NSArray *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self]; + + if (visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)... + _queuedRangeUpdate = NO; + return; // don't do anything for this update, but leave _rangeIsValid == NO to make sure we update it later + } + + [_layoutController setViewportSize:[_dataSource viewportSizeForRangeController:self]]; + + // the layout controller needs to know what the current visible indices are to calculate range offsets + if (_layoutControllerImplementsSetVisibleIndexPaths) { + [_layoutController setVisibleNodeIndexPaths:visibleNodePaths]; + } + + // allNodes is a 2D array: it contains arrays for each section, each containing nodes. + NSArray *allNodes = [_dataSource completedNodes]; + NSUInteger numberOfSections = [allNodes count]; + + NSArray *currentSectionNodes = nil; + NSInteger currentSectionIndex = -1; // Set to -1 so we don't match any indexPath.section on the first iteration. + NSUInteger numberOfNodesInSection = 0; + + NSSet *visibleIndexPaths = [NSSet setWithArray:visibleNodePaths]; + NSSet *displayIndexPaths = nil; + NSSet *fetchDataIndexPaths = 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. + NSMutableOrderedSet *allIndexPaths = [[NSMutableOrderedSet alloc] initWithSet:visibleIndexPaths]; + + ASInterfaceState selfInterfaceState = [_dataSource interfaceStateForRangeController:self]; + ASLayoutRangeMode rangeMode = [ASRangeController rangeModeForInterfaceState:selfInterfaceState + currentRangeMode:_currentRangeMode]; + + ASRangeTuningParameters parametersFetchData = [_layoutController tuningParametersForRangeMode:rangeMode + rangeType:ASLayoutRangeTypeFetchData]; + if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersFetchData, ASRangeTuningParametersZero)) { + fetchDataIndexPaths = visibleIndexPaths; + } else { + fetchDataIndexPaths = [_layoutController indexPathsForScrolling:_scrollDirection + rangeMode:rangeMode + rangeType:ASLayoutRangeTypeFetchData]; + } + + ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeMode:rangeMode + rangeType:ASLayoutRangeTypeDisplay]; + if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, ASRangeTuningParametersZero)) { + displayIndexPaths = visibleIndexPaths; + } else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, parametersFetchData)) { + displayIndexPaths = fetchDataIndexPaths; + } 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. + // 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]; + + // 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 + // scroll or major main thread stall could cause entirely disjoint sets. In either case we must visit all. + // Calling "-set" on NSMutableOrderedSet just references the underlying mutable data store, so we must copy it. + NSSet *allCurrentIndexPaths = [[allIndexPaths set] copy]; + [allIndexPaths unionSet:_allPreviousIndexPaths]; + _allPreviousIndexPaths = allCurrentIndexPaths; + _currentRangeMode = rangeMode; + + if (!_rangeIsValid) { + [allIndexPaths addObjectsFromArray:ASIndexPathsForMultidimensionalArray(allNodes)]; + } + + // TODO Don't register for notifications if this range update doesn't cause any node to enter rendering pipeline. + // This can be done once there is an API to observe to (or be notified upon) interface state changes or pipeline enterings + [self registerForNotificationsForInterfaceStateIfNeeded:selfInterfaceState]; + +#if RangeControllerLoggingEnabled + NSMutableArray *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil); +#endif + + for (NSIndexPath *indexPath in allIndexPaths) { + // Before a node / indexPath is exposed to ASRangeController, ASDataController should have already measured it. + // For consistency, make sure each node knows that it should measure itself if something changes. + ASInterfaceState interfaceState = ASInterfaceStateMeasureLayout; + + if (ASInterfaceStateIncludesVisible(selfInterfaceState)) { + if ([fetchDataIndexPaths containsObject:indexPath]) { + interfaceState |= ASInterfaceStateFetchData; + } + if ([displayIndexPaths containsObject:indexPath]) { + interfaceState |= ASInterfaceStateDisplay; + } + if ([visibleIndexPaths containsObject:indexPath]) { + interfaceState |= ASInterfaceStateVisible; + } + } else { + // If selfInterfaceState isn't visible, then visibleIndexPaths represents what /will/ be immediately visible at the + // instant we come onscreen. So, fetch data and display all of those things, but don't waste resources preloading yet. + // We handle this as a separate case to minimize set operations for offscreen preloading, including containsObject:. + + // Set Layout, Fetch Data, Display. DO NOT set Visible: even though these elements are in the visible range / "viewport", + // our overall container object is itself not visible yet. The moment it becomes visible, we will run the condition above. + if ([allCurrentIndexPaths containsObject:indexPath]) { + // 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. + interfaceState |= ASInterfaceStateDisplay; + interfaceState |= ASInterfaceStateFetchData; + } + } + + NSInteger section = indexPath.section; + NSInteger row = indexPath.row; + + if (section >= 0 && row >= 0 && section < numberOfSections) { + if (section != currentSectionIndex) { + // Often we'll be dealing with indexPaths in the same section, but the set isn't sorted and we may even bounce + // between the same ones. Still, this saves dozens of method calls to access the inner array and count. + currentSectionNodes = [allNodes objectAtIndex:section]; + numberOfNodesInSection = [currentSectionNodes count]; + currentSectionIndex = section; + } + + if (row < numberOfNodesInSection) { + ASDisplayNode *node = [currentSectionNodes objectAtIndex:row]; + + ASDisplayNodeAssert(node.hierarchyState & ASHierarchyStateRangeManaged, @"All nodes reaching this point should be range-managed, or interfaceState may be incorrectly reset."); + // Skip the many method calls of the recursive operation if the top level cell node already has the right interfaceState. + if (node.interfaceState != interfaceState) { +#if RangeControllerLoggingEnabled + [modifiedIndexPaths addObject:indexPath]; +#endif + [node recursivelySetInterfaceState:interfaceState]; + } + } + } + } + + if (_didRegisterForNotifications) { + _pendingDisplayNodesTimestamp = CFAbsoluteTimeGetCurrent(); + } + + _rangeIsValid = YES; + _queuedRangeUpdate = NO; + +#if RangeControllerLoggingEnabled + NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths]; + BOOL setsAreEqual = [visibleIndexPaths isEqualToSet:visibleNodePathsSet]; + NSLog(@"visible sets are equal: %d", setsAreEqual); + if (!setsAreEqual) { + NSLog(@"standard: %@", visibleIndexPaths); + NSLog(@"custom: %@", visibleNodePathsSet); + } + + [modifiedIndexPaths sortUsingSelector:@selector(compare:)]; + + for (NSIndexPath *indexPath in modifiedIndexPaths) { + ASDisplayNode *node = [_dataSource rangeController:self nodeAtIndexPath:indexPath]; + ASInterfaceState interfaceState = node.interfaceState; + BOOL inVisible = ASInterfaceStateIncludesVisible(interfaceState); + BOOL inDisplay = ASInterfaceStateIncludesDisplay(interfaceState); + BOOL inFetchData = ASInterfaceStateIncludesFetchData(interfaceState); + NSLog(@"indexPath %@, Visible: %d, Display: %d, FetchData: %d", indexPath, inVisible, inDisplay, inFetchData); + } +#endif +} + +#pragma mark - Notification observers + +- (void)registerForNotificationsForInterfaceStateIfNeeded:(ASInterfaceState)interfaceState +{ + if (!_didRegisterForNotifications) { + ASLayoutRangeMode nextRangeMode = [ASRangeController rangeModeForInterfaceState:interfaceState + currentRangeMode:_currentRangeMode]; + if (_currentRangeMode != nextRangeMode) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(scheduledNodesDidDisplay:) + name:ASRenderingEngineDidDisplayScheduledNodesNotification + object:nil]; + _didRegisterForNotifications = YES; + } + } +} + +- (void)scheduledNodesDidDisplay:(NSNotification *)notification +{ + CFAbsoluteTime notificationTimestamp = ((NSNumber *)[notification.userInfo objectForKey:ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp]).doubleValue; + if (_pendingDisplayNodesTimestamp < notificationTimestamp) { + // The rendering engine has processed all the nodes this range controller scheduled. Let's schedule a range update + [[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil]; + _didRegisterForNotifications = NO; + + [self scheduleRangeUpdate]; + } +} + +#pragma mark - Cell node view handling + - (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node { + ASDisplayNodeAssertMainThread(); + ASDisplayNodeAssert(node, @"Cannot move a nil node to a view"); + ASDisplayNodeAssert(contentView, @"Cannot move a node to a non-existent view"); + + if (node.view.superview == contentView) { + // this content view is already correctly configured + return; + } + + // clean the content view + for (UIView *view in contentView.subviews) { + [view removeFromSuperview]; + } + + [contentView addSubview:node.view]; } - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType @@ -38,4 +331,54 @@ return [_layoutController tuningParametersForRangeMode:rangeMode rangeType:rangeType]; } +#pragma mark - ASDataControllerDelegete + +- (void)dataControllerBeginUpdates:(ASDataController *)dataController +{ + ASPerformBlockOnMainThread(^{ + [_delegate didBeginUpdatesInRangeController:self]; + }); +} + +- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion +{ + ASPerformBlockOnMainThread(^{ + [_delegate rangeController:self didEndUpdatesAnimated:animated completion:completion]; + }); +} + +- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + ASDisplayNodeAssert(nodes.count == indexPaths.count, @"Invalid index path"); + ASPerformBlockOnMainThread(^{ + _rangeIsValid = NO; + [_delegate rangeController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; + }); +} + +- (void)dataController:(ASDataController *)dataController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + ASPerformBlockOnMainThread(^{ + _rangeIsValid = NO; + [_delegate rangeController:self didDeleteNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; + }); +} + +- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + ASDisplayNodeAssert(sections.count == indexSet.count, @"Invalid sections"); + ASPerformBlockOnMainThread(^{ + _rangeIsValid = NO; + [_delegate rangeController:self didInsertSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; + }); +} + +- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + ASPerformBlockOnMainThread(^{ + _rangeIsValid = NO; + [_delegate rangeController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; + }); +} + @end \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeControllerBeta.h b/AsyncDisplayKit/Details/ASRangeControllerBeta.h deleted file mode 100644 index 7c8385f8c1..0000000000 --- a/AsyncDisplayKit/Details/ASRangeControllerBeta.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -// ASRangeControllerBeta defined in ASRangeController.h - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeControllerBeta.mm b/AsyncDisplayKit/Details/ASRangeControllerBeta.mm deleted file mode 100644 index 3cf4943079..0000000000 --- a/AsyncDisplayKit/Details/ASRangeControllerBeta.mm +++ /dev/null @@ -1,374 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "ASRangeControllerBeta.h" - -#import "ASAssert.h" -#import "ASDisplayNodeExtras.h" -#import "ASDisplayNodeInternal.h" -#import "ASMultiDimensionalArrayUtils.h" -#import "ASRangeHandlerVisible.h" -#import "ASRangeHandlerRender.h" -#import "ASRangeHandlerPreload.h" -#import "ASInternalHelpers.h" -#import "ASDisplayNode+FrameworkPrivate.h" - -@interface ASRangeControllerBeta () -{ - BOOL _rangeIsValid; - BOOL _queuedRangeUpdate; - BOOL _layoutControllerImplementsSetVisibleIndexPaths; - ASScrollDirection _scrollDirection; - NSSet *_allPreviousIndexPaths; - ASLayoutRangeMode _currentRangeMode; - BOOL _didRegisterForNotifications; - CFAbsoluteTime _pendingDisplayNodesTimestamp; -} - -@end - -@implementation ASRangeControllerBeta - -- (instancetype)init -{ - if (!(self = [super init])) { - return nil; - } - - _rangeIsValid = YES; - _currentRangeMode = ASLayoutRangeModeInvalid; - - return self; -} - -- (void)dealloc -{ - if (_didRegisterForNotifications) { - [[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil]; - } -} - -#pragma mark - Core visible node range managment API - -+ (ASLayoutRangeMode)rangeModeForInterfaceState:(ASInterfaceState)interfaceState - currentRangeMode:(ASLayoutRangeMode)currentRangeMode -{ - BOOL isVisible = (ASInterfaceStateIncludesVisible(interfaceState)); - BOOL isFirstRangeUpdate = (currentRangeMode == ASLayoutRangeModeInvalid); - if (!isVisible || isFirstRangeUpdate) { - return ASLayoutRangeModeMinimum; - } - - return ASLayoutRangeModeFull; -} - -- (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection -{ - _scrollDirection = scrollDirection; - [self scheduleRangeUpdate]; -} - -- (void)scheduleRangeUpdate -{ - if (_queuedRangeUpdate) { - return; - } - - // coalesce these events -- handling them multiple times per runloop is noisy and expensive - _queuedRangeUpdate = YES; - - dispatch_async(dispatch_get_main_queue(), ^{ - [self _updateVisibleNodeIndexPaths]; - }); -} - -- (void)setLayoutController:(id)layoutController -{ - _layoutController = layoutController; - _layoutControllerImplementsSetVisibleIndexPaths = [_layoutController respondsToSelector:@selector(setVisibleNodeIndexPaths:)]; -} - -- (void)_updateVisibleNodeIndexPaths -{ - ASDisplayNodeAssert(_layoutController, @"An ASLayoutController is required by ASRangeController"); - if (!_queuedRangeUpdate || !_layoutController) { - return; - } - - // TODO: Consider if we need to use this codepath, or can rely on something more similar to the data & display ranges - // Example: ... = [_layoutController indexPathsForScrolling:_scrollDirection rangeType:ASLayoutRangeTypeVisible]; - NSArray *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self]; - - if (visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)... - _queuedRangeUpdate = NO; - return; // don't do anything for this update, but leave _rangeIsValid == NO to make sure we update it later - } - - [_layoutController setViewportSize:[_dataSource viewportSizeForRangeController:self]]; - - // the layout controller needs to know what the current visible indices are to calculate range offsets - if (_layoutControllerImplementsSetVisibleIndexPaths) { - [_layoutController setVisibleNodeIndexPaths:visibleNodePaths]; - } - - // allNodes is a 2D array: it contains arrays for each section, each containing nodes. - NSArray *allNodes = [_dataSource completedNodes]; - NSUInteger numberOfSections = [allNodes count]; - - NSArray *currentSectionNodes = nil; - NSInteger currentSectionIndex = -1; // Set to -1 so we don't match any indexPath.section on the first iteration. - NSUInteger numberOfNodesInSection = 0; - - NSSet *visibleIndexPaths = [NSSet setWithArray:visibleNodePaths]; - NSSet *displayIndexPaths = nil; - NSSet *fetchDataIndexPaths = 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. - NSMutableOrderedSet *allIndexPaths = [[NSMutableOrderedSet alloc] initWithSet:visibleIndexPaths]; - - ASInterfaceState selfInterfaceState = [_dataSource interfaceStateForRangeController:self]; - ASLayoutRangeMode rangeMode = [ASRangeControllerBeta rangeModeForInterfaceState:selfInterfaceState - currentRangeMode:_currentRangeMode]; - - ASRangeTuningParameters parametersFetchData = [_layoutController tuningParametersForRangeMode:rangeMode - rangeType:ASLayoutRangeTypeFetchData]; - if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersFetchData, ASRangeTuningParametersZero)) { - fetchDataIndexPaths = visibleIndexPaths; - } else { - fetchDataIndexPaths = [_layoutController indexPathsForScrolling:_scrollDirection - rangeMode:rangeMode - rangeType:ASLayoutRangeTypeFetchData]; - } - - ASRangeTuningParameters parametersDisplay = [_layoutController tuningParametersForRangeMode:rangeMode - rangeType:ASLayoutRangeTypeDisplay]; - if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, ASRangeTuningParametersZero)) { - displayIndexPaths = visibleIndexPaths; - } else if (ASRangeTuningParametersEqualToRangeTuningParameters(parametersDisplay, parametersFetchData)) { - displayIndexPaths = fetchDataIndexPaths; - } 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. - // 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]; - - // 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 - // scroll or major main thread stall could cause entirely disjoint sets. In either case we must visit all. - // Calling "-set" on NSMutableOrderedSet just references the underlying mutable data store, so we must copy it. - NSSet *allCurrentIndexPaths = [[allIndexPaths set] copy]; - [allIndexPaths unionSet:_allPreviousIndexPaths]; - _allPreviousIndexPaths = allCurrentIndexPaths; - _currentRangeMode = rangeMode; - - if (!_rangeIsValid) { - [allIndexPaths addObjectsFromArray:ASIndexPathsForMultidimensionalArray(allNodes)]; - } - - // TODO Don't register for notifications if this range update doesn't cause any node to enter rendering pipeline. - // This can be done once there is an API to observe to (or be notified upon) interface state changes or pipeline enterings - [self registerForNotificationsForInterfaceStateIfNeeded:selfInterfaceState]; - -#if RangeControllerLoggingEnabled - NSMutableArray *modifiedIndexPaths = (RangeControllerLoggingEnabled ? [NSMutableArray array] : nil); -#endif - - for (NSIndexPath *indexPath in allIndexPaths) { - // Before a node / indexPath is exposed to ASRangeController, ASDataController should have already measured it. - // For consistency, make sure each node knows that it should measure itself if something changes. - ASInterfaceState interfaceState = ASInterfaceStateMeasureLayout; - - if (ASInterfaceStateIncludesVisible(selfInterfaceState)) { - if ([fetchDataIndexPaths containsObject:indexPath]) { - interfaceState |= ASInterfaceStateFetchData; - } - if ([displayIndexPaths containsObject:indexPath]) { - interfaceState |= ASInterfaceStateDisplay; - } - if ([visibleIndexPaths containsObject:indexPath]) { - interfaceState |= ASInterfaceStateVisible; - } - } else { - // If selfInterfaceState isn't visible, then visibleIndexPaths represents what /will/ be immediately visible at the - // instant we come onscreen. So, fetch data and display all of those things, but don't waste resources preloading yet. - // We handle this as a separate case to minimize set operations for offscreen preloading, including containsObject:. - - // Set Layout, Fetch Data, Display. DO NOT set Visible: even though these elements are in the visible range / "viewport", - // our overall container object is itself not visible yet. The moment it becomes visible, we will run the condition above. - if ([allCurrentIndexPaths containsObject:indexPath]) { - // 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. - interfaceState |= ASInterfaceStateDisplay; - interfaceState |= ASInterfaceStateFetchData; - } - } - - NSInteger section = indexPath.section; - NSInteger row = indexPath.row; - - if (section >= 0 && row >= 0 && section < numberOfSections) { - if (section != currentSectionIndex) { - // Often we'll be dealing with indexPaths in the same section, but the set isn't sorted and we may even bounce - // between the same ones. Still, this saves dozens of method calls to access the inner array and count. - currentSectionNodes = [allNodes objectAtIndex:section]; - numberOfNodesInSection = [currentSectionNodes count]; - currentSectionIndex = section; - } - - if (row < numberOfNodesInSection) { - ASDisplayNode *node = [currentSectionNodes objectAtIndex:row]; - - ASDisplayNodeAssert(node.hierarchyState & ASHierarchyStateRangeManaged, @"All nodes reaching this point should be range-managed, or interfaceState may be incorrectly reset."); - // Skip the many method calls of the recursive operation if the top level cell node already has the right interfaceState. - if (node.interfaceState != interfaceState) { -#if RangeControllerLoggingEnabled - [modifiedIndexPaths addObject:indexPath]; -#endif - [node recursivelySetInterfaceState:interfaceState]; - } - } - } - } - - if (_didRegisterForNotifications) { - _pendingDisplayNodesTimestamp = CFAbsoluteTimeGetCurrent(); - } - - _rangeIsValid = YES; - _queuedRangeUpdate = NO; - -#if RangeControllerLoggingEnabled - NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths]; - BOOL setsAreEqual = [visibleIndexPaths isEqualToSet:visibleNodePathsSet]; - NSLog(@"visible sets are equal: %d", setsAreEqual); - if (!setsAreEqual) { - NSLog(@"standard: %@", visibleIndexPaths); - NSLog(@"custom: %@", visibleNodePathsSet); - } - - [modifiedIndexPaths sortUsingSelector:@selector(compare:)]; - - for (NSIndexPath *indexPath in modifiedIndexPaths) { - ASDisplayNode *node = [_dataSource rangeController:self nodeAtIndexPath:indexPath]; - ASInterfaceState interfaceState = node.interfaceState; - BOOL inVisible = ASInterfaceStateIncludesVisible(interfaceState); - BOOL inDisplay = ASInterfaceStateIncludesDisplay(interfaceState); - BOOL inFetchData = ASInterfaceStateIncludesFetchData(interfaceState); - NSLog(@"indexPath %@, Visible: %d, Display: %d, FetchData: %d", indexPath, inVisible, inDisplay, inFetchData); - } -#endif -} - -#pragma mark - Notification observers - -- (void)registerForNotificationsForInterfaceStateIfNeeded:(ASInterfaceState)interfaceState -{ - if (!_didRegisterForNotifications) { - ASLayoutRangeMode nextRangeMode = [ASRangeControllerBeta rangeModeForInterfaceState:interfaceState - currentRangeMode:_currentRangeMode]; - if (_currentRangeMode != nextRangeMode) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(scheduledNodesDidDisplay:) - name:ASRenderingEngineDidDisplayScheduledNodesNotification - object:nil]; - _didRegisterForNotifications = YES; - } - } -} - -- (void)scheduledNodesDidDisplay:(NSNotification *)notification -{ - CFAbsoluteTime notificationTimestamp = ((NSNumber *)[notification.userInfo objectForKey:ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp]).doubleValue; - if (_pendingDisplayNodesTimestamp < notificationTimestamp) { - // The rendering engine has processed all the nodes this range controller scheduled. Let's schedule a range update - [[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil]; - _didRegisterForNotifications = NO; - - [self scheduleRangeUpdate]; - } -} - -#pragma mark - Cell node view handling - -- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node -{ - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(node, @"Cannot move a nil node to a view"); - ASDisplayNodeAssert(contentView, @"Cannot move a node to a non-existent view"); - - if (node.view.superview == contentView) { - // this content view is already correctly configured - return; - } - - // clean the content view - for (UIView *view in contentView.subviews) { - [view removeFromSuperview]; - } - - [contentView addSubview:node.view]; -} - -#pragma mark - ASDataControllerDelegete - -- (void)dataControllerBeginUpdates:(ASDataController *)dataController -{ - ASPerformBlockOnMainThread(^{ - [_delegate didBeginUpdatesInRangeController:self]; - }); -} - -- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion -{ - ASPerformBlockOnMainThread(^{ - [_delegate rangeController:self didEndUpdatesAnimated:animated completion:completion]; - }); -} - -- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASDisplayNodeAssert(nodes.count == indexPaths.count, @"Invalid index path"); - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - [_delegate rangeController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; - }); -} - -- (void)dataController:(ASDataController *)dataController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - [_delegate rangeController:self didDeleteNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; - }); -} - -- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASDisplayNodeAssert(sections.count == indexSet.count, @"Invalid sections"); - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - [_delegate rangeController:self didInsertSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; - }); -} - -- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions -{ - ASPerformBlockOnMainThread(^{ - _rangeIsValid = NO; - [_delegate rangeController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; - }); -} - -@end From 03536ddefd24164852f5a6084acc653e34256248 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Sun, 7 Feb 2016 14:45:43 -0800 Subject: [PATCH 3/7] Remove shouldUpdateForVisibleIndexPaths This method can be removed as ASRangeControllerBeta is the main ASRangeController now --- .../Details/ASAbstractLayoutController.mm | 7 ----- .../Details/ASFlowLayoutController.mm | 28 ------------------- AsyncDisplayKit/Details/ASLayoutController.h | 4 --- 3 files changed, 39 deletions(-) diff --git a/AsyncDisplayKit/Details/ASAbstractLayoutController.mm b/AsyncDisplayKit/Details/ASAbstractLayoutController.mm index 2edcd4a78f..38828861e7 100644 --- a/AsyncDisplayKit/Details/ASAbstractLayoutController.mm +++ b/AsyncDisplayKit/Details/ASAbstractLayoutController.mm @@ -82,13 +82,6 @@ extern BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRangeTuningPar #pragma mark - Abstract Index Path Range Support -// FIXME: This method can be removed once ASRangeControllerBeta becomes the main version. -- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths rangeType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssertNotSupported(); - return NO; -} - - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType { ASDisplayNodeAssertNotSupported(); diff --git a/AsyncDisplayKit/Details/ASFlowLayoutController.mm b/AsyncDisplayKit/Details/ASFlowLayoutController.mm index cbcde0f011..dce8065e8e 100644 --- a/AsyncDisplayKit/Details/ASFlowLayoutController.mm +++ b/AsyncDisplayKit/Details/ASFlowLayoutController.mm @@ -15,8 +15,6 @@ #include #include -static const CGFloat kASFlowLayoutControllerRefreshingThreshold = 0.3; - @interface ASFlowLayoutController() { ASIndexPathRange _visibleRange; @@ -39,32 +37,6 @@ static const CGFloat kASFlowLayoutControllerRefreshingThreshold = 0.3; #pragma mark - Visible Indices -// FIXME: This method can be removed once ASRangeControllerBeta becomes the main version. -- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths rangeType:(ASLayoutRangeType)rangeType -{ - if (!indexPaths.count || rangeType >= _rangesByType.size()) { - return NO; - } - - ASIndexPathRange existingRange = _rangesByType[rangeType]; - ASIndexPathRange newRange = [self indexPathRangeForIndexPaths:indexPaths]; - - ASIndexPath maximumStart = ASIndexPathMaximum(existingRange.start, newRange.start); - ASIndexPath minimumEnd = ASIndexPathMinimum(existingRange.end, newRange.end); - - if (ASIndexPathEqualToIndexPath(maximumStart, existingRange.start) || ASIndexPathEqualToIndexPath(minimumEnd, existingRange.end)) { - return YES; - } - - NSInteger newStartDelta = [self flowLayoutDistanceForRange:ASIndexPathRangeMake(_visibleRange.start, newRange.start)]; - NSInteger existingStartDelta = [self flowLayoutDistanceForRange:ASIndexPathRangeMake(_visibleRange.start, existingRange.start)] * kASFlowLayoutControllerRefreshingThreshold; - - NSInteger newEndDelta = [self flowLayoutDistanceForRange:ASIndexPathRangeMake(_visibleRange.end, newRange.end)]; - NSInteger existingEndDelta = [self flowLayoutDistanceForRange:ASIndexPathRangeMake(_visibleRange.end, existingRange.end)] * kASFlowLayoutControllerRefreshingThreshold; - - return (newStartDelta > existingStartDelta) || (newEndDelta > existingEndDelta); -} - - (void)setVisibleNodeIndexPaths:(NSArray *)indexPaths { _visibleRange = [self indexPathRangeForIndexPaths:indexPaths]; diff --git a/AsyncDisplayKit/Details/ASLayoutController.h b/AsyncDisplayKit/Details/ASLayoutController.h index 0ed8658876..8cf34effd0 100644 --- a/AsyncDisplayKit/Details/ASLayoutController.h +++ b/AsyncDisplayKit/Details/ASLayoutController.h @@ -31,10 +31,6 @@ FOUNDATION_EXPORT BOOL ASRangeTuningParametersEqualToRangeTuningParameters(ASRan - (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType; -// 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? -- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths rangeType:(ASLayoutRangeType)rangeType; - - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType; @optional From e49a5d992c6cf30d127c677b7c14f75e67032c2c Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Sun, 7 Feb 2016 15:27:15 -0800 Subject: [PATCH 4/7] Remove unused ASCollectionViewLayoutController import --- AsyncDisplayKit/ASTableView.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 474d2d79d7..28d8ef3de9 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -11,7 +11,6 @@ #import "ASAssert.h" #import "ASBatchFetching.h" #import "ASChangeSetDataController.h" -#import "ASCollectionViewLayoutController.h" #import "ASDelegateProxy.h" #import "ASDisplayNode+Beta.h" #import "ASDisplayNode+FrameworkPrivate.h" From fa2a058585ca7e860eca8f0b4842d3711b9f8bd9 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Sun, 7 Feb 2016 15:27:45 -0800 Subject: [PATCH 5/7] Rename ASCollectionViewLayoutControllerBeta to ASCollectionViewLayoutController --- AsyncDisplayKit/ASCollectionView.mm | 2 +- AsyncDisplayKit/Details/ASCollectionViewLayoutController.h | 3 --- AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm | 4 ---- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 25a51674ef..23ae37aec8 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -167,7 +167,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; self.strongCollectionNode = collectionNode; } - _layoutController = [[ASCollectionViewLayoutControllerBeta alloc] initWithCollectionView:self]; + _layoutController = [[ASCollectionViewLayoutController alloc] initWithCollectionView:self]; _rangeController = [[ASRangeController alloc] init]; _rangeController.dataSource = self; diff --git a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h index 58745c8af4..632ba46bf8 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h +++ b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.h @@ -19,7 +19,4 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface ASCollectionViewLayoutControllerBeta : ASCollectionViewLayoutController -@end - NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm index 4515a9f3da..0d5f69bdf5 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm +++ b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm @@ -49,10 +49,6 @@ typedef struct ASRangeGeometry ASRangeGeometry; return self; } -@end - -@implementation ASCollectionViewLayoutControllerBeta - - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection rangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType { ASRangeTuningParameters tuningParameters = [self tuningParametersForRangeMode:rangeMode rangeType:rangeType]; From 28207c678d68467f95cc8d8427ef3c3d2da23544 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Mon, 8 Feb 2016 12:57:05 -0800 Subject: [PATCH 6/7] Remove ASRangeHandler protocol with all classes that implement it With the move to the new ASRangeController we don't need the ASRangeHandler protocol anymore --- AsyncDisplayKit.xcodeproj/project.pbxproj | 42 ----------- AsyncDisplayKit/AsyncDisplayKit.h | 3 - AsyncDisplayKit/Details/ASRangeController.mm | 3 - AsyncDisplayKit/Details/ASRangeHandler.h | 26 ------- .../Details/ASRangeHandlerPreload.h | 19 ----- .../Details/ASRangeHandlerPreload.mm | 27 ------- .../Details/ASRangeHandlerRender.h | 19 ----- .../Details/ASRangeHandlerRender.mm | 74 ------------------- .../Details/ASRangeHandlerVisible.h | 15 ---- .../Details/ASRangeHandlerVisible.mm | 25 ------- 10 files changed, 253 deletions(-) delete mode 100644 AsyncDisplayKit/Details/ASRangeHandler.h delete mode 100644 AsyncDisplayKit/Details/ASRangeHandlerPreload.h delete mode 100644 AsyncDisplayKit/Details/ASRangeHandlerPreload.mm delete mode 100644 AsyncDisplayKit/Details/ASRangeHandlerRender.h delete mode 100644 AsyncDisplayKit/Details/ASRangeHandlerRender.mm delete mode 100644 AsyncDisplayKit/Details/ASRangeHandlerVisible.h delete mode 100644 AsyncDisplayKit/Details/ASRangeHandlerVisible.mm diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 9695be1a49..859858ca93 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -186,10 +186,6 @@ 257754C21BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 257754C31BEE458E00737CA5 /* ASTextNodeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 257754C41BEE458E00737CA5 /* ASTextNodeWordKerner.m in Sources */ = {isa = PBXBuildFile; fileRef = 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */; }; - 258FF4271C0D152600A83844 /* ASRangeHandlerVisible.h in Headers */ = {isa = PBXBuildFile; fileRef = 258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */; }; - 258FF4281C0D152600A83844 /* ASRangeHandlerVisible.mm in Sources */ = {isa = PBXBuildFile; fileRef = 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */; }; - 25A977EF1C0D2A5500406B62 /* ASRangeHandlerVisible.mm in Sources */ = {isa = PBXBuildFile; fileRef = 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */; }; - 25BAA16F1C0D18D2002747C7 /* ASRangeHandlerVisible.h in Headers */ = {isa = PBXBuildFile; fileRef = 258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */; }; 25E327561C16819500A2170C /* ASPagerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E327541C16819500A2170C /* ASPagerNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25E327571C16819500A2170C /* ASPagerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E327541C16819500A2170C /* ASPagerNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25E327581C16819500A2170C /* ASPagerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E327551C16819500A2170C /* ASPagerNode.m */; }; @@ -199,11 +195,6 @@ 2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.m */; }; 291B63FB1AA53A7A000A71B3 /* ASScrollDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 296A0A311A951715005ACEAA /* ASScrollDirection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 292C599F1A956527007E5DD6 /* ASLayoutRangeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 292C59A01A956527007E5DD6 /* ASRangeHandlerPreload.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C599A1A956527007E5DD6 /* ASRangeHandlerPreload.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 292C59A11A956527007E5DD6 /* ASRangeHandlerPreload.mm in Sources */ = {isa = PBXBuildFile; fileRef = 292C599B1A956527007E5DD6 /* ASRangeHandlerPreload.mm */; }; - 292C59A21A956527007E5DD6 /* ASRangeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C599C1A956527007E5DD6 /* ASRangeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 292C59A31A956527007E5DD6 /* ASRangeHandlerRender.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C599D1A956527007E5DD6 /* ASRangeHandlerRender.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 292C59A41A956527007E5DD6 /* ASRangeHandlerRender.mm in Sources */ = {isa = PBXBuildFile; fileRef = 292C599E1A956527007E5DD6 /* ASRangeHandlerRender.mm */; }; 2967F9E21AB0A5190072E4AB /* ASBasicImageDownloaderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */; }; 296A0A351A951ABF005ACEAA /* ASBatchFetchingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.m */; }; 299DA1A91A828D2900162D41 /* ASBatchContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 299DA1A71A828D2900162D41 /* ASBatchContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -424,11 +415,6 @@ B35062251B010EFD0018CF92 /* ASMutableAttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */; }; B35062261B010EFD0018CF92 /* ASRangeController.h in Headers */ = {isa = PBXBuildFile; fileRef = 055F1A3619ABD413004DAFF1 /* ASRangeController.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */; }; - B35062281B010EFD0018CF92 /* ASRangeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C599C1A956527007E5DD6 /* ASRangeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B35062291B010EFD0018CF92 /* ASRangeHandlerPreload.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C599A1A956527007E5DD6 /* ASRangeHandlerPreload.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B350622A1B010EFD0018CF92 /* ASRangeHandlerPreload.mm in Sources */ = {isa = PBXBuildFile; fileRef = 292C599B1A956527007E5DD6 /* ASRangeHandlerPreload.mm */; }; - B350622B1B010EFD0018CF92 /* ASRangeHandlerRender.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C599D1A956527007E5DD6 /* ASRangeHandlerRender.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B350622C1B010EFD0018CF92 /* ASRangeHandlerRender.mm in Sources */ = {isa = PBXBuildFile; fileRef = 292C599E1A956527007E5DD6 /* ASRangeHandlerRender.mm */; }; B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 296A0A311A951715005ACEAA /* ASScrollDirection.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35062391B010EFD0018CF92 /* ASThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D0A12195D050800B7D73C /* ASThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; B350623A1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 058D09F5195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -684,17 +670,10 @@ 257754BB1BEE458E00737CA5 /* ASTextKitCoreTextAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextKitCoreTextAdditions.h; path = TextKit/ASTextKitCoreTextAdditions.h; sourceTree = ""; }; 257754BC1BEE458E00737CA5 /* ASTextNodeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTextNodeTypes.h; path = TextKit/ASTextNodeTypes.h; sourceTree = ""; }; 257754BD1BEE458E00737CA5 /* ASTextNodeWordKerner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASTextNodeWordKerner.m; path = TextKit/ASTextNodeWordKerner.m; sourceTree = ""; }; - 258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeHandlerVisible.h; sourceTree = ""; }; - 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRangeHandlerVisible.mm; sourceTree = ""; }; 25E327541C16819500A2170C /* ASPagerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ASPagerNode.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 25E327551C16819500A2170C /* ASPagerNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ASPagerNode.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 2911485B1A77147A005D0878 /* ASControlNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASControlNodeTests.m; sourceTree = ""; }; 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutRangeType.h; sourceTree = ""; }; - 292C599A1A956527007E5DD6 /* ASRangeHandlerPreload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeHandlerPreload.h; sourceTree = ""; }; - 292C599B1A956527007E5DD6 /* ASRangeHandlerPreload.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRangeHandlerPreload.mm; sourceTree = ""; }; - 292C599C1A956527007E5DD6 /* ASRangeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeHandler.h; sourceTree = ""; }; - 292C599D1A956527007E5DD6 /* ASRangeHandlerRender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeHandlerRender.h; sourceTree = ""; }; - 292C599E1A956527007E5DD6 /* ASRangeHandlerRender.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRangeHandlerRender.mm; sourceTree = ""; }; 2967F9E11AB0A4CF0072E4AB /* ASBasicImageDownloaderInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASBasicImageDownloaderInternal.h; sourceTree = ""; }; 296A0A311A951715005ACEAA /* ASScrollDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASScrollDirection.h; path = AsyncDisplayKit/Details/ASScrollDirection.h; sourceTree = SOURCE_ROOT; }; 296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASBatchFetchingTests.m; sourceTree = ""; }; @@ -1091,13 +1070,6 @@ 058D09E9195D050800B7D73C /* ASMutableAttributedStringBuilder.m */, 055F1A3619ABD413004DAFF1 /* ASRangeController.h */, 055F1A3719ABD413004DAFF1 /* ASRangeController.mm */, - 292C599C1A956527007E5DD6 /* ASRangeHandler.h */, - 258FF4251C0D152600A83844 /* ASRangeHandlerVisible.h */, - 258FF4261C0D152600A83844 /* ASRangeHandlerVisible.mm */, - 292C599A1A956527007E5DD6 /* ASRangeHandlerPreload.h */, - 292C599B1A956527007E5DD6 /* ASRangeHandlerPreload.mm */, - 292C599D1A956527007E5DD6 /* ASRangeHandlerRender.h */, - 292C599E1A956527007E5DD6 /* ASRangeHandlerRender.mm */, 296A0A311A951715005ACEAA /* ASScrollDirection.h */, 205F0E111B371BD7007741D0 /* ASScrollDirection.m */, 058D0A12195D050800B7D73C /* ASThread.h */, @@ -1360,7 +1332,6 @@ DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */, DBC452DB1C5BF64600B16017 /* NSArray+Diffing.h in Headers */, 058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */, - 258FF4271C0D152600A83844 /* ASRangeHandlerVisible.h in Headers */, 058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */, 058D0A84195D060300B7D73C /* ASDisplayNodeExtraIvars.h in Headers */, AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */, @@ -1403,9 +1374,6 @@ 055B9FA81A1C154B00035D6D /* ASNetworkImageNode.h in Headers */, ACF6ED2B1B17843500DA7C62 /* ASOverlayLayoutSpec.h in Headers */, 055F1A3819ABD413004DAFF1 /* ASRangeController.h in Headers */, - 292C59A21A956527007E5DD6 /* ASRangeHandler.h in Headers */, - 292C59A01A956527007E5DD6 /* ASRangeHandlerPreload.h in Headers */, - 292C59A31A956527007E5DD6 /* ASRangeHandlerRender.h in Headers */, ACF6ED2D1B17843500DA7C62 /* ASRatioLayoutSpec.h in Headers */, AC47D9451B3BB41900AAEE9D /* ASRelativeSize.h in Headers */, 291B63FB1AA53A7A000A71B3 /* ASScrollDirection.h in Headers */, @@ -1447,7 +1415,6 @@ buildActionMask = 2147483647; files = ( AC026B6A1BD57D6F00BBC17E /* ASChangeSetDataController.h in Headers */, - 25BAA16F1C0D18D2002747C7 /* ASRangeHandlerVisible.h in Headers */, B35062481B010EFD0018CF92 /* _AS-objc-internal.h in Headers */, B350623C1B010EFD0018CF92 /* _ASAsyncTransaction.h in Headers */, B350623E1B010EFD0018CF92 /* _ASAsyncTransactionContainer+Private.h in Headers */, @@ -1531,9 +1498,6 @@ B35062061B010EFD0018CF92 /* ASNetworkImageNode.h in Headers */, 34EFC76C1B701CED00AD841F /* ASOverlayLayoutSpec.h in Headers */, B35062261B010EFD0018CF92 /* ASRangeController.h in Headers */, - B35062281B010EFD0018CF92 /* ASRangeHandler.h in Headers */, - B35062291B010EFD0018CF92 /* ASRangeHandlerPreload.h in Headers */, - B350622B1B010EFD0018CF92 /* ASRangeHandlerRender.h in Headers */, 34EFC76E1B701CF400AD841F /* ASRatioLayoutSpec.h in Headers */, 34EFC7651B701CCC00AD841F /* ASRelativeSize.h in Headers */, 254C6B741BF94DF4003EC431 /* ASTextNodeWordKerner.h in Headers */, @@ -1828,8 +1792,6 @@ 257754AB1BEE44CD00737CA5 /* ASTextKitEntityAttribute.m in Sources */, 055F1A3919ABD413004DAFF1 /* ASRangeController.mm in Sources */, 044285091BAA63FE00D16268 /* ASBatchFetching.m in Sources */, - 292C59A11A956527007E5DD6 /* ASRangeHandlerPreload.mm in Sources */, - 292C59A41A956527007E5DD6 /* ASRangeHandlerRender.mm in Sources */, 257754AE1BEE44CD00737CA5 /* ASTextKitRenderer+Positioning.mm in Sources */, ACF6ED2E1B17843500DA7C62 /* ASRatioLayoutSpec.mm in Sources */, AC47D9461B3BB41900AAEE9D /* ASRelativeSize.mm in Sources */, @@ -1837,7 +1799,6 @@ D785F6631A74327E00291744 /* ASScrollNode.m in Sources */, 058D0A2C195D050800B7D73C /* ASSentinel.m in Sources */, 9C8221971BA237B80037F19A /* ASStackBaselinePositionedLayout.mm in Sources */, - 258FF4281C0D152600A83844 /* ASRangeHandlerVisible.mm in Sources */, 251B8EF81BBB3D690087C538 /* ASCollectionDataController.mm in Sources */, ACF6ED301B17843500DA7C62 /* ASStackLayoutSpec.mm in Sources */, 257754BE1BEE458E00737CA5 /* ASTextKitHelpers.mm in Sources */, @@ -1966,14 +1927,11 @@ 044285101BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm in Sources */, B35062271B010EFD0018CF92 /* ASRangeController.mm in Sources */, 0442850A1BAA63FE00D16268 /* ASBatchFetching.m in Sources */, - B350622A1B010EFD0018CF92 /* ASRangeHandlerPreload.mm in Sources */, - B350622C1B010EFD0018CF92 /* ASRangeHandlerRender.mm in Sources */, 34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */, 254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */, 34EFC7661B701CD200AD841F /* ASRelativeSize.mm in Sources */, 254C6B851BF94F8A003EC431 /* ASTextKitAttributes.mm in Sources */, 509E68601B3AED8E009B9150 /* ASScrollDirection.m in Sources */, - 25A977EF1C0D2A5500406B62 /* ASRangeHandlerVisible.mm in Sources */, B35062091B010EFD0018CF92 /* ASScrollNode.m in Sources */, B35062561B010EFD0018CF92 /* ASSentinel.m in Sources */, 9C8221981BA237B80037F19A /* ASStackBaselinePositionedLayout.mm in Sources */, diff --git a/AsyncDisplayKit/AsyncDisplayKit.h b/AsyncDisplayKit/AsyncDisplayKit.h index b854d7564a..2ad55f9080 100644 --- a/AsyncDisplayKit/AsyncDisplayKit.h +++ b/AsyncDisplayKit/AsyncDisplayKit.h @@ -63,9 +63,6 @@ #import #import #import -#import -#import -#import #import #import #import diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index 3b6966d9c6..1b8d7d8f89 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -12,9 +12,6 @@ #import "ASDisplayNodeExtras.h" #import "ASDisplayNodeInternal.h" #import "ASMultiDimensionalArrayUtils.h" -#import "ASRangeHandlerVisible.h" -#import "ASRangeHandlerRender.h" -#import "ASRangeHandlerPreload.h" #import "ASInternalHelpers.h" #import "ASDisplayNode+FrameworkPrivate.h" diff --git a/AsyncDisplayKit/Details/ASRangeHandler.h b/AsyncDisplayKit/Details/ASRangeHandler.h deleted file mode 100644 index 136736f442..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandler.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class ASDisplayNode; - -@protocol ASRangeHandler - -@required - -- (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType; -- (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType; - -@end - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASRangeHandlerPreload.h b/AsyncDisplayKit/Details/ASRangeHandlerPreload.h deleted file mode 100644 index eb7c34f991..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandlerPreload.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface ASRangeHandlerPreload : NSObject - -@end - -NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm b/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm deleted file mode 100644 index 3eccec5dd8..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandlerPreload.mm +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "ASRangeHandlerPreload.h" -#import "ASDisplayNode.h" -#import "ASDisplayNode+FrameworkPrivate.h" - -@implementation ASRangeHandlerPreload - -- (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeFetchData, @"Preload delegate should not handle other ranges"); - [node enterInterfaceState:ASInterfaceStateFetchData]; -} - -- (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeFetchData, @"Preload delegate should not handle other ranges"); - [node exitInterfaceState:ASInterfaceStateFetchData]; -} - -@end diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.h b/AsyncDisplayKit/Details/ASRangeHandlerRender.h deleted file mode 100644 index 8b00982b99..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface ASRangeHandlerRender : NSObject - -@end - -NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm deleted file mode 100644 index df7b4acb93..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "ASRangeHandlerRender.h" - -#import "ASDisplayNode.h" -#import "ASDisplayNode+Subclasses.h" -#import "ASDisplayNode+FrameworkPrivate.h" -#import "ASDisplayNode+Beta.h" - -@interface ASRangeHandlerRender () -@property (nonatomic,readonly) UIWindow *workingWindow; -@end - -@implementation ASRangeHandlerRender - -- (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeDisplay, @"Render delegate should not handle other ranges"); - - // If a node had previously been onscreen but now is only in the working range, - // ensure its view is not orphaned in a UITableViewCell in the reuse pool. - if (![node isLayerBacked] && node.view.superview) { - [node.view removeFromSuperview]; - } - - // The node un-suspends display. - [node enterInterfaceState:ASInterfaceStateDisplay]; - - -// ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled"); - [node recursivelyEnsureDisplaySynchronously:NO]; -} - -- (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType -{ - ASDisplayNodeAssertMainThread(); - ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeDisplay, @"Render delegate should not handle other ranges"); - - // This code is tricky. There are several possible states a node can be in when it reaches this point. - // 1. Layer-backed vs view-backed nodes. AS of this writing, only ASCellNodes arrive here, which are always view-backed — - // but we maintain correctness for all ASDisplayNodes, including layer-backed ones. - // (Note: it would not make sense to pass in a subnode of a rasterized node here, so that is unsupported). - // 2. The node's layer may have been added to the workingWindow previously, or it may have never been added, such as if rangeTuningParameter's leading value is 0. - // 3. The node's layer may not be present in the workingWindow, even if it was previously added. - // This is a common case, as once the node is added to an active cell contentsView (e.g. visible), it is automatically removed from the workingWindow. - // The system does this when addSublayer is called, even if removeFromSuperlayer is never explicitly called. - // 4. Lastly and most unusually, it is possible for a node to be offscreen, completely outside the heirarchy, and yet considered within the working range. - // This happens if the UITableViewCell is reused after scrolling offscreen. Because the node has already been given the opportunity to display, we do not - // proactively re-host it within the workingWindow (improving efficiency). Some time later, it may fall outside the working range, in which case calling - // -recursivelyClearContents is critical. If the user scrolls back and it is re-hosted in a UITableViewCell, the content will still exist as it is not cleared - // by simply being removed from the cell. The code that usually triggers this condition is the -removeFromSuperview in -[ASRangeController configureContentView:forCellNode:]. - // Condition #4 is suboptimal in some cases, as it is conceivable that memory warnings could trigger clearing content that is inside the working range. However, enforcing the - // preservation of this content could result in the app being killed, which is not likely preferable over briefly seeing placeholders in the event the user scrolls backwards. - // Nonetheless, future changes to the implementation will likely eliminate this behavior to simplify debugging and extensibility of working range functionality. - - // The node calls clearCurrentContents and suspends display - [node exitInterfaceState:ASInterfaceStateDisplay]; - -// ASDisplayNodeAssert(![ASDisplayNode shouldUseNewRenderingRange], @"It should no longer be possible to reach this point with the new display range enabled"); - if (![node isLayerBacked]) { - [node.view removeFromSuperview]; - } else { - [node.layer removeFromSuperlayer]; - } -} - -@end diff --git a/AsyncDisplayKit/Details/ASRangeHandlerVisible.h b/AsyncDisplayKit/Details/ASRangeHandlerVisible.h deleted file mode 100644 index eab9f77f29..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandlerVisible.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -@interface ASRangeHandlerVisible : NSObject - -@end diff --git a/AsyncDisplayKit/Details/ASRangeHandlerVisible.mm b/AsyncDisplayKit/Details/ASRangeHandlerVisible.mm deleted file mode 100644 index f17bc1cad3..0000000000 --- a/AsyncDisplayKit/Details/ASRangeHandlerVisible.mm +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "ASRangeHandlerVisible.h" -#import "ASDisplayNode.h" -#import "ASDisplayNode+FrameworkPrivate.h" - -@implementation ASRangeHandlerVisible - -- (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType -{ - [node enterInterfaceState:ASInterfaceStateVisible]; -} - -- (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType -{ - [node exitInterfaceState:ASInterfaceStateVisible]; -} - -@end From bdb486cf9e257d65cccf2ac8afed60de488d9549 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 9 Feb 2016 06:56:34 -0800 Subject: [PATCH 7/7] Fix sample build errors --- examples/ASTableViewStressTest/Sample/AppDelegate.m | 2 -- .../VerticalWithinHorizontalScrolling/Sample/AppDelegate.m | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/ASTableViewStressTest/Sample/AppDelegate.m b/examples/ASTableViewStressTest/Sample/AppDelegate.m index 4bc15faea9..50382b9daa 100644 --- a/examples/ASTableViewStressTest/Sample/AppDelegate.m +++ b/examples/ASTableViewStressTest/Sample/AppDelegate.m @@ -20,8 +20,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [ASDisplayNode setShouldUseNewRenderingRange:YES]; - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[UINavigationController alloc] init]; diff --git a/examples/VerticalWithinHorizontalScrolling/Sample/AppDelegate.m b/examples/VerticalWithinHorizontalScrolling/Sample/AppDelegate.m index 3ba9d1faf9..6c998ed4bb 100644 --- a/examples/VerticalWithinHorizontalScrolling/Sample/AppDelegate.m +++ b/examples/VerticalWithinHorizontalScrolling/Sample/AppDelegate.m @@ -19,9 +19,7 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - [ASDisplayNode setShouldUseNewRenderingRange:YES]; - +{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];