[Batch Fetching] Add ASBatchFetchingDelegate (#281)

* Add ASBatchFetchingDelegate
- In addition to checking remaining leading screens, ASBatchFetching now also calculates a remaining time and consults its delegate if needed.
- The delegate can override the decision of ASBatchFetching, for example based on remaining time and average time of past batch requests.

* Fix up tests

* Update CHANGELOG
This commit is contained in:
Huy Nguyen 2017-05-17 13:26:30 +01:00 committed by GitHub
parent 432018cfdc
commit 8c45eaefce
12 changed files with 160 additions and 32 deletions

View File

@ -427,6 +427,8 @@
E5B077FF1E69F4EB00C24B5B /* ASElementMap.h in Headers */ = {isa = PBXBuildFile; fileRef = E5B077FD1E69F4EB00C24B5B /* ASElementMap.h */; settings = {ATTRIBUTES = (Public, ); }; };
E5B078001E69F4EB00C24B5B /* ASElementMap.m in Sources */ = {isa = PBXBuildFile; fileRef = E5B077FE1E69F4EB00C24B5B /* ASElementMap.m */; };
E5B5B9D11E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = E5B5B9D01E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h */; };
E5C347B11ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E5C347B01ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h */; };
E5C347B31ECB40AA00EC4BE4 /* ASTableNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = E5C347B21ECB40AA00EC4BE4 /* ASTableNode+Beta.h */; };
E5E281741E71C833006B67C2 /* ASCollectionLayoutState.h in Headers */ = {isa = PBXBuildFile; fileRef = E5E281731E71C833006B67C2 /* ASCollectionLayoutState.h */; settings = {ATTRIBUTES = (Public, ); }; };
E5E281761E71C845006B67C2 /* ASCollectionLayoutState.m in Sources */ = {isa = PBXBuildFile; fileRef = E5E281751E71C845006B67C2 /* ASCollectionLayoutState.m */; };
F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F711994D1D20C21100568860 /* ASDisplayNodeExtrasTests.m */; };
@ -883,6 +885,8 @@
E5B077FD1E69F4EB00C24B5B /* ASElementMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASElementMap.h; sourceTree = "<group>"; };
E5B077FE1E69F4EB00C24B5B /* ASElementMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASElementMap.m; sourceTree = "<group>"; };
E5B5B9D01E9BAD9800A6B726 /* ASCollectionLayoutContext+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionLayoutContext+Private.h"; sourceTree = "<group>"; };
E5C347B01ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASBatchFetchingDelegate.h; sourceTree = "<group>"; };
E5C347B21ECB40AA00EC4BE4 /* ASTableNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASTableNode+Beta.h"; sourceTree = "<group>"; };
E5E281731E71C833006B67C2 /* ASCollectionLayoutState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCollectionLayoutState.h; sourceTree = "<group>"; };
E5E281751E71C845006B67C2 /* ASCollectionLayoutState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCollectionLayoutState.m; sourceTree = "<group>"; };
EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AsyncDisplayKitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1051,6 +1055,7 @@
68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */,
B0F880581BEAEC7500D17647 /* ASTableNode.h */,
9CFFC6C11CCAC768006A6476 /* ASTableNode.mm */,
E5C347B21ECB40AA00EC4BE4 /* ASTableNode+Beta.h */,
055F1A3219ABD3E3004DAFF1 /* ASTableView.h */,
055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */,
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */,
@ -1187,6 +1192,7 @@
054963481A1EA066000F8E56 /* ASBasicImageDownloader.mm */,
299DA1A71A828D2900162D41 /* ASBatchContext.h */,
299DA1A81A828D2900162D41 /* ASBatchContext.mm */,
E5C347B01ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h */,
68C215561DE10D330019C4BC /* ASCollectionViewLayoutInspector.h */,
68C215571DE10D330019C4BC /* ASCollectionViewLayoutInspector.m */,
205F0E1B1B373A2C007741D0 /* ASCollectionViewLayoutController.h */,
@ -1687,6 +1693,7 @@
68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */,
CCCCCCE11EC3EF060087FE10 /* ASTextUtilities.h in Headers */,
B350624B1B010EFD0018CF92 /* _ASPendingState.h in Headers */,
E5C347B11ECB3D9200EC4BE4 /* ASBatchFetchingDelegate.h in Headers */,
CC54A81C1D70079800296A24 /* ASDispatch.h in Headers */,
B350624D1B010EFD0018CF92 /* _ASScopeTimer.h in Headers */,
CC0F88631E4281E700576FED /* ASSupplementaryNodeSource.h in Headers */,
@ -1768,6 +1775,7 @@
34EFC76E1B701CF400AD841F /* ASRatioLayoutSpec.h in Headers */,
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */,
CCA282C41E9EAE630037E8B7 /* ASLayerBackingTipProvider.h in Headers */,
E5C347B31ECB40AA00EC4BE4 /* ASTableNode+Beta.h in Headers */,
6900C5F41E8072DA00BCD75C /* ASImageNode+Private.h in Headers */,
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */,
B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */,

View File

@ -23,3 +23,5 @@
- [ASCollectionNode] Fixed conversion of item index paths between node & view. [Adlai Holler](https://github.com/Adlai-Holler) [#262](https://github.com/TextureGroup/Texture/pull/262)
- [Layout] Extract layout implementation code into it's own subcategories [Michael Schneider] (https://github.com/maicki)[#272](https://github.com/TextureGroup/Texture/pull/272)
- [Fix] Fix a potential crash when cell nodes that need layout are deleted during the same runloop. [Adlai Holler](https://github.com/Adlai-Holler) [#279](https://github.com/TextureGroup/Texture/pull/279)
- [Batch fetching] Add ASBatchFetchingDelegate that takes scroll velocity and remaining time into account [Huy Nguyen](https://github.com/nguyenhuy) [#281](https://github.com/TextureGroup/Texture/pull/281)

View File

@ -17,7 +17,7 @@
#import <AsyncDisplayKit/ASCollectionNode.h>
@protocol ASCollectionViewLayoutFacilitatorProtocol, ASCollectionLayoutDelegate;
@protocol ASCollectionViewLayoutFacilitatorProtocol, ASCollectionLayoutDelegate, ASBatchFetchingDelegate;
@class ASElementMap;
NS_ASSUME_NONNULL_BEGIN
@ -38,6 +38,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, readonly, nullable) id<ASCollectionLayoutDelegate> layoutDelegate;
@property (nonatomic, weak) id<ASBatchFetchingDelegate> batchFetchingDelegate;
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(nullable id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator;
- (instancetype)initWithLayoutDelegate:(id<ASCollectionLayoutDelegate>)layoutDelegate layoutFacilitator:(nullable id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator;

View File

@ -111,6 +111,7 @@
{
ASDN::RecursiveMutex _environmentStateLock;
Class _collectionViewClass;
id<ASBatchFetchingDelegate> _batchFetchingDelegate;
}
@property (nonatomic) _ASCollectionPendingState *pendingState;
@end
@ -442,6 +443,16 @@
return nil;
}
- (void)setBatchFetchingDelegate:(id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
_batchFetchingDelegate = batchFetchingDelegate;
}
- (id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
return _batchFetchingDelegate;
}
#pragma mark - Range Tuning
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType

View File

@ -22,6 +22,7 @@
#import <AsyncDisplayKit/ASCollectionElement.h>
#import <AsyncDisplayKit/ASCollectionInternal.h>
#import <AsyncDisplayKit/ASCollectionLayout.h>
#import <AsyncDisplayKit/ASCollectionNode+Beta.h>
#import <AsyncDisplayKit/ASCollectionViewLayoutController.h>
#import <AsyncDisplayKit/ASCollectionViewLayoutFacilitatorProtocol.h>
#import <AsyncDisplayKit/ASCollectionViewFlowLayoutInspector.h>
@ -1347,7 +1348,7 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
if (targetContentOffset != NULL) {
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
[self _beginBatchFetchingIfNeededWithContentOffset:*targetContentOffset];
[self _beginBatchFetchingIfNeededWithContentOffset:*targetContentOffset velocity:velocity];
}
if (_asyncDelegateFlags.scrollViewWillEndDragging) {
@ -1521,6 +1522,10 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
}
}
- (id<ASBatchFetchingDelegate>)batchFetchingDelegate{
return self.collectionNode.batchFetchingDelegate;
}
- (void)_scheduleCheckForBatchFetchingForNumberOfChanges:(NSUInteger)changes
{
// Prevent fetching will continually trigger in a loop after reaching end of content and no new content was provided
@ -1542,12 +1547,12 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
return;
}
[self _beginBatchFetchingIfNeededWithContentOffset:self.contentOffset];
[self _beginBatchFetchingIfNeededWithContentOffset:self.contentOffset velocity:CGPointZero];
}
- (void)_beginBatchFetchingIfNeededWithContentOffset:(CGPoint)contentOffset
- (void)_beginBatchFetchingIfNeededWithContentOffset:(CGPoint)contentOffset velocity:(CGPoint)velocity
{
if (ASDisplayShouldFetchBatchForScrollView(self, self.scrollDirection, self.scrollableDirections, contentOffset)) {
if (ASDisplayShouldFetchBatchForScrollView(self, self.scrollDirection, self.scrollableDirections, contentOffset, velocity)) {
[self _beginBatchFetching];
}
}

25
Source/ASTableNode+Beta.h Normal file
View File

@ -0,0 +1,25 @@
//
// ASTableNode+Beta.h
// Texture
//
// Copyright (c) 2017-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/ASTableNode.h>
@protocol ASBatchFetchingDelegate;
NS_ASSUME_NONNULL_BEGIN
@interface ASTableNode (Beta)
@property (nonatomic, weak) id<ASBatchFetchingDelegate> batchFetchingDelegate;
@end
NS_ASSUME_NONNULL_END

View File

@ -16,6 +16,8 @@
//
#import <AsyncDisplayKit/ASTableNode.h>
#import <AsyncDisplayKit/ASTableNode+Beta.h>
#import <AsyncDisplayKit/ASCollectionElement.h>
#import <AsyncDisplayKit/ASElementMap.h>
#import <AsyncDisplayKit/ASTableViewInternal.h>
@ -68,6 +70,7 @@
@interface ASTableNode ()
{
ASDN::RecursiveMutex _environmentStateLock;
id<ASBatchFetchingDelegate> _batchFetchingDelegate;
}
@property (nonatomic, strong) _ASTablePendingState *pendingState;
@ -381,6 +384,16 @@
}
}
- (void)setBatchFetchingDelegate:(id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
_batchFetchingDelegate = batchFetchingDelegate;
}
- (id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
return _batchFetchingDelegate;
}
#pragma mark ASRangeControllerUpdateRangeProtocol
- (void)updateCurrentRangeWithMode:(ASLayoutRangeMode)rangeMode

View File

@ -30,7 +30,7 @@
#import <AsyncDisplayKit/ASElementMap.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASTableNode.h>
#import <AsyncDisplayKit/ASTableNode+Beta.h>
#import <AsyncDisplayKit/ASRangeController.h>
#import <AsyncDisplayKit/ASEqualityHelpers.h>
#import <AsyncDisplayKit/ASTableLayoutController.h>
@ -1225,7 +1225,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
if (targetContentOffset != NULL) {
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
[self _beginBatchFetchingIfNeededWithContentOffset:*targetContentOffset];
[self _beginBatchFetchingIfNeededWithContentOffset:*targetContentOffset velocity:velocity];
}
if (_asyncDelegateFlags.scrollViewWillEndDragging) {
@ -1381,6 +1381,11 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
}
}
- (id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
return self.tableNode.batchFetchingDelegate;
}
- (void)_scheduleCheckForBatchFetchingForNumberOfChanges:(NSUInteger)changes
{
// Prevent fetching will continually trigger in a loop after reaching end of content and no new content was provided
@ -1402,12 +1407,12 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
return;
}
[self _beginBatchFetchingIfNeededWithContentOffset:self.contentOffset];
[self _beginBatchFetchingIfNeededWithContentOffset:self.contentOffset velocity:CGPointZero];
}
- (void)_beginBatchFetchingIfNeededWithContentOffset:(CGPoint)contentOffset
- (void)_beginBatchFetchingIfNeededWithContentOffset:(CGPoint)contentOffset velocity:(CGPoint)velocity
{
if (ASDisplayShouldFetchBatchForScrollView(self, self.scrollDirection, ASScrollDirectionVerticalDirections, contentOffset)) {
if (ASDisplayShouldFetchBatchForScrollView(self, self.scrollDirection, ASScrollDirectionVerticalDirections, contentOffset, velocity)) {
[self _beginBatchFetching];
}
}

View File

@ -0,0 +1,27 @@
//
// ASBatchFetchingDelegate.h
// Texture
//
// Copyright (c) 2017-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <UIKit/UIKit.h>
@protocol ASBatchFetchingDelegate <NSObject>
/**
* @abstract Determine if batch fetching should begin based on the remaining time.
* If the delegate doesn't have enough information to confidently decide, it can take the given hint.
*
* @param remainingTime The amount of time left for user to reach the end of the scroll view's content.
*
* @param hint A hint for the delegate to fallback to.
*/
- (BOOL)shouldFetchBatchWithRemainingTime:(NSTimeInterval)remainingTime hint:(BOOL)hint;
@end

View File

@ -21,13 +21,17 @@
ASDISPLAYNODE_EXTERN_C_BEGIN
NS_ASSUME_NONNULL_BEGIN
@class ASBatchContext;
@protocol ASBatchFetchingDelegate;
@protocol ASBatchFetchingScrollView <NSObject>
- (BOOL)canBatchFetch;
- (ASBatchContext *)batchContext;
- (CGFloat)leadingScreensForBatching;
- (nullable id<ASBatchFetchingDelegate>)batchFetchingDelegate;
@end
@ -39,9 +43,14 @@ ASDISPLAYNODE_EXTERN_C_BEGIN
@param scrollDirection The current scrolling direction of the scroll view.
@param scrollableDirections The possible scrolling directions of the scroll view.
@param contentOffset The offset that the scrollview will scroll to.
@param velocity The velocity of the scroll view (in points) at the moment the touch was released.
@return Whether or not the current state should proceed with batch fetching.
*/
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView, ASScrollDirection scrollDirection, ASScrollDirection scrollableDirections, CGPoint contentOffset);
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView,
ASScrollDirection scrollDirection,
ASScrollDirection scrollableDirections,
CGPoint contentOffset,
CGPoint velocity);
/**
@ -54,6 +63,8 @@ BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollVi
@param targetOffset The offset that the scrollview will scroll to.
@param leadingScreens How many screens in the remaining distance will trigger batch fetching.
@param visible Whether the view is visible or not.
@param velocity The velocity of the scroll view (in points) at the moment the touch was released.
@param delegate The delegate to be consulted if needed.
@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.
@ -65,6 +76,9 @@ extern BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
CGSize contentSize,
CGPoint targetOffset,
CGFloat leadingScreens,
BOOL visible);
BOOL visible,
CGPoint velocity,
_Nullable id<ASBatchFetchingDelegate> delegate);
NS_ASSUME_NONNULL_END
ASDISPLAYNODE_EXTERN_C_END

View File

@ -17,8 +17,13 @@
#import <AsyncDisplayKit/ASBatchFetching.h>
#import <AsyncDisplayKit/ASBatchContext.h>
#import <AsyncDisplayKit/ASBatchFetchingDelegate.h>
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView, ASScrollDirection scrollDirection, ASScrollDirection scrollableDirections, CGPoint contentOffset)
BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollView> *scrollView,
ASScrollDirection scrollDirection,
ASScrollDirection scrollableDirections,
CGPoint contentOffset,
CGPoint velocity)
{
// Don't fetch if the scroll view does not allow
if (![scrollView canBatchFetch]) {
@ -30,8 +35,9 @@ BOOL ASDisplayShouldFetchBatchForScrollView(UIScrollView<ASBatchFetchingScrollVi
CGRect bounds = scrollView.bounds;
CGSize contentSize = scrollView.contentSize;
CGFloat leadingScreens = scrollView.leadingScreensForBatching;
id<ASBatchFetchingDelegate> delegate = scrollView.batchFetchingDelegate;
BOOL visible = (scrollView.window != nil);
return ASDisplayShouldFetchBatchForContext(context, scrollDirection, scrollableDirections, bounds, contentSize, contentOffset, leadingScreens, visible);
return ASDisplayShouldFetchBatchForContext(context, scrollDirection, scrollableDirections, bounds, contentSize, contentOffset, leadingScreens, visible, velocity, delegate);
}
BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
@ -41,7 +47,9 @@ BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
CGSize contentSize,
CGPoint targetOffset,
CGFloat leadingScreens,
BOOL visible)
BOOL visible,
CGPoint velocity,
id<ASBatchFetchingDelegate> delegate)
{
// Do not allow fetching if a batch is already in-flight and hasn't been completed or cancelled
if ([context isFetching]) {
@ -53,16 +61,18 @@ BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
return NO;
}
CGFloat viewLength, offset, contentLength;
CGFloat viewLength, offset, contentLength, velocityLength;
if (ASScrollDirectionContainsVerticalDirection(scrollableDirections)) {
viewLength = bounds.size.height;
offset = targetOffset.y;
contentLength = contentSize.height;
velocityLength = velocity.y;
} else { // horizontal / right
viewLength = bounds.size.width;
offset = targetOffset.x;
contentLength = contentSize.width;
velocityLength = velocity.x;
}
BOOL hasSmallContent = contentLength < viewLength;
@ -84,6 +94,12 @@ BOOL ASDisplayShouldFetchBatchForContext(ASBatchContext *context,
CGFloat triggerDistance = viewLength * leadingScreens;
CGFloat remainingDistance = contentLength - viewLength - offset;
return remainingDistance <= triggerDistance;
BOOL result = remainingDistance <= triggerDistance;
if (delegate != nil && (velocityLength = round(fabs(velocityLength))) > 0) {
NSTimeInterval remainingTime = remainingDistance / (velocityLength * 1000);
result = [delegate shouldFetchBatchWithRemainingTime:remainingTime hint:result];
}
return result;
}

View File

@ -38,26 +38,26 @@
- (void)testBatchNullState {
ASBatchContext *context = [[ASBatchContext alloc] init];
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, CGRectZero, CGSizeZero, CGPointZero, 0.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, CGRectZero, CGSizeZero, CGPointZero, 0.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == NO, @"Should not fetch in the null state");
}
- (void)testBatchAlreadyFetching {
ASBatchContext *context = [[ASBatchContext alloc] init];
[context beginBatchFetching];
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == NO, @"Should not fetch when context is already fetching");
}
- (void)testUnsupportedScrollDirections {
ASBatchContext *context = [[ASBatchContext alloc] init];
BOOL fetchRight = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionRight, ASScrollDirectionHorizontalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES);
BOOL fetchRight = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionRight, ASScrollDirectionHorizontalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES, CGPointZero, nil);
XCTAssert(fetchRight == YES, @"Should fetch for scrolling right");
BOOL fetchDown = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES);
BOOL fetchDown = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES, CGPointZero, nil);
XCTAssert(fetchDown == YES, @"Should fetch for scrolling down");
BOOL fetchUp = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionUp, ASScrollDirectionVerticalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES);
BOOL fetchUp = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionUp, ASScrollDirectionVerticalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES, CGPointZero, nil);
XCTAssert(fetchUp == NO, @"Should not fetch for scrolling up");
BOOL fetchLeft = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionLeft, ASScrollDirectionHorizontalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES);
BOOL fetchLeft = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionLeft, ASScrollDirectionHorizontalDirections, PASSING_RECT, PASSING_SIZE, PASSING_POINT, 1.0, YES, CGPointZero, nil);
XCTAssert(fetchLeft == NO, @"Should not fetch for scrolling left");
}
@ -65,7 +65,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// scroll to 1-screen top offset, height is 1 screen, so bottom is 1 screen away from end of content
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 3.0), VERTICAL_OFFSET(screen * 1.0), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 3.0), VERTICAL_OFFSET(screen * 1.0), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == YES, @"Fetch should begin when vertically scrolling to exactly 1 leading screen away");
}
@ -73,7 +73,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// 3 screens of content, scroll only 1/2 of one screen
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 3.0), VERTICAL_OFFSET(screen * 0.5), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 3.0), VERTICAL_OFFSET(screen * 0.5), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == NO, @"Fetch should not begin when vertically scrolling less than the leading distance away");
}
@ -81,7 +81,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// 3 screens of content, top offset to 3-screens, height 1 screen, so its 1 screen past the leading
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 3.0), VERTICAL_OFFSET(screen * 3.0), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 3.0), VERTICAL_OFFSET(screen * 3.0), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == YES, @"Fetch should begin when vertically scrolling past the content size");
}
@ -89,7 +89,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// scroll to 1-screen left offset, width is 1 screen, so right is 1 screen away from end of content
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionRight, ASScrollDirectionVerticalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 3.0), HORIZONTAL_OFFSET(screen * 1.0), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionRight, ASScrollDirectionVerticalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 3.0), HORIZONTAL_OFFSET(screen * 1.0), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == YES, @"Fetch should begin when horizontally scrolling to exactly 1 leading screen away");
}
@ -97,7 +97,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// 3 screens of content, scroll only 1/2 of one screen
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionLeft, ASScrollDirectionHorizontalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 3.0), HORIZONTAL_OFFSET(screen * 0.5), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionLeft, ASScrollDirectionHorizontalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 3.0), HORIZONTAL_OFFSET(screen * 0.5), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == NO, @"Fetch should not begin when horizontally scrolling less than the leading distance away");
}
@ -105,7 +105,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// 3 screens of content, left offset to 3-screens, width 1 screen, so its 1 screen past the leading
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionHorizontalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 3.0), HORIZONTAL_OFFSET(screen * 3.0), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionHorizontalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 3.0), HORIZONTAL_OFFSET(screen * 3.0), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == YES, @"Fetch should begin when vertically scrolling past the content size");
}
@ -113,7 +113,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// when the content size is < screen size, the target offset will always be 0
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 0.5), VERTICAL_OFFSET(0.0), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionDown, ASScrollDirectionVerticalDirections, VERTICAL_RECT(screen), VERTICAL_SIZE(screen * 0.5), VERTICAL_OFFSET(0.0), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == YES, @"Fetch should begin when the target is 0 and the content size is smaller than the scree");
}
@ -121,7 +121,7 @@
CGFloat screen = 1.0;
ASBatchContext *context = [[ASBatchContext alloc] init];
// when the content size is < screen size, the target offset will always be 0
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionRight, ASScrollDirectionHorizontalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 0.5), HORIZONTAL_OFFSET(0.0), 1.0, YES);
BOOL shouldFetch = ASDisplayShouldFetchBatchForContext(context, ASScrollDirectionRight, ASScrollDirectionHorizontalDirections, HORIZONTAL_RECT(screen), HORIZONTAL_SIZE(screen * 0.5), HORIZONTAL_OFFSET(0.0), 1.0, YES, CGPointZero, nil);
XCTAssert(shouldFetch == YES, @"Fetch should begin when the target is 0 and the content size is smaller than the scree");
}