mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-03-29 08:39:00 +08:00
Merge pull request #1477 from maicki/SmallContentBatchFetch
[ASBatchContext] Fix fetch call won't occur for content smaller than bounds unless user scrolls
This commit is contained in:
@@ -91,7 +91,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
#pragma mark -
|
||||
#pragma mark ASCollectionView.
|
||||
|
||||
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor> {
|
||||
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView> {
|
||||
ASCollectionViewProxy *_proxyDataSource;
|
||||
ASCollectionViewProxy *_proxyDelegate;
|
||||
|
||||
@@ -605,8 +605,45 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
cellNode.scrollView = nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Scroll Direction.
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
// If a scroll happenes the current range mode needs to go to full
|
||||
ASInterfaceState interfaceState = [self interfaceStateForRangeController:_rangeController];
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
[_rangeController updateCurrentRangeWithMode:ASLayoutRangeModeFull];
|
||||
}
|
||||
|
||||
for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) {
|
||||
// Only nodes that respond to the selector are added to _cellsForVisibilityUpdates
|
||||
[[collectionCell node] cellNodeVisibilityEvent:ASCellNodeVisibilityEventVisibleRectChanged
|
||||
inScrollView:scrollView
|
||||
withCellFrame:collectionCell.frame];
|
||||
}
|
||||
if (_asyncDelegateImplementsScrollviewDidScroll) {
|
||||
[_asyncDelegate scrollViewDidScroll:scrollView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
|
||||
{
|
||||
_deceleratingVelocity = CGPointMake(
|
||||
scrollView.contentOffset.x - ((targetContentOffset != NULL) ? targetContentOffset->x : 0),
|
||||
scrollView.contentOffset.y - ((targetContentOffset != NULL) ? targetContentOffset->y : 0)
|
||||
);
|
||||
|
||||
if (targetContentOffset != NULL) {
|
||||
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
|
||||
[self _beginBatchFetchingIfNeededWithScrollView:self forScrollDirection:[self scrollDirection] contentOffset:*targetContentOffset];
|
||||
}
|
||||
|
||||
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
|
||||
[_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Scroll Direction.
|
||||
|
||||
- (ASScrollDirection)scrollDirection
|
||||
{
|
||||
@@ -700,45 +737,14 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Batch Fetching
|
||||
#pragma mark - Batch Fetching
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
|
||||
- (ASBatchContext *)batchContext
|
||||
{
|
||||
_deceleratingVelocity = CGPointMake(
|
||||
scrollView.contentOffset.x - ((targetContentOffset != NULL) ? targetContentOffset->x : 0),
|
||||
scrollView.contentOffset.y - ((targetContentOffset != NULL) ? targetContentOffset->y : 0)
|
||||
);
|
||||
|
||||
if (targetContentOffset != NULL) {
|
||||
[self handleBatchFetchScrollingToOffset:*targetContentOffset];
|
||||
}
|
||||
|
||||
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
|
||||
[_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
|
||||
}
|
||||
return _batchContext;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
// If a scroll happenes the current range mode needs to go to full
|
||||
ASInterfaceState interfaceState = [self interfaceStateForRangeController:_rangeController];
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
[_rangeController updateCurrentRangeWithMode:ASLayoutRangeModeFull];
|
||||
}
|
||||
|
||||
for (_ASCollectionViewCell *collectionCell in _cellsForVisibilityUpdates) {
|
||||
// Only nodes that respond to the selector are added to _cellsForVisibilityUpdates
|
||||
[[collectionCell node] cellNodeVisibilityEvent:ASCellNodeVisibilityEventVisibleRectChanged
|
||||
inScrollView:scrollView
|
||||
withCellFrame:collectionCell.frame];
|
||||
}
|
||||
if (_asyncDelegateImplementsScrollviewDidScroll) {
|
||||
[_asyncDelegate scrollViewDidScroll:scrollView];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldBatchFetch
|
||||
- (BOOL)canBatchFetch
|
||||
{
|
||||
// if the delegate does not respond to this method, there is no point in starting to fetch
|
||||
BOOL canFetch = [_asyncDelegate respondsToSelector:@selector(collectionView:willBeginBatchFetchWithContext:)];
|
||||
@@ -749,16 +755,37 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleBatchFetchScrollingToOffset:(CGPoint)targetOffset
|
||||
- (void)_scheduleCheckForBatchFetching
|
||||
{
|
||||
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
|
||||
|
||||
if (![self shouldBatchFetch]) {
|
||||
// Push this to the next runloop to be sure the scroll view has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)_checkForBatchFetching
|
||||
{
|
||||
// Dragging will be handled in scrollViewWillEndDragging:withVelocity:targetContentOffset:
|
||||
if (self.isDragging || self.isTracking) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ASDisplayShouldFetchBatchForContext(_batchContext, [self scrollDirection], self.bounds, self.contentSize, targetOffset, _leadingScreensForBatching)) {
|
||||
[_batchContext beginBatchFetching];
|
||||
[self _beginBatchFetchingIfNeededWithScrollView:self forScrollDirection:[self scrollableDirections] contentOffset:self.contentOffset];
|
||||
}
|
||||
|
||||
- (void)_beginBatchFetchingIfNeededWithScrollView:(UIScrollView<ASBatchFetchingScrollView> *)scrollView forScrollDirection:(ASScrollDirection)scrollDirection contentOffset:(CGPoint)contentOffset
|
||||
{
|
||||
if (ASDisplayShouldFetchBatchForScrollView(self, scrollDirection, contentOffset)) {
|
||||
[self _beginBatchFetching];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_beginBatchFetching
|
||||
{
|
||||
NSLog(@"begin batch fetching");
|
||||
|
||||
[_batchContext beginBatchFetching];
|
||||
if ([_asyncDelegate respondsToSelector:@selector(collectionView:willBeginBatchFetchWithContext:)]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[_asyncDelegate collectionView:self willBeginBatchFetchWithContext:_batchContext];
|
||||
});
|
||||
@@ -954,7 +981,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
for (dispatch_block_t block in _batchUpdateBlocks) {
|
||||
block();
|
||||
}
|
||||
} completion:completion];
|
||||
} completion:^(BOOL finished){
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
if (completion) { completion(finished); }
|
||||
}];
|
||||
});
|
||||
|
||||
[_batchUpdateBlocks removeAllObjects];
|
||||
@@ -977,6 +1007,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:indexPaths batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super insertItemsAtIndexPaths:indexPaths];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -997,6 +1028,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:indexPaths batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super deleteItemsAtIndexPaths:indexPaths];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1017,6 +1049,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditSectionsAtIndexSet:indexSet batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super insertSections:indexSet];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1037,6 +1070,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditSectionsAtIndexSet:indexSet batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super deleteSections:indexSet];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +88,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
- (instancetype)_initWithTableView:(ASTableView *)tableView;
|
||||
@end
|
||||
|
||||
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate,
|
||||
ASDataControllerSource, _ASTableViewCellDelegate,
|
||||
ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor>
|
||||
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView>
|
||||
{
|
||||
ASTableViewProxy *_proxyDataSource;
|
||||
ASTableViewProxy *_proxyDelegate;
|
||||
@@ -524,8 +522,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Intercepted selectors
|
||||
|
||||
#pragma mark - Intercepted selectors
|
||||
|
||||
- (void)setTableHeaderView:(UIView *)tableHeaderView
|
||||
{
|
||||
@@ -579,47 +577,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
return [_dataController numberOfRowsInSection:section];
|
||||
}
|
||||
|
||||
- (ASScrollDirection)scrollDirection
|
||||
{
|
||||
CGPoint scrollVelocity;
|
||||
if (self.isTracking) {
|
||||
scrollVelocity = [self.panGestureRecognizer velocityInView:self.superview];
|
||||
} else {
|
||||
scrollVelocity = _deceleratingVelocity;
|
||||
}
|
||||
ASScrollDirection scrollDirection = [self _scrollDirectionForVelocity:scrollVelocity];
|
||||
return ASScrollDirectionApplyTransform(scrollDirection, self.transform);
|
||||
}
|
||||
|
||||
- (ASScrollDirection)_scrollDirectionForVelocity:(CGPoint)velocity
|
||||
{
|
||||
ASScrollDirection direction = ASScrollDirectionNone;
|
||||
if (velocity.y < 0.0) {
|
||||
direction = ASScrollDirectionDown;
|
||||
} else if (velocity.y > 0.0) {
|
||||
direction = ASScrollDirectionUp;
|
||||
}
|
||||
return direction;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
// If a scroll happenes the current range mode needs to go to full
|
||||
ASInterfaceState interfaceState = [self interfaceStateForRangeController:_rangeController];
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
[_rangeController updateCurrentRangeWithMode:ASLayoutRangeModeFull];
|
||||
}
|
||||
|
||||
for (_ASTableViewCell *tableCell in _cellsForVisibilityUpdates) {
|
||||
[[tableCell node] cellNodeVisibilityEvent:ASCellNodeVisibilityEventVisibleRectChanged
|
||||
inScrollView:scrollView
|
||||
withCellFrame:tableCell.frame];
|
||||
}
|
||||
if (_asyncDelegateImplementsScrollviewDidScroll) {
|
||||
[_asyncDelegate scrollViewDidScroll:scrollView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayCell:(_ASTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
_pendingVisibleIndexPath = indexPath;
|
||||
@@ -631,7 +588,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
[_asyncDelegate tableView:self willDisplayNodeForRowAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:[self scrollDirection]];
|
||||
|
||||
if (cellNode.neverShowPlaceholders) {
|
||||
[cellNode recursivelyEnsureDisplaySynchronously:YES];
|
||||
@@ -650,7 +607,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
ASCellNode *cellNode = [cell node];
|
||||
|
||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:[self scrollDirection]];
|
||||
|
||||
if ([_asyncDelegate respondsToSelector:@selector(tableView:didEndDisplayingNode:forRowAtIndexPath:)]) {
|
||||
ASDisplayNodeAssertNotNil(cellNode, @"Expected node associated with removed cell not to be nil.");
|
||||
@@ -672,8 +629,23 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Batch Fetching
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
// If a scroll happenes the current range mode needs to go to full
|
||||
ASInterfaceState interfaceState = [self interfaceStateForRangeController:_rangeController];
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
[_rangeController updateCurrentRangeWithMode:ASLayoutRangeModeFull];
|
||||
}
|
||||
|
||||
for (_ASTableViewCell *tableCell in _cellsForVisibilityUpdates) {
|
||||
[[tableCell node] cellNodeVisibilityEvent:ASCellNodeVisibilityEventVisibleRectChanged
|
||||
inScrollView:scrollView
|
||||
withCellFrame:tableCell.frame];
|
||||
}
|
||||
if (_asyncDelegateImplementsScrollviewDidScroll) {
|
||||
[_asyncDelegate scrollViewDidScroll:scrollView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
|
||||
{
|
||||
@@ -683,7 +655,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
);
|
||||
|
||||
if (targetContentOffset != NULL) {
|
||||
[self handleBatchFetchScrollingToOffset:*targetContentOffset];
|
||||
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
|
||||
[self _beginBatchFetchingIfNeededWithScrollView:self forScrollDirection:[self scrollDirection] contentOffset:*targetContentOffset];
|
||||
}
|
||||
|
||||
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
|
||||
@@ -691,7 +664,62 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldBatchFetch
|
||||
|
||||
#pragma mark - Scroll Direction
|
||||
|
||||
- (ASScrollDirection)scrollDirection
|
||||
{
|
||||
CGPoint scrollVelocity;
|
||||
if (self.isTracking) {
|
||||
scrollVelocity = [self.panGestureRecognizer velocityInView:self.superview];
|
||||
} else {
|
||||
scrollVelocity = _deceleratingVelocity;
|
||||
}
|
||||
|
||||
ASScrollDirection scrollDirection = [self _scrollDirectionForVelocity:scrollVelocity];
|
||||
return ASScrollDirectionApplyTransform(scrollDirection, self.transform);
|
||||
}
|
||||
|
||||
- (ASScrollDirection)_scrollDirectionForVelocity:(CGPoint)scrollVelocity
|
||||
{
|
||||
ASScrollDirection direction = ASScrollDirectionNone;
|
||||
ASScrollDirection scrollableDirections = [self scrollableDirections];
|
||||
|
||||
if (ASScrollDirectionContainsVerticalDirection(scrollableDirections)) { // Can scroll vertically.
|
||||
if (scrollVelocity.y < 0.0) {
|
||||
direction |= ASScrollDirectionDown;
|
||||
} else if (scrollVelocity.y > 0.0) {
|
||||
direction |= ASScrollDirectionUp;
|
||||
}
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
- (ASScrollDirection)scrollableDirections
|
||||
{
|
||||
ASScrollDirection scrollableDirection = ASScrollDirectionNone;
|
||||
CGFloat totalContentWidth = self.contentSize.width + self.contentInset.left + self.contentInset.right;
|
||||
CGFloat totalContentHeight = self.contentSize.height + self.contentInset.top + self.contentInset.bottom;
|
||||
|
||||
if (self.alwaysBounceHorizontal || totalContentWidth > self.bounds.size.width) { // Can scroll horizontally.
|
||||
scrollableDirection |= ASScrollDirectionHorizontalDirections;
|
||||
}
|
||||
if (self.alwaysBounceVertical || totalContentHeight > self.bounds.size.height) { // Can scroll vertically.
|
||||
scrollableDirection |= ASScrollDirectionVerticalDirections;
|
||||
}
|
||||
return scrollableDirection;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Batch Fetching
|
||||
|
||||
- (ASBatchContext *)batchContext
|
||||
{
|
||||
return _batchContext;
|
||||
}
|
||||
|
||||
- (BOOL)canBatchFetch
|
||||
{
|
||||
// if the delegate does not respond to this method, there is no point in starting to fetch
|
||||
BOOL canFetch = [_asyncDelegate respondsToSelector:@selector(tableView:willBeginBatchFetchWithContext:)];
|
||||
@@ -702,16 +730,35 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleBatchFetchScrollingToOffset:(CGPoint)targetOffset
|
||||
- (void)_scheduleCheckForBatchFetching
|
||||
{
|
||||
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
|
||||
// Push this to the next runloop to be sure the scroll view has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
});
|
||||
}
|
||||
|
||||
if (![self shouldBatchFetch]) {
|
||||
- (void)_checkForBatchFetching
|
||||
{
|
||||
// Dragging will be handled in scrollViewWillEndDragging:withVelocity:targetContentOffset:
|
||||
if (self.isDragging || self.isTracking) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self _beginBatchFetchingIfNeededWithScrollView:self forScrollDirection:[self scrollableDirections] contentOffset:self.contentOffset];
|
||||
}
|
||||
|
||||
if (ASDisplayShouldFetchBatchForContext(_batchContext, [self scrollDirection], self.bounds, self.contentSize, targetOffset, _leadingScreensForBatching)) {
|
||||
[_batchContext beginBatchFetching];
|
||||
- (void)_beginBatchFetchingIfNeededWithScrollView:(UIScrollView<ASBatchFetchingScrollView> *)scrollView forScrollDirection:(ASScrollDirection)scrollDirection contentOffset:(CGPoint)contentOffset
|
||||
{
|
||||
if (ASDisplayShouldFetchBatchForScrollView(self, scrollDirection, contentOffset)) {
|
||||
[self _beginBatchFetching];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_beginBatchFetching
|
||||
{
|
||||
[_batchContext beginBatchFetching];
|
||||
if ([_asyncDelegate respondsToSelector:@selector(tableView:willBeginBatchFetchWithContext:)]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[_asyncDelegate tableView:self willBeginBatchFetchWithContext:_batchContext];
|
||||
});
|
||||
@@ -857,6 +904,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
|
||||
if (_automaticallyAdjustsContentOffset) {
|
||||
@@ -876,6 +924,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
|
||||
if (_automaticallyAdjustsContentOffset) {
|
||||
@@ -896,6 +945,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -911,6 +961,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1077,7 +1128,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
// Updating the visible node index paths only for not range managed nodes. Range managed nodes will get their
|
||||
// their update in the layout pass
|
||||
if (![node supportsRangeManagedInterfaceState]) {
|
||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection];
|
||||
[_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:[self scrollDirection]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,12 @@ typedef NS_ENUM(NSInteger, ASBatchContextState) {
|
||||
return _state == ASBatchContextStateCancelled;
|
||||
}
|
||||
|
||||
- (void)beginBatchFetching
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
_state = ASBatchContextStateFetching;
|
||||
}
|
||||
|
||||
- (void)completeBatchFetching:(BOOL)didComplete
|
||||
{
|
||||
if (didComplete) {
|
||||
@@ -53,12 +59,6 @@ typedef NS_ENUM(NSInteger, ASBatchContextState) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)beginBatchFetching
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
_state = ASBatchContextStateFetching;
|
||||
}
|
||||
|
||||
- (void)cancelBatchFetching
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
|
||||
@@ -10,10 +10,29 @@
|
||||
|
||||
#import "ASBatchContext.h"
|
||||
#import "ASScrollDirection.h"
|
||||
#import "ASBaseDefines.h"
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_BEGIN
|
||||
|
||||
@protocol ASBatchFetchingScrollView <NSObject>
|
||||
|
||||
- (BOOL)canBatchFetch;
|
||||
- (ASBatchContext *)batchContext;
|
||||
- (CGFloat)leadingScreensForBatching;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
@abstract Determine if batch fetching should begin based on the state of the parameters.
|
||||
@discussion This method is broken into a category for unit testing purposes and should be used with the ASTableView and
|
||||
* ASCollectionView batch fetching API.
|
||||
@param context The scroll view that in-flight fetches are happening.
|
||||
@param scrollDirection The current scrolling direction of the scroll view.
|
||||
@param targetOffset The offset that the scrollview will scroll to.
|
||||
@return Whether or not the current state should proceed with batch fetching.
|
||||
*/
|
||||
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView, ASScrollDirection scrollDirection, CGPoint contentOffset);
|
||||
|
||||
|
||||
/**
|
||||
@abstract Determine if batch fetching should begin based on the state of the parameters.
|
||||
@param context The batch fetching context that contains knowledge about in-flight fetches.
|
||||
|
||||
@@ -8,34 +8,50 @@
|
||||
|
||||
#import "ASBatchFetching.h"
|
||||
|
||||
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView, ASScrollDirection scrollDirection, CGPoint contentOffset)
|
||||
{
|
||||
// Don't fetch if the scroll view does not allow
|
||||
if (![scrollView canBatchFetch]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Check if we should batch fetch
|
||||
ASBatchContext *context = scrollView.batchContext;
|
||||
CGRect bounds = scrollView.bounds;
|
||||
CGSize contentSize = scrollView.contentSize;
|
||||
CGFloat leadingScreens = scrollView.leadingScreensForBatching;
|
||||
return ASDisplayShouldFetchBatchForContext(context, scrollDirection, bounds, contentSize, contentOffset, leadingScreens);
|
||||
}
|
||||
|
||||
BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
|
||||
ASScrollDirection scrollDirection,
|
||||
CGRect bounds,
|
||||
CGSize contentSize,
|
||||
CGPoint targetOffset,
|
||||
CGFloat leadingScreens) {
|
||||
// do not allow fetching if a batch is already in-flight and hasn't been completed or cancelled
|
||||
ASScrollDirection scrollDirection,
|
||||
CGRect bounds,
|
||||
CGSize contentSize,
|
||||
CGPoint targetOffset,
|
||||
CGFloat leadingScreens)
|
||||
{
|
||||
// Do not allow fetching if a batch is already in-flight and hasn't been completed or cancelled
|
||||
if ([context isFetching]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// only Down and Right scrolls are currently supported (tail loading)
|
||||
if (scrollDirection != ASScrollDirectionDown && scrollDirection != ASScrollDirectionRight) {
|
||||
// Only Down and Right scrolls are currently supported (tail loading)
|
||||
if (!ASScrollDirectionContainsDown(scrollDirection) && !ASScrollDirectionContainsRight(scrollDirection)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
// no fetching for null states
|
||||
// No fetching for null states
|
||||
if (leadingScreens <= 0.0 || CGRectEqualToRect(bounds, CGRectZero)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
CGFloat viewLength, offset, contentLength;
|
||||
|
||||
if (scrollDirection == ASScrollDirectionDown) {
|
||||
if (ASScrollDirectionContainsDown(scrollDirection)) {
|
||||
viewLength = bounds.size.height;
|
||||
offset = targetOffset.y;
|
||||
contentLength = contentSize.height;
|
||||
} else { // horizontal
|
||||
} else { // horizontal / right
|
||||
viewLength = bounds.size.width;
|
||||
offset = targetOffset.x;
|
||||
contentLength = contentSize.width;
|
||||
|
||||
Reference in New Issue
Block a user