From 04d93532bc68356ed5071709d4bf4a7d753ac923 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Mon, 30 Nov 2015 17:20:32 -0800 Subject: [PATCH] Only require node sizes once per run loop, and only if a node's size has changed --- AsyncDisplayKit/ASCellNode.h | 5 +++-- AsyncDisplayKit/ASCellNode.m | 5 +++-- AsyncDisplayKit/ASCollectionView.mm | 21 +++++++++++++++++++-- AsyncDisplayKit/ASTableView.mm | 21 +++++++++++++++++++-- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 16fc60d1f3..6b038ee853 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -15,12 +15,13 @@ typedef NSUInteger ASCellNodeAnimation; @protocol ASCellNodeLayoutDelegate /** - * Notifies the delegate that the specified cell node has done a relayout. + * Notifies the delegate that the specified cell node has done a relayout + * that resulted in a change of `calculatedSize`. * The notification is done on main thread. * * @param node A node informing the delegate about the relayout. */ -- (void)nodeDidRelayout:(ASCellNode *)node; +- (void)nodeDidRelayoutWithSizeChange:(ASCellNode *)node; @end /** diff --git a/AsyncDisplayKit/ASCellNode.m b/AsyncDisplayKit/ASCellNode.m index ef6652b700..029de4b8a4 100644 --- a/AsyncDisplayKit/ASCellNode.m +++ b/AsyncDisplayKit/ASCellNode.m @@ -53,11 +53,12 @@ - (void)setNeedsLayout { ASDisplayNodeAssertThreadAffinity(self); + CGSize oldSize = self.calculatedSize; [super setNeedsLayout]; - if (_layoutDelegate != nil) { + if (_layoutDelegate != nil && !CGSizeEqualToSize(oldSize, self.calculatedSize)) { ASPerformBlockOnMainThread(^{ - [_layoutDelegate nodeDidRelayout:self]; + [_layoutDelegate nodeDidRelayoutWithSizeChange:self]; }); } } diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index a139bdecec..0c1f7e9961 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -155,6 +155,7 @@ static BOOL _isInterceptedSelector(SEL sel) BOOL _asyncDelegateImplementsInsetSection; BOOL _collectionViewLayoutImplementsInsetSection; BOOL _asyncDataSourceImplementsConstrainedSizeForNode; + BOOL _queuedNodeSizeUpdate; ASBatchContext *_batchContext; @@ -912,10 +913,26 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark - ASCellNodeDelegate -- (void)nodeDidRelayout:(ASCellNode *)node +- (void)nodeDidRelayoutWithSizeChange:(ASCellNode *)node { ASDisplayNodeAssertMainThread(); - // Cause UICollectionView to requery for the new height of this node + + if (_queuedNodeSizeUpdate) { + return; + } + + _queuedNodeSizeUpdate = YES; + [self performSelector:@selector(requeryNodeSizes) + withObject:nil + afterDelay:0 + inModes:@[ NSRunLoopCommonModes ]]; +} + +// Cause UICollectionView to requery for the new size of all nodes +- (void)requeryNodeSizes +{ + _queuedNodeSizeUpdate = NO; + [super performBatchUpdates:^{} completion:nil]; } diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 7354bdcf55..295e592a7e 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -179,6 +179,7 @@ static BOOL _isInterceptedSelector(SEL sel) CGFloat _nodesConstrainedWidth; BOOL _ignoreNodesConstrainedWidthChange; + BOOL _queuedNodeHeightUpdate; } @property (atomic, assign) BOOL asyncDataSourceLocked; @@ -909,10 +910,26 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark - ASCellNodeLayoutDelegate -- (void)nodeDidRelayout:(ASCellNode *)node +- (void)nodeDidRelayoutWithSizeChange:(ASCellNode *)node { ASDisplayNodeAssertMainThread(); - // Cause UITableView to requery for the new height of this node + + if (_queuedNodeHeightUpdate) { + return; + } + + _queuedNodeHeightUpdate = YES; + [self performSelector:@selector(requeryNodeHeights) + withObject:nil + afterDelay:0 + inModes:@[ NSRunLoopCommonModes ]]; +} + +// Cause UITableView to requery for the new height of this node +- (void)requeryNodeHeights +{ + _queuedNodeHeightUpdate = NO; + [super beginUpdates]; [super endUpdates]; }