@@ -174,6 +174,15 @@ @interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDe
174174 * The collection view never queried your data source before the update to see that it actually had 0 items.
175175 */
176176 BOOL _superIsPendingDataLoad;
177+
178+ /* *
179+ * It's important that we always check for batch fetching at least once, but also
180+ * that we do not check for batch fetching for empty updates (as that may cause an infinite
181+ * loop of batch fetching, where the batch completes and performBatchUpdates: is called without
182+ * actually making any changes.) So to handle the case where a collection is completely empty
183+ * (0 sections) we always check at least once after each update (initial reload is the first update.)
184+ */
185+ BOOL _hasEverCheckedForBatchFetchingDueToUpdate;
177186
178187 struct {
179188 unsigned int scrollViewDidScroll:1 ;
@@ -1080,6 +1089,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView
10801089 ASInterfaceState interfaceState = [self interfaceStateForRangeController: _rangeController];
10811090 if (ASInterfaceStateIncludesVisible (interfaceState)) {
10821091 [_rangeController updateCurrentRangeWithMode: ASLayoutRangeModeFull];
1092+ [self _checkForBatchFetching ];
10831093 }
10841094
10851095 for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) {
@@ -1103,7 +1113,7 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi
11031113
11041114 if (targetContentOffset != NULL ) {
11051115 ASDisplayNodeAssert (_batchContext != nil , @" Batch context should exist" );
1106- [self _beginBatchFetchingIfNeededWithScrollView: self forScrollDirection: [ self scrollDirection ] contentOffset : *targetContentOffset];
1116+ [self _beginBatchFetchingIfNeededWithContentOffset : *targetContentOffset];
11071117 }
11081118
11091119 if (_asyncDelegateFlags.scrollViewWillEndDragging ) {
@@ -1244,9 +1254,10 @@ - (BOOL)canBatchFetch
12441254- (void )_scheduleCheckForBatchFetchingForNumberOfChanges : (NSUInteger )changes
12451255{
12461256 // Prevent fetching will continually trigger in a loop after reaching end of content and no new content was provided
1247- if (changes == 0 ) {
1257+ if (changes == 0 && _hasEverCheckedForBatchFetchingDueToUpdate ) {
12481258 return ;
12491259 }
1260+ _hasEverCheckedForBatchFetchingDueToUpdate = YES ;
12501261
12511262 // Push this to the next runloop to be sure the scroll view has the right content size
12521263 dispatch_async (dispatch_get_main_queue (), ^{
@@ -1261,12 +1272,12 @@ - (void)_checkForBatchFetching
12611272 return ;
12621273 }
12631274
1264- [self _beginBatchFetchingIfNeededWithScrollView: self forScrollDirection: [ self scrollableDirections ] contentOffset :self .contentOffset];
1275+ [self _beginBatchFetchingIfNeededWithContentOffset :self .contentOffset];
12651276}
12661277
1267- - (void )_beginBatchFetchingIfNeededWithScrollView : (UIScrollView<ASBatchFetchingScrollView> *) scrollView forScrollDirection : (ASScrollDirection) scrollDirection contentOffset : (CGPoint)contentOffset
1278+ - (void )_beginBatchFetchingIfNeededWithContentOffset : (CGPoint)contentOffset
12681279{
1269- if (ASDisplayShouldFetchBatchForScrollView (self, scrollDirection, contentOffset)) {
1280+ if (ASDisplayShouldFetchBatchForScrollView (self, self. scrollDirection , self. scrollableDirections , contentOffset)) {
12701281 [self _beginBatchFetching ];
12711282 }
12721283}
@@ -1521,11 +1532,6 @@ - (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimat
15211532 _performingBatchUpdates = NO ;
15221533}
15231534
1524- - (void )didCompleteUpdatesInRangeController : (ASRangeController *)rangeController
1525- {
1526- [self _checkForBatchFetching ];
1527- }
1528-
15291535- (void )rangeController : (ASRangeController *)rangeController didInsertNodes : (NSArray *)nodes atIndexPaths : (NSArray *)indexPaths withAnimationOptions : (ASDataControllerAnimationOptions)animationOptions
15301536{
15311537 ASDisplayNodeAssertMainThread ();
0 commit comments