From 68e2e068c358fcf5dc3ec19005e4bf2d8c920218 Mon Sep 17 00:00:00 2001 From: Ethan Nagel Date: Fri, 17 Apr 2015 16:09:44 -0700 Subject: [PATCH] Bug Fix - ASTableVie sometimes fails to render cell contents when scrolling programatically. Root cause is because we assume UITableView's indexPathsForVisibleRows return the new item to be displayed after tableView:willDisplayCell:forRowAtIndexPath: is called. This is not always true, especially when we are scrolling programmatically. Fix is to track this "pending" visible index path and return it along with the UITableView's indexPathsForVisibleRows in rangeControllerVisibleNodeIndexPaths:. --- AsyncDisplayKit/ASTableView.mm | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 4c2b79ca01..26f9f9601e 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -118,6 +118,8 @@ static BOOL _isInterceptedSelector(SEL sel) BOOL _asyncDataFetchingEnabled; ASBatchContext *_batchContext; + + NSIndexPath *_pendingVisibleIndexPath; } @property (atomic, assign) BOOL asyncDataSourceLocked; @@ -366,6 +368,8 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { + _pendingVisibleIndexPath = indexPath; + [_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection]; if ([_asyncDelegate respondsToSelector:@selector(tableView:willDisplayNodeForRowAtIndexPath:)]) { @@ -375,6 +379,10 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath { + if ([_pendingVisibleIndexPath isEqual:indexPath]) { + _pendingVisibleIndexPath = nil; + } + [_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection]; if ([_asyncDelegate respondsToSelector:@selector(tableView:didEndDisplayingNodeForRowAtIndexPath:)]) { @@ -445,7 +453,21 @@ static BOOL _isInterceptedSelector(SEL sel) - (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController { ASDisplayNodeAssertMainThread(); - return [self indexPathsForVisibleRows]; + + NSArray *visibleIndexPaths = self.indexPathsForVisibleRows; + + if ( _pendingVisibleIndexPath ) { + NSMutableSet *indexPaths = [NSMutableSet setWithArray:self.indexPathsForVisibleRows]; + + if ( [indexPaths containsObject:_pendingVisibleIndexPath]) { + _pendingVisibleIndexPath = nil; // once it has shown up in visibleIndexPaths, we can stop tracking it + } else { + [indexPaths addObject:_pendingVisibleIndexPath]; + visibleIndexPaths = indexPaths.allObjects; + } + } + + return visibleIndexPaths; } - (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths