mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-12 17:30:34 +00:00
Move most of the batch fetching logic to a central place for ASTableView and ASCollectionView usage
This commit is contained in:
parent
40fe1f3ac7
commit
24ca09ee6c
@ -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,58 +737,14 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Batch Fetching
|
||||
#pragma mark - Batch Fetching
|
||||
|
||||
- (void)_checkForBatchFetching
|
||||
- (ASBatchContext *)batchContext
|
||||
{
|
||||
// Dragging will be handled in scrollViewWillEndDragging:withVelocity:targetContentOffset:
|
||||
if ([self isDragging] || [self isTracking] || ![self _shouldBatchFetch]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we should batch fetch
|
||||
if (ASDisplayShouldFetchBatchForContext(_batchContext, [self scrollableDirections], self.bounds, self.contentSize, self.contentOffset, _leadingScreensForBatching)) {
|
||||
[self _beginBatchFetching];
|
||||
}
|
||||
return _batchContext;
|
||||
}
|
||||
|
||||
- (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) {
|
||||
[self _handleBatchFetchScrollingToOffset:*targetContentOffset];
|
||||
}
|
||||
|
||||
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
|
||||
[_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
|
||||
}
|
||||
}
|
||||
|
||||
- (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:)];
|
||||
@ -762,25 +755,41 @@ 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 UITableView 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)) {
|
||||
[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];
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[_asyncDelegate collectionView:self willBeginBatchFetchWithContext:_batchContext];
|
||||
});
|
||||
if ([_asyncDelegate respondsToSelector:@selector(collectionView:willBeginBatchFetchWithContext:)]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[_asyncDelegate collectionView:self willBeginBatchFetchWithContext:_batchContext];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -972,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];
|
||||
@ -993,11 +1005,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}];
|
||||
} else {
|
||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:indexPaths batched:NO];
|
||||
ASPerformBlockWithoutAnimationCompletion(YES, ^{
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super insertItemsAtIndexPaths:indexPaths];
|
||||
}, ^{
|
||||
|
||||
});
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1017,6 +1028,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:indexPaths batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super deleteItemsAtIndexPaths:indexPaths];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@ -1037,6 +1049,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditSectionsAtIndexSet:indexSet batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super insertSections:indexSet];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@ -1057,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,75 +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)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;
|
||||
}
|
||||
|
||||
- (ASScrollDirection)_scrollDirectionForVelocity:(CGPoint)scrollVelocity
|
||||
{
|
||||
ASScrollDirection direction = ASScrollDirectionNone;
|
||||
ASScrollDirection scrollableDirections = [self scrollableDirections];
|
||||
|
||||
if (ASScrollDirectionContainsHorizontalDirection(scrollableDirections)) { // Can scroll horizontally.
|
||||
if (scrollVelocity.x < 0.0) {
|
||||
direction |= ASScrollDirectionRight;
|
||||
} else if (scrollVelocity.x > 0.0) {
|
||||
direction |= ASScrollDirectionLeft;
|
||||
}
|
||||
}
|
||||
if (ASScrollDirectionContainsVerticalDirection(scrollableDirections)) { // Can scroll vertically.
|
||||
if (scrollVelocity.y < 0.0) {
|
||||
direction |= ASScrollDirectionDown;
|
||||
} else if (scrollVelocity.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;
|
||||
@ -700,16 +629,22 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Batch Fetching
|
||||
|
||||
- (void)_checkForBatchFetching
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
// Dragging will be handled in scrollViewWillEndDragging:withVelocity:targetContentOffset:
|
||||
if ([self isDragging] || [self isTracking]) {
|
||||
return;
|
||||
// If a scroll happenes the current range mode needs to go to full
|
||||
ASInterfaceState interfaceState = [self interfaceStateForRangeController:_rangeController];
|
||||
if (ASInterfaceStateIncludesVisible(interfaceState)) {
|
||||
[_rangeController updateCurrentRangeWithMode:ASLayoutRangeModeFull];
|
||||
}
|
||||
|
||||
[self _beginBatchFetchingIfNeededForScrollDirection:[self scrollableDirections] contentOffset:self.contentOffset];
|
||||
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
|
||||
@ -721,7 +656,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
if (targetContentOffset != NULL) {
|
||||
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
|
||||
[self _beginBatchFetchingIfNeededForScrollDirection:[self scrollDirection] contentOffset:*targetContentOffset];
|
||||
[self _beginBatchFetchingIfNeededWithScrollView:self forScrollDirection:[self scrollDirection] contentOffset:*targetContentOffset];
|
||||
}
|
||||
|
||||
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
|
||||
@ -729,19 +664,69 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_beginBatchFetchingIfNeededForScrollDirection:(ASScrollDirection)scrollDirection contentOffset:(CGPoint)contentOffset
|
||||
|
||||
#pragma mark - Scroll Direction
|
||||
|
||||
- (ASScrollDirection)scrollDirection
|
||||
{
|
||||
if (![self _shouldBatchFetch]) {
|
||||
return;
|
||||
CGPoint scrollVelocity;
|
||||
if (self.isTracking) {
|
||||
scrollVelocity = [self.panGestureRecognizer velocityInView:self.superview];
|
||||
} else {
|
||||
scrollVelocity = _deceleratingVelocity;
|
||||
}
|
||||
|
||||
// Check if we should batch fetch
|
||||
if (ASDisplayShouldFetchBatchForContext(_batchContext, [self scrollableDirections], self.bounds, self.contentSize, self.contentOffset, _leadingScreensForBatching)) {
|
||||
[self _beginBatchFetching];
|
||||
}
|
||||
ASScrollDirection scrollDirection = [self _scrollDirectionForVelocity:scrollVelocity];
|
||||
return ASScrollDirectionApplyTransform(scrollDirection, self.transform);
|
||||
}
|
||||
|
||||
- (BOOL)_shouldBatchFetch
|
||||
- (ASScrollDirection)_scrollDirectionForVelocity:(CGPoint)scrollVelocity
|
||||
{
|
||||
ASScrollDirection direction = ASScrollDirectionNone;
|
||||
ASScrollDirection scrollableDirections = [self scrollableDirections];
|
||||
|
||||
if (ASScrollDirectionContainsHorizontalDirection(scrollableDirections)) { // Can scroll horizontally.
|
||||
if (scrollVelocity.x < 0.0) {
|
||||
direction |= ASScrollDirectionRight;
|
||||
} else if (scrollVelocity.x > 0.0) {
|
||||
direction |= ASScrollDirectionLeft;
|
||||
}
|
||||
}
|
||||
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:)];
|
||||
@ -752,12 +737,39 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_scheduleCheckForBatchFetching
|
||||
{
|
||||
// Push this to the next runloop to be sure the UITableView 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;
|
||||
}
|
||||
|
||||
[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
|
||||
{
|
||||
[_batchContext beginBatchFetching];
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[_asyncDelegate tableView:self willBeginBatchFetchWithContext:_batchContext];
|
||||
});
|
||||
if ([_asyncDelegate respondsToSelector:@selector(tableView:willBeginBatchFetchWithContext:)]) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[_asyncDelegate tableView:self willBeginBatchFetchWithContext:_batchContext];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ASRangeControllerDataSource
|
||||
@ -897,13 +909,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
// Push this to the next runloop to be sure the UITableView has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
});
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
|
||||
if (_automaticallyAdjustsContentOffset) {
|
||||
@ -923,10 +931,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
// Push this to the next runloop to be sure the UITableView has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
});
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
|
||||
if (_automaticallyAdjustsContentOffset) {
|
||||
@ -947,10 +952,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
// Push this to the next runloop to be sure the UITableView has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
});
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
}
|
||||
|
||||
@ -966,10 +968,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
// Push this to the next runloop to be sure the UITableView has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
});
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -10,27 +10,26 @@
|
||||
|
||||
#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.
|
||||
@param context The batch fetching context that contains knowledge about in-flight fetches.
|
||||
@param scrollDirection The current scrolling direction of the scroll view.
|
||||
@param bounds The bounds of the scrollview.
|
||||
@param contentSize The content size of the scrollview.
|
||||
@param targetOffset The offset that the scrollview will scroll to.
|
||||
@param leadingScreens How many screens in the remaining distance will trigger batch fetching.
|
||||
@return Whether or not the current state should proceed with batch fetching.
|
||||
@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.
|
||||
*/
|
||||
extern BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
|
||||
ASScrollDirection scrollDirection,
|
||||
CGRect bounds,
|
||||
CGSize contentSize,
|
||||
CGPoint targetOffset,
|
||||
CGFloat leadingScreens);
|
||||
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView, ASScrollDirection scrollDirection, CGPoint contentOffset);
|
||||
|
||||
ASDISPLAYNODE_EXTERN_C_END
|
||||
|
||||
@ -8,23 +8,31 @@
|
||||
|
||||
#import "ASBatchFetching.h"
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
// 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)
|
||||
// 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;
|
||||
}
|
||||
@ -33,11 +41,11 @@ BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
|
||||
|
||||
if (ASScrollDirectionContainsDown(scrollDirection)) {
|
||||
viewLength = bounds.size.height;
|
||||
offset = targetOffset.y;
|
||||
offset = contentOffset.y;
|
||||
contentLength = contentSize.height;
|
||||
} else { // horizontal / right
|
||||
viewLength = bounds.size.width;
|
||||
offset = targetOffset.x;
|
||||
offset = contentOffset.x;
|
||||
contentLength = contentSize.width;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user