Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AsyncDisplayKit/ASCollectionView.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,16 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)clearFetchedData;

/**
* Forces the .contentInset to be UIEdgeInsetsZero.
*
* @discussion By default, UIKit sets the top inset to the navigation bar height, even for horizontally
* scrolling views. This can only be disabled by setting a property on the containing UIViewController,
* automaticallyAdjustsScrollViewInsets, which may not be accessible. ASPagerNode uses this to ensure
* its flow layout behaves predictably and does not log undefined layout warnings.
*/
@property (nonatomic) BOOL zeroContentInsets;

@end


Expand Down
12 changes: 11 additions & 1 deletion AsyncDisplayKit/ASCollectionView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import "ASInternalHelpers.h"
#import "ASRangeController.h"
#import "UICollectionViewLayout+ASConvenience.h"
#import "_ASDisplayLayer.h"

static const NSUInteger kASCollectionViewAnimationNone = UITableViewRowAnimationNone;
static const ASSizeRange kInvalidSizeRange = {CGSizeZero, CGSizeZero};
Expand Down Expand Up @@ -113,6 +114,12 @@ - (instancetype)_initWithCollectionView:(ASCollectionView *)collectionView;

@implementation ASCollectionView

// Using _ASDisplayLayer ensures things like -layout are properly forwarded to ASCollectionNode.
+ (Class)layerClass
{
return [_ASDisplayLayer class];
}

#pragma mark -
#pragma mark Lifecycle.

Expand Down Expand Up @@ -221,7 +228,6 @@ - (ASCollectionViewFlowLayoutInspector *)flowLayoutInspector

- (void)reloadDataWithCompletion:(void (^)())completion
{
ASDisplayNodeAssert(self.asyncDelegate, @"ASCollectionView's asyncDelegate property must be set.");
ASPerformBlockOnMainThread(^{
_superIsPendingDataLoad = YES;
[super reloadData];
Expand Down Expand Up @@ -557,6 +563,10 @@ - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(

- (void)layoutSubviews
{
if (_zeroContentInsets) {
self.contentInset = UIEdgeInsetsZero;
}

if (! CGSizeEqualToSize(_maxSizeForNodesConstrainedSize, self.bounds.size)) {
_maxSizeForNodesConstrainedSize = self.bounds.size;

Expand Down
2 changes: 2 additions & 0 deletions AsyncDisplayKit/ASPagerNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
- (ASCellNode *)pagerNode:(ASPagerNode *)pagerNode nodeAtIndex:(NSInteger)index;
@end

// WARNING: ASPagerNode is new in AsyncDisplayKit 1.9.4 and not yet widely tested.
// Details of its API or behavior may change in future releases
@interface ASPagerNode : ASCollectionNode

// Configures a default horizontal, paging flow layout with 0 inter-item spacing.
Expand Down
55 changes: 32 additions & 23 deletions AsyncDisplayKit/ASPagerNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#import "ASDelegateProxy.h"
#import "ASDisplayNode+Subclasses.h"

@interface ASPagerNode () <ASCollectionDataSource, ASCollectionViewDelegateFlowLayout, ASDelegateProxyInterceptor> {
@interface ASPagerNode () <ASCollectionDataSource, ASCollectionViewDelegateFlowLayout, ASDelegateProxyInterceptor>
{
UICollectionViewFlowLayout *_flowLayout;
ASPagerNodeProxy *_proxy;
id <ASPagerNodeDataSource> _pagerDataSource;
Expand Down Expand Up @@ -46,25 +47,6 @@ - (instancetype)initWithFlowLayout:(UICollectionViewFlowLayout *)flowLayout
return self;
}

- (void)setDataSource:(id <ASPagerNodeDataSource>)pagerDataSource
{
if (pagerDataSource != _pagerDataSource) {
_pagerDataSource = pagerDataSource;
_proxy = pagerDataSource ? [[ASPagerNodeProxy alloc] initWithTarget:pagerDataSource interceptor:self] : nil;
super.dataSource = (id <ASCollectionDataSource>)_proxy;
}
}

- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy
{
[self setDataSource:nil];
}

- (id <ASPagerNodeDataSource>)dataSource
{
return _pagerDataSource;
}

- (void)didLoad
{
[super didLoad];
Expand All @@ -77,6 +59,11 @@ - (void)didLoad
cv.showsHorizontalScrollIndicator = NO;
cv.scrollsToTop = NO;

// Zeroing contentInset is important, as UIKit will set the top inset for the navigation bar even though
// our view is only horizontally scrollable. This causes UICollectionViewFlowLayout to log a warning.
// From here we cannot disable this directly (UIViewController's automaticallyAdjustsScrollViewInsets).
cv.zeroContentInsets = YES;

ASRangeTuningParameters preloadParams = { .leadingBufferScreenfuls = 2.0, .trailingBufferScreenfuls = 2.0 };
ASRangeTuningParameters renderParams = { .leadingBufferScreenfuls = 1.0, .trailingBufferScreenfuls = 1.0 };
[self setTuningParameters:preloadParams forRangeType:ASLayoutRangeTypePreload];
Expand All @@ -95,13 +82,14 @@ - (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated

- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath
{
ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load paging nodes");
return [_pagerDataSource pagerNode:self nodeAtIndex:indexPath.item];
ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load nodes to display");
ASCellNode *pageNode = [_pagerDataSource pagerNode:self nodeAtIndex:indexPath.item];
return pageNode;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load paging nodes");
ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load nodes to display");
return [_pagerDataSource numberOfPagesInPagerNode:self];
}

Expand All @@ -110,4 +98,25 @@ - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSize
return ASSizeRangeMake(CGSizeZero, self.view.bounds.size);
}

#pragma mark - Data Source Proxy

- (id <ASPagerNodeDataSource>)dataSource
{
return _pagerDataSource;
}

- (void)setDataSource:(id <ASPagerNodeDataSource>)pagerDataSource
{
if (pagerDataSource != _pagerDataSource) {
_pagerDataSource = pagerDataSource;
_proxy = pagerDataSource ? [[ASPagerNodeProxy alloc] initWithTarget:pagerDataSource interceptor:self] : nil;
super.dataSource = (id <ASCollectionDataSource>)_proxy;
}
}

- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy
{
[self setDataSource:nil];
}

@end
8 changes: 7 additions & 1 deletion AsyncDisplayKit/ASTableView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#import "ASLayout.h"
#import "ASLayoutController.h"
#import "ASRangeController.h"
#import "_ASDisplayLayer.h"

#import <CoreFoundation/CoreFoundation.h>

Expand Down Expand Up @@ -120,6 +121,12 @@ @interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegat

@implementation ASTableView

// Using _ASDisplayLayer ensures things like -layout are properly forwarded to ASTableNode.
+ (Class)layerClass
{
return [_ASDisplayLayer class];
}

+ (Class)dataControllerClass
{
return [ASChangeSetDataController class];
Expand Down Expand Up @@ -280,7 +287,6 @@ - (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy

- (void)reloadDataWithCompletion:(void (^)())completion
{
ASDisplayNodeAssert(self.asyncDelegate, @"ASTableView's asyncDelegate property must be set.");
ASPerformBlockOnMainThread(^{
[super reloadData];
});
Expand Down