From 75eab1db07382d33598b082b27e65833dd65cc08 Mon Sep 17 00:00:00 2001 From: Max Gu Date: Thu, 18 Feb 2016 18:00:37 -0800 Subject: [PATCH 1/9] Adding scroll visibility --- AsyncDisplayKit/ASCellNode.h | 5 +++++ AsyncDisplayKit/ASCellNode.m | 6 ++++++ AsyncDisplayKit/ASCollectionView.mm | 16 +++++++++++++++- AsyncDisplayKit/Details/ASDelegateProxy.m | 3 +++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index d1e575383e..669c6757f5 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -16,6 +16,7 @@ typedef NSUInteger ASCellNodeAnimation; @protocol ASCellNodeLayoutDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView cellFrameInScrollView:(CGRect)cellFrame; /** * Notifies the delegate that the specified cell node has done a relayout. * The notification is done on main thread. @@ -24,6 +25,8 @@ typedef NSUInteger ASCellNodeAnimation; * @param sizeChanged `YES` if the node's `calculatedSize` changed during the relayout, `NO` otherwise. */ - (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged; + + @end /** @@ -75,6 +78,7 @@ typedef NSUInteger ASCellNodeAnimation; */ @property (nonatomic, weak) id layoutDelegate; +@property (nonatomic, assign) BOOL shouldObserveVisibility; /* * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. @@ -107,6 +111,7 @@ typedef NSUInteger ASCellNodeAnimation; */ - (instancetype)initWithViewControllerBlock:(ASDisplayNodeViewControllerBlock)viewControllerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock; +- (void)updateScrollSituationWithScrollVIew:(UIScrollView *)scrollView; @end diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index df7040d92e..840c5edea3 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -134,6 +134,12 @@ [(_ASDisplayView *)self.view __forwardTouchesCancelled:touches withEvent:event]; } +- (void)updateScrollSituationWithScrollVIew:(UIScrollView *)scrollView +{ + // TODO(Max): Fix the cellFrame here + [self.layoutDelegate scrollViewDidScroll:scrollView cellFrameInScrollView:CGRectZero]; +} + @end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index b9f58ee5ff..ccfaa73115 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -67,7 +67,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; ASRangeController *_rangeController; ASCollectionViewLayoutController *_layoutController; ASCollectionViewFlowLayoutInspector *_flowLayoutInspector; - + NSMutableArray *_cellsForVisibilityUpdates; id _layoutFacilitator; BOOL _performingBatchUpdates; @@ -212,6 +212,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _registeredSupplementaryKinds = [NSMutableSet set]; + _cellsForVisibilityUpdates = [[NSMutableArray alloc] init]; self.backgroundColor = [UIColor whiteColor]; [self registerClass:[_ASCollectionViewCell class] forCellWithReuseIdentifier:kCellReuseIdentifier]; @@ -589,6 +590,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; if (cellNode.neverShowPlaceholders) { [cellNode recursivelyEnsureDisplaySynchronously:YES]; } + [_cellsForVisibilityUpdates addObject:cell]; } - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath @@ -600,6 +602,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; ASDisplayNodeAssertNotNil(node, @"Expected node associated with removed cell not to be nil."); [_asyncDelegate collectionView:self didEndDisplayingNode:node forItemAtIndexPath:indexPath]; } + [_cellsForVisibilityUpdates removeObject:cell]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if ([_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNodeForItemAtIndexPath:)]) { @@ -650,6 +653,17 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; } } +- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ + for (ASCellNode *node in _cellsForVisibilityUpdates) { + if (node.shouldObserveVisibility) { + [node updateScrollSituationWithScrollVIew:scrollView]; + } + } + if ([_asyncDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { + [_asyncDelegate scrollViewDidScroll:scrollView]; + } +} + - (BOOL)shouldBatchFetch { // if the delegate does not respond to this method, there is no point in starting to fetch diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index 2af0e7c7d5..baa65a65c7 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -56,6 +56,9 @@ // used for batch fetching API selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) || + // used for ASCellNode visibility + selector == @selector(scrollViewDidScroll:) || + // intercepted due to not being supported by ASCollectionView (prevent bugs caused by usage) selector == @selector(collectionView:canMoveItemAtIndexPath:) || selector == @selector(collectionView:moveItemAtIndexPath:toIndexPath:) || From 03446d97e199e61221cb9cfbab09b603d17a7db7 Mon Sep 17 00:00:00 2001 From: Max Gu Date: Thu, 18 Feb 2016 18:00:37 -0800 Subject: [PATCH 2/9] Adding scroll visibility --- AsyncDisplayKit/ASCellNode+Internal.h | 15 ++++++++ AsyncDisplayKit/ASCellNode.h | 21 +++++++++++ AsyncDisplayKit/ASCellNode.m | 24 +++++++++++-- AsyncDisplayKit/ASCollectionView.mm | 43 +++++++++++++++++++++-- AsyncDisplayKit/Details/ASDelegateProxy.m | 3 ++ 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 AsyncDisplayKit/ASCellNode+Internal.h diff --git a/AsyncDisplayKit/ASCellNode+Internal.h b/AsyncDisplayKit/ASCellNode+Internal.h new file mode 100644 index 0000000000..feb816467d --- /dev/null +++ b/AsyncDisplayKit/ASCellNode+Internal.h @@ -0,0 +1,15 @@ +// +// ASCellNode+Internal.h +// Pods +// +// Created by Max Gu on 2/19/16. +// +// + +#import "ASCellNode.h" + +@interface ASCellNode (Internal) + +@property (nonatomic, assign) BOOL shouldObserveVisibility; + +@end diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index d1e575383e..1267ff0920 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -16,6 +16,7 @@ typedef NSUInteger ASCellNodeAnimation; @protocol ASCellNodeLayoutDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView cellFrameInScrollView:(CGRect)cellFrame; /** * Notifies the delegate that the specified cell node has done a relayout. * The notification is done on main thread. @@ -24,6 +25,19 @@ typedef NSUInteger ASCellNodeAnimation; * @param sizeChanged `YES` if the node's `calculatedSize` changed during the relayout, `NO` otherwise. */ - (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged; + +<<<<<<< HEAD +======= +@optional +/** + * Notifies the delegate that the specified cell node has scrolled + * + * @param node: A node informing the delegate about the scroll + * @param cellFrame: The frame of the cell that has just scrolled + */ +- (void)visibleNodeDidScroll:(ASCellNode *)node inScrollView:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; +>>>>>>> 4b8216f... Adding scroll visibility + @end /** @@ -75,6 +89,7 @@ typedef NSUInteger ASCellNodeAnimation; */ @property (nonatomic, weak) id layoutDelegate; +@property (nonatomic, assign) BOOL shouldObserveVisibility; /* * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. @@ -107,6 +122,12 @@ typedef NSUInteger ASCellNodeAnimation; */ - (instancetype)initWithViewControllerBlock:(ASDisplayNodeViewControllerBlock)viewControllerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock; +<<<<<<< HEAD +- (void)updateScrollSituationWithScrollVIew:(UIScrollView *)scrollView; +======= +- (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; + +>>>>>>> 4b8216f... Adding scroll visibility @end diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index df7040d92e..8ed29380a0 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -6,9 +6,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASCellNode.h" +#import "ASCellNode+Internal.h" #import "ASInternalHelpers.h" +#import "ASCollectionView.h" #import #import #import @@ -36,7 +37,9 @@ // Use UITableViewCell defaults _selectionStyle = UITableViewCellSelectionStyleDefault; self.clipsToBounds = YES; - + if ([self.layoutDelegate respondsToSelector:@selector(visibleNodeDidScroll:inScrollView:withCellFrame:)]) { + self.shouldObserveVisibility= YES; + } return self; } @@ -57,6 +60,9 @@ [self addSubnode:_viewControllerNode]; } + if ([self.layoutDelegate respondsToSelector:@selector(visibleNodeDidScroll:inScrollView:withCellFrame:)]) { + self.shouldObserveVisibility = YES; + } return self; } @@ -134,6 +140,20 @@ [(_ASDisplayView *)self.view __forwardTouchesCancelled:touches withEvent:event]; } +<<<<<<< HEAD +- (void)updateScrollSituationWithScrollVIew:(UIScrollView *)scrollView +{ + // TODO(Max): Fix the cellFrame here + [self.layoutDelegate scrollViewDidScroll:scrollView cellFrameInScrollView:CGRectZero]; +======= +- (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame +{ + if (layoutDelegateImplementsVisibleNodeDidScroll) { + [self.layoutDelegate visibleNodeDidScroll:self inScrollView:scrollView withCellFrame:cellFrame]; + } +>>>>>>> 4b8216f... Adding scroll visibility +} + @end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index b9f58ee5ff..cd31312cb9 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -9,6 +9,7 @@ #import "ASAssert.h" #import "ASBatchFetching.h" #import "ASDelegateProxy.h" +#import "ASCellNode+Internal.h" #import "ASCollectionNode.h" #import "ASCollectionDataController.h" #import "ASCollectionViewLayoutController.h" @@ -67,7 +68,11 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; ASRangeController *_rangeController; ASCollectionViewLayoutController *_layoutController; ASCollectionViewFlowLayoutInspector *_flowLayoutInspector; - +<<<<<<< HEAD + NSMutableArray *_cellsForVisibilityUpdates; +======= + NSMutableSet *_cellsForVisibilityUpdates; +>>>>>>> 4b8216f... Adding scroll visibility id _layoutFacilitator; BOOL _performingBatchUpdates; @@ -75,6 +80,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; BOOL _asyncDataFetchingEnabled; BOOL _asyncDelegateImplementsInsetSection; + BOOL _asyncDelegateImplementsScrollviewDidScroll; BOOL _collectionViewLayoutImplementsInsetSection; BOOL _asyncDataSourceImplementsConstrainedSizeForNode; BOOL _asyncDataSourceImplementsNodeBlockForItemAtIndexPath; @@ -212,6 +218,11 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _registeredSupplementaryKinds = [NSMutableSet set]; +<<<<<<< HEAD + _cellsForVisibilityUpdates = [[NSMutableArray alloc] init]; +======= + _cellsForVisibilityUpdates = [NSMutableSet set]; +>>>>>>> 4b8216f... Adding scroll visibility self.backgroundColor = [UIColor whiteColor]; [self registerClass:[_ASCollectionViewCell class] forCellWithReuseIdentifier:kCellReuseIdentifier]; @@ -328,12 +339,14 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; _asyncDelegate = nil; _proxyDelegate = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; _asyncDelegateImplementsInsetSection = NO; + _asyncDelegateImplementsScrollviewDidScroll = NO; } else { _asyncDelegate = asyncDelegate; _proxyDelegate = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDelegate interceptor:self]; _asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0); + _asyncDelegateImplementsScrollviewDidScroll = ([_asyncDelegate respondsToSelector:@selector(scrollViewDidScroll:)] ? 1 : 0); } - + super.delegate = (id)_proxyDelegate; [_layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; @@ -589,6 +602,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; if (cellNode.neverShowPlaceholders) { [cellNode recursivelyEnsureDisplaySynchronously:YES]; } + [_cellsForVisibilityUpdates addObject:cell]; } - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath @@ -600,6 +614,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; ASDisplayNodeAssertNotNil(node, @"Expected node associated with removed cell not to be nil."); [_asyncDelegate collectionView:self didEndDisplayingNode:node forItemAtIndexPath:indexPath]; } + [_cellsForVisibilityUpdates removeObject:cell]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if ([_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNodeForItemAtIndexPath:)]) { @@ -650,6 +665,30 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; } } +<<<<<<< HEAD +- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ + for (ASCellNode *node in _cellsForVisibilityUpdates) { + if (node.shouldObserveVisibility) { + [node updateScrollSituationWithScrollVIew:scrollView]; + } + } + if ([_asyncDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { + [_asyncDelegate scrollViewDidScroll:scrollView]; + } +======= +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + for (ASCellNode *node in _cellsForVisibilityUpdates) { + if (node.shouldObserveVisibility) { + [node _visibleNodeDidScroll:scrollView withCellFrame:node.frame]; + } + } + if (_asyncDelegateImplementsScrollviewDidScroll) { + [_asyncDelegate scrollViewDidScroll:scrollView]; + } +>>>>>>> 4b8216f... Adding scroll visibility +} + - (BOOL)shouldBatchFetch { // if the delegate does not respond to this method, there is no point in starting to fetch diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index 2af0e7c7d5..baa65a65c7 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -56,6 +56,9 @@ // used for batch fetching API selector == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:) || + // used for ASCellNode visibility + selector == @selector(scrollViewDidScroll:) || + // intercepted due to not being supported by ASCollectionView (prevent bugs caused by usage) selector == @selector(collectionView:canMoveItemAtIndexPath:) || selector == @selector(collectionView:moveItemAtIndexPath:toIndexPath:) || From 274029a5e05e71dd8db8c4f104b806ecdffe410e Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 13:02:02 -0800 Subject: [PATCH 3/9] Removing an unnecessary property --- AsyncDisplayKit/ASCellNode.h | 1 - 1 file changed, 1 deletion(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index ecb616e09f..7f8cc01238 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -85,7 +85,6 @@ typedef NSUInteger ASCellNodeAnimation; */ @property (nonatomic, weak) id layoutDelegate; -@property (nonatomic, assign) BOOL shouldObserveVisibility; /* * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. From a834382bcbc521f236d96689d6c6644a4df903fc Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 14:27:22 -0800 Subject: [PATCH 4/9] Update for visibility monitoring --- AsyncDisplayKit/ASCellNode+Internal.h | 2 +- AsyncDisplayKit/ASCellNode.m | 6 +++--- AsyncDisplayKit/ASCollectionView.mm | 8 +++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode+Internal.h b/AsyncDisplayKit/ASCellNode+Internal.h index feb816467d..5481965995 100644 --- a/AsyncDisplayKit/ASCellNode+Internal.h +++ b/AsyncDisplayKit/ASCellNode+Internal.h @@ -10,6 +10,6 @@ @interface ASCellNode (Internal) -@property (nonatomic, assign) BOOL shouldObserveVisibility; +@property (nonatomic, assign) BOOL shouldMonitorScrollViewDidScroll; @end diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index 61458d5ac0..42f5b0b971 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -38,7 +38,7 @@ _selectionStyle = UITableViewCellSelectionStyleDefault; self.clipsToBounds = YES; if ([self.layoutDelegate respondsToSelector:@selector(visibleNodeDidScroll:inScrollView:withCellFrame:)]) { - self.shouldObserveVisibility= YES; + self.shouldMonitorScrollViewDidScroll = YES; } return self; } @@ -61,7 +61,7 @@ } if ([self.layoutDelegate respondsToSelector:@selector(visibleNodeDidScroll:inScrollView:withCellFrame:)]) { - self.shouldObserveVisibility = YES; + self.shouldMonitorScrollViewDidScroll = YES; } return self; } @@ -142,7 +142,7 @@ - (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame { - if (self.shouldObserveVisibility) { + if (self.shouldMonitorScrollViewDidScroll) { [self.layoutDelegate visibleNodeDidScroll:self inScrollView:scrollView withCellFrame:cellFrame]; } } diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 1f9a7ff89b..35ddd61c22 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -673,9 +673,11 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - for (ASCellNode *node in _cellsForVisibilityUpdates) { - if (node.shouldObserveVisibility) { - [node _visibleNodeDidScroll:scrollView withCellFrame:node.frame]; + for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) { + ASCellNode *node = [collectionCell node]; + if (node.shouldMonitorScrollViewDidScroll) { + NSLog(@"Calling _visibleNodeDidScroll"); + [node _visibleNodeDidScroll:scrollView withCellFrame: node.frame]; } } if (_asyncDelegateImplementsScrollviewDidScroll) { From 53cbd643de111c42969cb7a3f1db730a590d3a64 Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 14:56:02 -0800 Subject: [PATCH 5/9] Removing ASCellNode+Internal --- AsyncDisplayKit/ASCellNode+Internal.h | 15 --------------- AsyncDisplayKit/ASCellNode.h | 2 ++ AsyncDisplayKit/ASCellNode.m | 3 ++- AsyncDisplayKit/ASCollectionView.mm | 2 -- 4 files changed, 4 insertions(+), 18 deletions(-) delete mode 100644 AsyncDisplayKit/ASCellNode+Internal.h diff --git a/AsyncDisplayKit/ASCellNode+Internal.h b/AsyncDisplayKit/ASCellNode+Internal.h deleted file mode 100644 index 5481965995..0000000000 --- a/AsyncDisplayKit/ASCellNode+Internal.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ASCellNode+Internal.h -// Pods -// -// Created by Max Gu on 2/19/16. -// -// - -#import "ASCellNode.h" - -@interface ASCellNode (Internal) - -@property (nonatomic, assign) BOOL shouldMonitorScrollViewDidScroll; - -@end diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 7f8cc01238..45da0fd1ce 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -85,6 +85,8 @@ typedef NSUInteger ASCellNodeAnimation; */ @property (nonatomic, weak) id layoutDelegate; +@property (nonatomic, assign, readonly) BOOL shouldMonitorScrollViewDidScroll; + /* * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index 42f5b0b971..7aa83fc9fe 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -6,7 +6,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "ASCellNode+Internal.h" +#import "ASCellNode.h" #import "ASInternalHelpers.h" #import "ASCollectionView.h" @@ -24,6 +24,7 @@ UIViewController *_viewController; ASDisplayNode *_viewControllerNode; } +@property (nonatomic, assign, readwrite) BOOL shouldMonitorScrollViewDidScroll; @end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 35ddd61c22..461fe2e702 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -9,7 +9,6 @@ #import "ASAssert.h" #import "ASBatchFetching.h" #import "ASDelegateProxy.h" -#import "ASCellNode+Internal.h" #import "ASCollectionNode.h" #import "ASCollectionDataController.h" #import "ASCollectionViewLayoutController.h" @@ -676,7 +675,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) { ASCellNode *node = [collectionCell node]; if (node.shouldMonitorScrollViewDidScroll) { - NSLog(@"Calling _visibleNodeDidScroll"); [node _visibleNodeDidScroll:scrollView withCellFrame: node.frame]; } } From 382509fac84d0e39fdcd993e50c1e292788fbe01 Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 21:30:36 -0800 Subject: [PATCH 6/9] Letting ASCellNode and its subclasses handle didScroll --- AsyncDisplayKit/ASCellNode+Internal.h | 15 +++++++++++++++ AsyncDisplayKit/ASCellNode.h | 10 ---------- AsyncDisplayKit/ASCellNode.m | 14 ++------------ AsyncDisplayKit/ASCollectionView.mm | 15 ++++++++++----- 4 files changed, 27 insertions(+), 27 deletions(-) create mode 100644 AsyncDisplayKit/ASCellNode+Internal.h diff --git a/AsyncDisplayKit/ASCellNode+Internal.h b/AsyncDisplayKit/ASCellNode+Internal.h new file mode 100644 index 0000000000..2152d91bc3 --- /dev/null +++ b/AsyncDisplayKit/ASCellNode+Internal.h @@ -0,0 +1,15 @@ +// +// ASCellNode+Internal.h +// Pods +// +// Created by Max Gu on 2/19/16. +// +// + +#import "ASCellNode.h" + +@interface ASCellNode (Internal) + +- (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; + +@end diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 45da0fd1ce..830ed49e8f 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -25,15 +25,6 @@ typedef NSUInteger ASCellNodeAnimation; */ - (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged; -@optional -/** - * Notifies the delegate that the specified cell node has scrolled - * - * @param node: A node informing the delegate about the scroll - * @param cellFrame: The frame of the cell that has just scrolled - */ -- (void)visibleNodeDidScroll:(ASCellNode *)node inScrollView:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; - @end /** @@ -120,7 +111,6 @@ typedef NSUInteger ASCellNodeAnimation; - (instancetype)initWithViewControllerBlock:(ASDisplayNodeViewControllerBlock)viewControllerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock; - (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; - @end diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index 7aa83fc9fe..c007110680 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -9,7 +9,6 @@ #import "ASCellNode.h" #import "ASInternalHelpers.h" -#import "ASCollectionView.h" #import #import #import @@ -24,7 +23,6 @@ UIViewController *_viewController; ASDisplayNode *_viewControllerNode; } -@property (nonatomic, assign, readwrite) BOOL shouldMonitorScrollViewDidScroll; @end @@ -38,9 +36,6 @@ // Use UITableViewCell defaults _selectionStyle = UITableViewCellSelectionStyleDefault; self.clipsToBounds = YES; - if ([self.layoutDelegate respondsToSelector:@selector(visibleNodeDidScroll:inScrollView:withCellFrame:)]) { - self.shouldMonitorScrollViewDidScroll = YES; - } return self; } @@ -60,10 +55,7 @@ [self addSubnode:_viewControllerNode]; } - - if ([self.layoutDelegate respondsToSelector:@selector(visibleNodeDidScroll:inScrollView:withCellFrame:)]) { - self.shouldMonitorScrollViewDidScroll = YES; - } + return self; } @@ -143,9 +135,7 @@ - (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame { - if (self.shouldMonitorScrollViewDidScroll) { - [self.layoutDelegate visibleNodeDidScroll:self inScrollView:scrollView withCellFrame:cellFrame]; - } + // To be overriden by subclasses } @end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 461fe2e702..eb456bba15 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -9,6 +9,7 @@ #import "ASAssert.h" #import "ASBatchFetching.h" #import "ASDelegateProxy.h" +#import "ASCellNode+Internal.h" #import "ASCollectionNode.h" #import "ASCollectionDataController.h" #import "ASCollectionViewLayoutController.h" @@ -541,7 +542,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; if (cellNode.neverShowPlaceholders) { [cellNode recursivelyEnsureDisplaySynchronously:YES]; } - [_cellsForVisibilityUpdates addObject:cell]; + if (ASSubclassOverridesSelector([ASCellNode class], [cellNode class], @selector(_visibleNodeDidScroll:withCellFrame:))) { + [_cellsForVisibilityUpdates addObject:cell]; + } } - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath @@ -553,7 +556,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; ASDisplayNodeAssertNotNil(node, @"Expected node associated with removed cell not to be nil."); [_asyncDelegate collectionView:self didEndDisplayingNode:node forItemAtIndexPath:indexPath]; } - [_cellsForVisibilityUpdates removeObject:cell]; + if ([_cellsForVisibilityUpdates containsObject:cell]) { + [_cellsForVisibilityUpdates removeObject:cell]; + } + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if ([_asyncDelegate respondsToSelector:@selector(collectionView:didEndDisplayingNodeForItemAtIndexPath:)]) { @@ -674,9 +680,8 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; { for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) { ASCellNode *node = [collectionCell node]; - if (node.shouldMonitorScrollViewDidScroll) { - [node _visibleNodeDidScroll:scrollView withCellFrame: node.frame]; - } + // Only nodes that respond to the selector are added to _cellsForVisibilityUpdates + [node _visibleNodeDidScroll:scrollView withCellFrame:collectionCell.frame]; } if (_asyncDelegateImplementsScrollviewDidScroll) { [_asyncDelegate scrollViewDidScroll:scrollView]; From 115fc2b3da60a591b8be03b5f122cf05b317a92a Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 22:15:44 -0800 Subject: [PATCH 7/9] Adding visibility monitoring for ASTableVieww --- AsyncDisplayKit/ASCellNode.h | 5 ++-- AsyncDisplayKit/ASCellNode.m | 2 +- AsyncDisplayKit/ASCollectionView.mm | 6 ++--- AsyncDisplayKit/ASTableView.mm | 29 +++++++++++++++++++---- AsyncDisplayKit/Details/ASDelegateProxy.m | 3 +++ 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 830ed49e8f..8788d30015 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -76,8 +76,6 @@ typedef NSUInteger ASCellNodeAnimation; */ @property (nonatomic, weak) id layoutDelegate; -@property (nonatomic, assign, readonly) BOOL shouldMonitorScrollViewDidScroll; - /* * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. @@ -110,7 +108,8 @@ typedef NSUInteger ASCellNodeAnimation; */ - (instancetype)initWithViewControllerBlock:(ASDisplayNodeViewControllerBlock)viewControllerBlock didLoadBlock:(ASDisplayNodeDidLoadBlock)didLoadBlock; -- (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; +- (void)visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; + @end diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index c007110680..3e1fccdbc8 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -133,7 +133,7 @@ [(_ASDisplayView *)self.view __forwardTouchesCancelled:touches withEvent:event]; } -- (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame +- (void)visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame { // To be overriden by subclasses } diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index eb456bba15..bd60b03d82 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -530,7 +530,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; return cell; } -- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(_ASCollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { [_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:[self scrollDirection]]; @@ -538,7 +538,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; [_asyncDelegate collectionView:self willDisplayNodeForItemAtIndexPath:indexPath]; } - ASCellNode *cellNode = [self nodeForItemAtIndexPath:indexPath]; + ASCellNode *cellNode = [cell node]; if (cellNode.neverShowPlaceholders) { [cellNode recursivelyEnsureDisplaySynchronously:YES]; } @@ -681,7 +681,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) { ASCellNode *node = [collectionCell node]; // Only nodes that respond to the selector are added to _cellsForVisibilityUpdates - [node _visibleNodeDidScroll:scrollView withCellFrame:collectionCell.frame]; + [node visibleNodeDidScroll:scrollView withCellFrame:collectionCell.frame]; } if (_asyncDelegateImplementsScrollviewDidScroll) { [_asyncDelegate scrollViewDidScroll:scrollView]; diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index bbcfb42bba..272e6c4f46 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -112,6 +112,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; BOOL _queuedNodeHeightUpdate; BOOL _isDeallocating; BOOL _dataSourceImplementsNodeBlockForRowAtIndexPath; + BOOL _asyncDelegateImplementsScrollviewDidScroll; + NSMutableSet *_cellsForVisibilityUpdates; } @property (atomic, assign) BOOL asyncDataSourceLocked; @@ -197,7 +199,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; if (!(self = [super initWithFrame:frame style:style])) { return nil; } - + _cellsForVisibilityUpdates = [NSMutableSet set]; if (!dataControllerClass) { dataControllerClass = [[self class] dataControllerClass]; } @@ -585,7 +587,18 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; return direction; } -- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + for (_ASTableViewCell *tableCell in _cellsForVisibilityUpdates) { + ASCellNode *node = [tableCell node]; + [node visibleNodeDidScroll:scrollView withCellFrame:tableCell.frame]; + } + if (_asyncDelegateImplementsScrollviewDidScroll) { + [_asyncDelegate scrollViewDidScroll:scrollView]; + } +} + +- (void)tableView:(UITableView *)tableView willDisplayCell:(_ASTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { _pendingVisibleIndexPath = indexPath; @@ -595,13 +608,17 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; [_asyncDelegate tableView:self willDisplayNodeForRowAtIndexPath:indexPath]; } - ASCellNode *cellNode = [self nodeForRowAtIndexPath:indexPath]; + ASCellNode *cellNode = [cell node]; + + if (ASSubclassOverridesSelector([ASCellNode class], [cellNode class], @selector(visibleNodeDidScroll:withCellFrame:))) { + [_cellsForVisibilityUpdates addObject:cell]; + } if (cellNode.neverShowPlaceholders) { [cellNode recursivelyEnsureDisplaySynchronously:YES]; } } -- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath +- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(_ASTableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath { if ([_pendingVisibleIndexPath isEqual:indexPath]) { _pendingVisibleIndexPath = nil; @@ -615,6 +632,10 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; [_asyncDelegate tableView:self didEndDisplayingNode:node forRowAtIndexPath:indexPath]; } + if ([_cellsForVisibilityUpdates containsObject:cell]) { + [_cellsForVisibilityUpdates removeObject:cell]; + } + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if ([_asyncDelegate respondsToSelector:@selector(tableView:didEndDisplayingNodeForRowAtIndexPath:)]) { diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index baa65a65c7..3034a83d86 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -24,6 +24,9 @@ selector == @selector(numberOfSectionsInTableView:) || selector == @selector(tableView:numberOfRowsInSection:) || + // used for ASCellNode visibility + selector == @selector(scrollViewDidScroll:) || + // used for ASRangeController visibility updates selector == @selector(tableView:willDisplayCell:forRowAtIndexPath:) || selector == @selector(tableView:didEndDisplayingCell:forRowAtIndexPath:) || From 548b600504ae39ce037a1f3fa423a58de6ccd7eb Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 22:18:08 -0800 Subject: [PATCH 8/9] Removing 2 unnecessary checks --- AsyncDisplayKit/ASCollectionView.mm | 5 ++--- AsyncDisplayKit/ASTableView.mm | 4 +--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index bd60b03d82..f26f38a85a 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -556,9 +556,8 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; ASDisplayNodeAssertNotNil(node, @"Expected node associated with removed cell not to be nil."); [_asyncDelegate collectionView:self didEndDisplayingNode:node forItemAtIndexPath:indexPath]; } - if ([_cellsForVisibilityUpdates containsObject:cell]) { - [_cellsForVisibilityUpdates removeObject:cell]; - } + [_cellsForVisibilityUpdates removeObject:cell]; + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 272e6c4f46..a9f4d2aff9 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -632,9 +632,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; [_asyncDelegate tableView:self didEndDisplayingNode:node forRowAtIndexPath:indexPath]; } - if ([_cellsForVisibilityUpdates containsObject:cell]) { - [_cellsForVisibilityUpdates removeObject:cell]; - } + [_cellsForVisibilityUpdates removeObject:cell]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" From 67c8cd5ccf90b2a44b69cc87a1de4d4f3e2622e7 Mon Sep 17 00:00:00 2001 From: Max Gu Date: Fri, 19 Feb 2016 22:21:07 -0800 Subject: [PATCH 9/9] Removing underscore --- AsyncDisplayKit/ASCellNode+Internal.h | 2 -- AsyncDisplayKit/ASCollectionView.mm | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode+Internal.h b/AsyncDisplayKit/ASCellNode+Internal.h index 2152d91bc3..a660e46d80 100644 --- a/AsyncDisplayKit/ASCellNode+Internal.h +++ b/AsyncDisplayKit/ASCellNode+Internal.h @@ -10,6 +10,4 @@ @interface ASCellNode (Internal) -- (void)_visibleNodeDidScroll:(UIScrollView *)scrollView withCellFrame:(CGRect)cellFrame; - @end diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index f26f38a85a..20e30b7c40 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -542,7 +542,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; if (cellNode.neverShowPlaceholders) { [cellNode recursivelyEnsureDisplaySynchronously:YES]; } - if (ASSubclassOverridesSelector([ASCellNode class], [cellNode class], @selector(_visibleNodeDidScroll:withCellFrame:))) { + if (ASSubclassOverridesSelector([ASCellNode class], [cellNode class], @selector(visibleNodeDidScroll:withCellFrame:))) { [_cellsForVisibilityUpdates addObject:cell]; } }