From e9a32bfd3cd187069bfba74bccd4b581fd613c54 Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Thu, 19 Nov 2015 11:48:06 -0800 Subject: [PATCH 1/4] Remove deprecated layout controller methods --- AsyncDisplayKit/ASCollectionView.h | 8 +----- AsyncDisplayKit/ASTableView.h | 8 +----- .../Details/ASAbstractLayoutController.h | 2 -- .../Details/ASAbstractLayoutController.mm | 28 +------------------ AsyncDisplayKit/Details/ASLayoutController.h | 6 ---- 5 files changed, 3 insertions(+), 49 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index eca5ba4883..204d155f8a 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -415,10 +415,4 @@ */ - (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section; -@end - -@interface ASCollectionView (Deprecated) - -@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED; - -@end +@end \ No newline at end of file diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index d7ea79dc2d..8a5f33531e 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -344,10 +344,4 @@ */ - (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView; -@end - -@interface ASTableView (Deprecated) - -@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED; - -@end +@end \ No newline at end of file diff --git a/AsyncDisplayKit/Details/ASAbstractLayoutController.h b/AsyncDisplayKit/Details/ASAbstractLayoutController.h index 45b92ece00..7fcf36da70 100644 --- a/AsyncDisplayKit/Details/ASAbstractLayoutController.h +++ b/AsyncDisplayKit/Details/ASAbstractLayoutController.h @@ -15,6 +15,4 @@ - (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType; -@property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED; - @end diff --git a/AsyncDisplayKit/Details/ASAbstractLayoutController.mm b/AsyncDisplayKit/Details/ASAbstractLayoutController.mm index 28d6ceb04f..30723e43b7 100644 --- a/AsyncDisplayKit/Details/ASAbstractLayoutController.mm +++ b/AsyncDisplayKit/Details/ASAbstractLayoutController.mm @@ -52,33 +52,7 @@ _tuningParameters[rangeType] = tuningParameters; } -// Support for the deprecated tuningParameters property -- (ASRangeTuningParameters)tuningParameters -{ - return [self tuningParametersForRangeType:ASLayoutRangeTypeRender]; -} - -// Support for the deprecated tuningParameters property -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters -{ - [self setTuningParameters:tuningParameters forRangeType:ASLayoutRangeTypeRender]; -} - -#pragma mark - Index Path Range Support - -// Support for deprecated method -- (BOOL)shouldUpdateForVisibleIndexPath:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize -{ - return [self shouldUpdateForVisibleIndexPaths:indexPaths viewportSize:viewportSize rangeType:ASLayoutRangeTypeRender]; -} - -// Support for the deprecated method -- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize -{ - return [self indexPathsForScrolling:scrollDirection viewportSize:viewportSize rangeType:ASLayoutRangeTypeRender]; -} - -#pragma mark - Abstract +#pragma mark - Abstract Index Path Range Support - (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType { diff --git a/AsyncDisplayKit/Details/ASLayoutController.h b/AsyncDisplayKit/Details/ASLayoutController.h index b45efd8793..5c206a75ee 100644 --- a/AsyncDisplayKit/Details/ASLayoutController.h +++ b/AsyncDisplayKit/Details/ASLayoutController.h @@ -31,12 +31,6 @@ typedef struct { - (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType; -@property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED; - -- (BOOL)shouldUpdateForVisibleIndexPath:(NSArray *)indexPath viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED; - -- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED; - @optional - (void)insertNodesAtIndexPaths:(NSArray *)indexPaths withSizes:(NSArray *)nodeSizes; From 09a2e086b03f324a7700b2d354c1d3febb0b0a39 Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Thu, 19 Nov 2015 14:03:53 -0800 Subject: [PATCH 2/4] Clean up syntax and method ordering in ASRangeController --- AsyncDisplayKit/ASTableView.mm | 4 +- AsyncDisplayKit/Details/ASRangeController.mm | 66 +++++++++----------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index e8be092d97..990bc3e947 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -690,7 +690,7 @@ static BOOL _isInterceptedSelector(SEL sel) NSArray *visibleIndexPaths = self.indexPathsForVisibleRows; - if ( _pendingVisibleIndexPath ) { + if (_pendingVisibleIndexPath) { NSMutableSet *indexPaths = [NSMutableSet setWithArray:self.indexPathsForVisibleRows]; BOOL (^isAfter)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { @@ -720,7 +720,7 @@ static BOOL _isInterceptedSelector(SEL sel) return isAfter(anchor, indexPath); }; - if ( [indexPaths containsObject:_pendingVisibleIndexPath]) { + if ([indexPaths containsObject:_pendingVisibleIndexPath]) { _pendingVisibleIndexPath = nil; // once it has shown up in visibleIndexPaths, we can stop tracking it } else if (!isBefore(_pendingVisibleIndexPath, visibleIndexPaths.firstObject) && !isAfter(_pendingVisibleIndexPath, visibleIndexPaths.lastObject)) { diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index b511c4d43f..993401544a 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -31,22 +31,35 @@ @implementation ASRangeController - (instancetype)init { - if (self = [super init]) { - + self = [super init]; + if (self != nil) { _rangeIsValid = YES; - _rangeTypeIndexPaths = [[NSMutableDictionary alloc] init]; - + _rangeTypeIndexPaths = [NSMutableDictionary dictionary]; _rangeTypeHandlers = @{ - @(ASLayoutRangeTypeRender): [[ASRangeHandlerRender alloc] init], - @(ASLayoutRangeTypePreload): [[ASRangeHandlerPreload alloc] init], - }; + @(ASLayoutRangeTypeRender): [[ASRangeHandlerRender alloc] init], + @(ASLayoutRangeTypePreload): [[ASRangeHandlerPreload alloc] init], + }; } return self; } +#pragma mark - Cell node view handling -#pragma mark - View manipulation +- (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 { @@ -62,8 +75,7 @@ [view addSubview:node.view]; } - -#pragma mark - API +#pragma mark - Core visible node range managment API - (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection { @@ -76,13 +88,13 @@ // coalesce these events -- handling them multiple times per runloop is noisy and expensive _queuedRangeUpdate = YES; - [self performSelector:@selector(updateVisibleNodeIndexPaths) + [self performSelector:@selector(_updateVisibleNodeIndexPaths) withObject:nil afterDelay:0 inModes:@[ NSRunLoopCommonModes ]]; } -- (void)updateVisibleNodeIndexPaths +- (void)_updateVisibleNodeIndexPaths { if (!_queuedRangeUpdate) { return; @@ -90,7 +102,7 @@ NSArray *visibleNodePaths = [_delegate rangeControllerVisibleNodeIndexPaths:self]; - if ( visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)... + 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 } @@ -108,13 +120,13 @@ id rangeKey = @(rangeType); // this delegate decide what happens when a node is added or removed from a range - id rangeDelegate = _rangeTypeHandlers[rangeKey]; + id rangeHandler = _rangeTypeHandlers[rangeKey]; if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths viewportSize:viewportSize rangeType:rangeType]) { NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection viewportSize:viewportSize rangeType:rangeType]; // Notify to remove indexpaths that are leftover that are not visible or included in the _layoutController calculated paths - NSMutableSet *removedIndexPaths = _rangeIsValid ? [[_rangeTypeIndexPaths objectForKey:rangeKey] mutableCopy] : [NSMutableSet set]; + NSMutableSet *removedIndexPaths = _rangeIsValid ? [_rangeTypeIndexPaths[rangeKey] mutableCopy] : [NSMutableSet set]; [removedIndexPaths minusSet:indexPaths]; [removedIndexPaths minusSet:visibleNodePathsSet]; @@ -123,11 +135,11 @@ [removedNodes enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger idx, BOOL *stop) { // 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. - [rangeDelegate node:node exitedRangeOfType:rangeType]; + [rangeHandler node:node exitedRangeOfType:rangeType]; }]; } - // Notify to add indexpaths that are not currently in _rangeTypeIndexPaths + // Notify to add index paths that are not currently in _rangeTypeIndexPaths NSMutableSet *addedIndexPaths = [indexPaths mutableCopy]; [addedIndexPaths minusSet:[_rangeTypeIndexPaths objectForKey:rangeKey]]; @@ -140,12 +152,12 @@ if (addedIndexPaths.count) { NSArray *addedNodes = [_delegate rangeController:self nodesAtIndexPaths:[addedIndexPaths allObjects]]; [addedNodes enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger idx, BOOL *stop) { - [rangeDelegate node:node enteredRangeOfType:rangeType]; + [rangeHandler node:node enteredRangeOfType:rangeType]; }]; } // set the range indexpaths so that we can remove/add on the next update pass - [_rangeTypeIndexPaths setObject:indexPaths forKey:rangeKey]; + _rangeTypeIndexPaths[rangeKey] = indexPaths; } } @@ -158,22 +170,6 @@ return rangeType == ASLayoutRangeTypeRender; } -- (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]; -} - - #pragma mark - ASDataControllerDelegete - (void)dataControllerBeginUpdates:(ASDataController *)dataController { From e05c4b7419657188fd449991425b06d2cbc97426 Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Thu, 19 Nov 2015 16:01:38 -0800 Subject: [PATCH 3/4] Separate range controller delegate methods into separate data source --- AsyncDisplayKit/ASCollectionView.mm | 47 ++++--- AsyncDisplayKit/ASTableView.mm | 133 ++++++++++--------- AsyncDisplayKit/Details/ASLayoutController.h | 1 - AsyncDisplayKit/Details/ASRangeController.h | 67 ++++++---- AsyncDisplayKit/Details/ASRangeController.mm | 26 ++-- 5 files changed, 149 insertions(+), 125 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index f7516a264a..81941e2cd5 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -130,7 +130,7 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark - #pragma mark ASCollectionView. -@interface ASCollectionView () { +@interface ASCollectionView () { _ASCollectionViewProxy *_proxyDataSource; _ASCollectionViewProxy *_proxyDelegate; @@ -199,6 +199,7 @@ static BOOL _isInterceptedSelector(SEL sel) _layoutController = [[ASCollectionViewLayoutController alloc] initWithCollectionView:self]; _rangeController = [[ASRangeController alloc] init]; + _rangeController.dataSource = self; _rangeController.delegate = self; _rangeController.layoutController = _layoutController; @@ -765,14 +766,35 @@ static BOOL _isInterceptedSelector(SEL sel) return [_layoutInspector collectionView:self numberOfSectionsForSupplementaryNodeOfKind:kind]; } -#pragma mark - ASRangeControllerDelegate. +#pragma mark - ASRangeControllerDataSource -- (void)rangeControllerBeginUpdates:(ASRangeController *)rangeController { +- (NSArray *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController +{ + ASDisplayNodeAssertMainThread(); + return [self indexPathsForVisibleItems]; +} + +- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController +{ + ASDisplayNodeAssertMainThread(); + return self.bounds.size; +} + +- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths +{ + return [_dataController nodesAtIndexPaths:indexPaths]; +} + +#pragma mark - ASRangeControllerDelegate + +- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController +{ ASDisplayNodeAssertMainThread(); _performingBatchUpdates = YES; } -- (void)rangeController:(ASRangeController *)rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { +- (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion +{ ASDisplayNodeAssertMainThread(); if (!self.asyncDataSource || _superIsPendingDataLoad) { @@ -794,23 +816,6 @@ static BOOL _isInterceptedSelector(SEL sel) _performingBatchUpdates = NO; } -- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController -{ - ASDisplayNodeAssertMainThread(); - return [self indexPathsForVisibleItems]; -} - -- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController -{ - ASDisplayNodeAssertMainThread(); - return self.bounds.size; -} - -- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths -{ - return [_dataController nodesAtIndexPaths:indexPaths]; -} - - (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 990bc3e947..20aa0ada65 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -151,7 +151,7 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark - #pragma mark ASTableView -@interface ASTableView () { +@interface ASTableView () { _ASTableViewProxy *_proxyDataSource; _ASTableViewProxy *_proxyDelegate; @@ -193,6 +193,7 @@ static BOOL _isInterceptedSelector(SEL sel) _rangeController = [[ASRangeController alloc] init]; _rangeController.layoutController = _layoutController; + _rangeController.dataSource = self; _rangeController.delegate = self; _dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:asyncDataFetching]; @@ -639,11 +640,72 @@ static BOOL _isInterceptedSelector(SEL sel) } } +#pragma mark - ASRangeControllerDataSource -#pragma mark - -#pragma mark ASRangeControllerDelegate +- (NSArray *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController +{ + ASDisplayNodeAssertMainThread(); + + NSArray *visibleIndexPaths = self.indexPathsForVisibleRows; + + if (_pendingVisibleIndexPath) { + NSMutableSet *indexPaths = [NSMutableSet setWithArray:self.indexPathsForVisibleRows]; + + BOOL (^isAfter)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { + if (!anchor || !indexPath) { + return NO; + } + if (indexPath.section == anchor.section) { + return (indexPath.row == anchor.row+1); // assumes that indexes are valid + + } else if (indexPath.section > anchor.section && indexPath.row == 0) { + if (anchor.row != [_dataController numberOfRowsInSection:anchor.section] -1) { + return NO; // anchor is not at the end of the section + } + + NSInteger nextSection = anchor.section+1; + while([_dataController numberOfRowsInSection:nextSection] == 0) { + ++nextSection; + } + + return indexPath.section == nextSection; + } + + return NO; + }; + + BOOL (^isBefore)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { + return isAfter(anchor, indexPath); + }; + + if ([indexPaths containsObject:_pendingVisibleIndexPath]) { + _pendingVisibleIndexPath = nil; // once it has shown up in visibleIndexPaths, we can stop tracking it + } else if (!isBefore(_pendingVisibleIndexPath, visibleIndexPaths.firstObject) && + !isAfter(_pendingVisibleIndexPath, visibleIndexPaths.lastObject)) { + _pendingVisibleIndexPath = nil; // not contiguous, ignore. + } else { + [indexPaths addObject:_pendingVisibleIndexPath]; + visibleIndexPaths = [indexPaths.allObjects sortedArrayUsingSelector:@selector(compare:)]; + } + } + + return visibleIndexPaths; +} -- (void)rangeControllerBeginUpdates:(ASRangeController *)rangeController +- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths +{ + return [_dataController nodesAtIndexPaths:indexPaths]; +} + +- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController +{ + ASDisplayNodeAssertMainThread(); + return self.bounds.size; +} + +#pragma mark - ASRangeControllerDelegate + +- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController { ASDisplayNodeAssertMainThread(); LOG(@"--- UITableView beginUpdates"); @@ -659,7 +721,7 @@ static BOOL _isInterceptedSelector(SEL sel) } } -- (void)rangeController:(ASRangeController *)rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion +- (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { ASDisplayNodeAssertMainThread(); LOG(@"--- UITableView endUpdates"); @@ -684,67 +746,6 @@ static BOOL _isInterceptedSelector(SEL sel) } } -- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController -{ - ASDisplayNodeAssertMainThread(); - - NSArray *visibleIndexPaths = self.indexPathsForVisibleRows; - - if (_pendingVisibleIndexPath) { - NSMutableSet *indexPaths = [NSMutableSet setWithArray:self.indexPathsForVisibleRows]; - - BOOL (^isAfter)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { - if (!anchor || !indexPath) { - return NO; - } - if (indexPath.section == anchor.section) { - return (indexPath.row == anchor.row+1); // assumes that indexes are valid - - } else if (indexPath.section > anchor.section && indexPath.row == 0) { - if (anchor.row != [_dataController numberOfRowsInSection:anchor.section] -1) { - return NO; // anchor is not at the end of the section - } - - NSInteger nextSection = anchor.section+1; - while([_dataController numberOfRowsInSection:nextSection] == 0) { - ++nextSection; - } - - return indexPath.section == nextSection; - } - - return NO; - }; - - BOOL (^isBefore)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { - return isAfter(anchor, indexPath); - }; - - if ([indexPaths containsObject:_pendingVisibleIndexPath]) { - _pendingVisibleIndexPath = nil; // once it has shown up in visibleIndexPaths, we can stop tracking it - } else if (!isBefore(_pendingVisibleIndexPath, visibleIndexPaths.firstObject) && - !isAfter(_pendingVisibleIndexPath, visibleIndexPaths.lastObject)) { - _pendingVisibleIndexPath = nil; // not contiguous, ignore. - } else { - [indexPaths addObject:_pendingVisibleIndexPath]; - visibleIndexPaths = [indexPaths.allObjects sortedArrayUsingSelector:@selector(compare:)]; - } - } - - return visibleIndexPaths; -} - -- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths -{ - return [_dataController nodesAtIndexPaths:indexPaths]; -} - -- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController -{ - ASDisplayNodeAssertMainThread(); - return self.bounds.size; -} - - (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); diff --git a/AsyncDisplayKit/Details/ASLayoutController.h b/AsyncDisplayKit/Details/ASLayoutController.h index 5c206a75ee..759cb0cc74 100644 --- a/AsyncDisplayKit/Details/ASLayoutController.h +++ b/AsyncDisplayKit/Details/ASLayoutController.h @@ -12,7 +12,6 @@ #import #import - typedef struct { CGFloat leadingBufferScreenfuls; CGFloat trailingBufferScreenfuls; diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index cf4cc37354..4af67e037c 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -13,7 +13,7 @@ #import #import - +@protocol ASRangeControllerDataSource; @protocol ASRangeControllerDelegate; /** @@ -46,49 +46,43 @@ - (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node; /** - * Delegate and ultimate data source. Must not be nil. + * + */ +@property (nonatomic, strong) id layoutController; + +/** + * The underlying data source for the range controller + */ +@property (nonatomic, weak) id dataSource; + +/** + * Delegate for handling range controller events. Must not be nil. */ @property (nonatomic, weak) id delegate; -@property (nonatomic, strong) id layoutController; - @end - /** - * delegate. For example, . + * Data source for ASRangeController. + * + * Allows the range controller to perform external queries on the range. + * Ex. range nodes, visible index paths, and viewport size. */ -@protocol ASRangeControllerDelegate +@protocol ASRangeControllerDataSource /** * @param rangeController Sender. * * @returns an array of index paths corresponding to the nodes currently visible onscreen (i.e., the visible range). */ -- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController; +- (NSArray *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController; /** * @param rangeController Sender. * * @returns the receiver's viewport size (i.e., the screen space occupied by the visible range). */ -- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController; - -/** - * Begin updates. - * - * @param rangeController Sender. - */ -- (void)rangeControllerBeginUpdates:(ASRangeController *)rangeController; - -/** - * End updates. - * - * @param rangeController Sender. - * @param animated NO if all animations are disabled. YES otherwise. - * @param completion Completion block. - */ -- (void)rangeController:(ASRangeController * )rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion; +- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController; /** * Fetch nodes at specific index paths. @@ -99,6 +93,29 @@ */ - (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths; +@end + +/** + * Delegate for ASRangeController. + */ +@protocol ASRangeControllerDelegate + +/** + * Begin updates. + * + * @param rangeController Sender. + */ +- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController; + +/** + * End updates. + * + * @param rangeController Sender. + * @param animated NO if all animations are disabled. YES otherwise. + * @param completion Completion block. + */ +- (void)rangeController:(ASRangeController * )rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion; + /** * Called for nodes insertion. * diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index 993401544a..1907baff75 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -100,7 +100,7 @@ return; } - NSArray *visibleNodePaths = [_delegate rangeControllerVisibleNodeIndexPaths:self]; + NSArray *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self]; if (visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)... _queuedRangeUpdate = NO; @@ -108,7 +108,7 @@ } NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths]; - CGSize viewportSize = [_delegate rangeControllerViewportSize:self]; + CGSize viewportSize = [_dataSource viewportSizeForRangeController:self]; // the layout controller needs to know what the current visible indices are to calculate range offsets if ([_layoutController respondsToSelector:@selector(setVisibleNodeIndexPaths:)]) { @@ -123,7 +123,9 @@ id rangeHandler = _rangeTypeHandlers[rangeKey]; if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths viewportSize:viewportSize rangeType:rangeType]) { - NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection viewportSize:viewportSize rangeType:rangeType]; + NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection + viewportSize:viewportSize + 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]; @@ -131,17 +133,17 @@ [removedIndexPaths minusSet:visibleNodePathsSet]; if (removedIndexPaths.count) { - NSArray *removedNodes = [_delegate rangeController:self nodesAtIndexPaths:[removedIndexPaths allObjects]]; - [removedNodes enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger idx, BOOL *stop) { + 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 objectForKey:rangeKey]]; + [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 @@ -150,10 +152,10 @@ } if (addedIndexPaths.count) { - NSArray *addedNodes = [_delegate rangeController:self nodesAtIndexPaths:[addedIndexPaths allObjects]]; - [addedNodes enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger idx, BOOL *stop) { + 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 @@ -174,13 +176,13 @@ - (void)dataControllerBeginUpdates:(ASDataController *)dataController { ASPerformBlockOnMainThread(^{ - [_delegate rangeControllerBeginUpdates:self]; + [_delegate didBeginUpdatesInRangeController:self]; }); } - (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { ASPerformBlockOnMainThread(^{ - [_delegate rangeController:self endUpdatesAnimated:animated completion:completion]; + [_delegate rangeController:self didEndUpdatesAnimated:animated completion:completion]; }); } From c6d4ed0dc3f71b6774acac2d25552ecc60ba9de4 Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Thu, 19 Nov 2015 18:26:50 -0800 Subject: [PATCH 4/4] Update documentation on the ASRangeController layoutController property --- AsyncDisplayKit/Details/ASRangeController.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index 4af67e037c..c8a74e1890 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -46,7 +46,10 @@ - (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node; /** - * + * An object that describes the layout behavior of the ranged component (table view, collection view, etc.) + * + * Used primarily for providing the current range of index paths and identifying when the + * range controller should invalidate its range. */ @property (nonatomic, strong) id layoutController;