Merge pull request #1015 from facebook/CollectionTableLayers

Use _ASDisplayLayer for both ASTableView and ASCollectionView.  zeroContentInsets to fix UIKit.
This commit is contained in:
appleguy
2015-12-29 23:10:43 -08:00
5 changed files with 62 additions and 25 deletions

View File

@@ -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

View File

@@ -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};
@@ -113,6 +114,12 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
@implementation ASCollectionView
// Using _ASDisplayLayer ensures things like -layout are properly forwarded to ASCollectionNode.
+ (Class)layerClass
{
return [_ASDisplayLayer class];
}
#pragma mark -
#pragma mark Lifecycle.
@@ -221,7 +228,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
- (void)reloadDataWithCompletion:(void (^)())completion
{
ASDisplayNodeAssert(self.asyncDelegate, @"ASCollectionView's asyncDelegate property must be set.");
ASPerformBlockOnMainThread(^{
_superIsPendingDataLoad = YES;
[super reloadData];
@@ -557,6 +563,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
- (void)layoutSubviews
{
if (_zeroContentInsets) {
self.contentInset = UIEdgeInsetsZero;
}
if (! CGSizeEqualToSize(_maxSizeForNodesConstrainedSize, self.bounds.size)) {
_maxSizeForNodesConstrainedSize = self.bounds.size;

View File

@@ -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.

View File

@@ -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;
@@ -46,25 +47,6 @@
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];
@@ -77,6 +59,11 @@
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];
@@ -95,13 +82,14 @@
- (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];
}
@@ -110,4 +98,25 @@
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

View File

@@ -18,6 +18,7 @@
#import "ASLayout.h"
#import "ASLayoutController.h"
#import "ASRangeController.h"
#import "_ASDisplayLayer.h"
#import <CoreFoundation/CoreFoundation.h>
@@ -120,6 +121,12 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
@implementation ASTableView
// Using _ASDisplayLayer ensures things like -layout are properly forwarded to ASTableNode.
+ (Class)layerClass
{
return [_ASDisplayLayer class];
}
+ (Class)dataControllerClass
{
return [ASChangeSetDataController class];
@@ -280,7 +287,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
- (void)reloadDataWithCompletion:(void (^)())completion
{
ASDisplayNodeAssert(self.asyncDelegate, @"ASTableView's asyncDelegate property must be set.");
ASPerformBlockOnMainThread(^{
[super reloadData];
});