mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
[ASCollectionView / ASPagerNode] Move constrainedSizeForNodeAtIndexPath from the DataSource to the Delegate (#2065)
* Move constrainedSizeForNodeAtIndexPath from the DataSource to the Delegate in ASCollectionView and ASPagerNode * Fix ASPagerNode declaration of dataSource and delegate As ASPagerDataSource does not inherit from ASCollectionDataSource it's not possible to declare it as property. * Update comment
This commit is contained in:
committed by
Adlai Holler
parent
2c9e51e8f7
commit
93be894e0c
@@ -400,17 +400,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
/**
|
||||
* Provides the constrained size range for measuring the node at the index path.
|
||||
*
|
||||
* @param collectionView The sender.
|
||||
*
|
||||
* @param indexPath The index path of the node.
|
||||
*
|
||||
* @returns A constrained size range for layout the node at this index path.
|
||||
*/
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
/**
|
||||
* Indicator to lock the data source for data fetching in async mode.
|
||||
* We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistency or exception
|
||||
@@ -442,6 +431,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Provides the constrained size range for measuring the node at the index path.
|
||||
*
|
||||
* @param collectionView The sender.
|
||||
*
|
||||
* @param indexPath The index path of the node.
|
||||
*
|
||||
* @returns A constrained size range for layout the node at this index path.
|
||||
*/
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
/**
|
||||
* Informs the delegate that the collection view will add the node
|
||||
* at the given index path to the view hierarchy.
|
||||
|
||||
@@ -151,11 +151,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
} _asyncDelegateFlags;
|
||||
|
||||
struct {
|
||||
unsigned int asyncDataSourceConstrainedSizeForNode:1;
|
||||
unsigned int asyncDataSourceNodeForItemAtIndexPath:1;
|
||||
unsigned int asyncDataSourceNodeBlockForItemAtIndexPath:1;
|
||||
unsigned int asyncDataSourceNumberOfSectionsInCollectionView:1;
|
||||
unsigned int asyncDataSourceCollectionViewConstrainedSizeForNodeAtIndexPath:1;
|
||||
} _asyncDataSourceFlags;
|
||||
|
||||
struct {
|
||||
@@ -354,11 +352,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
_asyncDataSource = asyncDataSource;
|
||||
_proxyDataSource = [[ASCollectionViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self];
|
||||
|
||||
_asyncDataSourceFlags.asyncDataSourceConstrainedSizeForNode = [_asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||
_asyncDataSourceFlags.asyncDataSourceNodeForItemAtIndexPath = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeForItemAtIndexPath:)];
|
||||
_asyncDataSourceFlags.asyncDataSourceNodeBlockForItemAtIndexPath = [_asyncDataSource respondsToSelector:@selector(collectionView:nodeBlockForItemAtIndexPath:)];
|
||||
_asyncDataSourceFlags.asyncDataSourceNumberOfSectionsInCollectionView = [_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)];
|
||||
_asyncDataSourceFlags.asyncDataSourceCollectionViewConstrainedSizeForNodeAtIndexPath = [_asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||
|
||||
// Data-source must implement collectionView:nodeForItemAtIndexPath: or collectionView:nodeBlockForItemAtIndexPath:
|
||||
ASDisplayNodeAssertTrue(_asyncDataSourceFlags.asyncDataSourceNodeBlockForItemAtIndexPath || _asyncDataSourceFlags.asyncDataSourceNodeForItemAtIndexPath);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
@class ASPagerNode;
|
||||
@class ASPagerFlowLayout;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#define ASPagerNodeDataSource ASPagerDataSource
|
||||
@protocol ASPagerDataSource <NSObject>
|
||||
|
||||
@@ -52,6 +54,12 @@
|
||||
*/
|
||||
- (ASCellNodeBlock)pagerNode:(ASPagerNode *)pagerNode nodeBlockAtIndex:(NSInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
@protocol ASPagerDelegate <ASCollectionDelegate>
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Provides the constrained size range for measuring the node at the index path.
|
||||
*
|
||||
@@ -63,10 +71,6 @@
|
||||
|
||||
@end
|
||||
|
||||
@protocol ASPagerDelegate <ASCollectionDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@interface ASPagerNode : ASCollectionNode
|
||||
|
||||
/**
|
||||
@@ -82,14 +86,15 @@
|
||||
/**
|
||||
* Data Source is required, and uses a different protocol from ASCollectionNode.
|
||||
*/
|
||||
- (void)setDataSource:(id <ASPagerDataSource>)dataSource;
|
||||
- (id <ASPagerDataSource>)dataSource;
|
||||
- (void)setDataSource:(nullable id <ASPagerDataSource>)dataSource;
|
||||
- (nullable id <ASPagerDataSource>)dataSource;
|
||||
|
||||
/**
|
||||
* Delegate is optional, and uses the same protocol as ASCollectionNode.
|
||||
* Delegate is optional.
|
||||
* This includes UIScrollViewDelegate as well as most methods from UICollectionViewDelegate, like willDisplay...
|
||||
*/
|
||||
@property (nonatomic, weak) id <ASPagerDelegate> delegate;
|
||||
- (void)setDelegate:(nullable id <ASPagerDelegate>)delegate;
|
||||
- (nullable id <ASPagerDelegate>)delegate;
|
||||
|
||||
/**
|
||||
* The underlying ASCollectionView object.
|
||||
@@ -112,3 +117,5 @@
|
||||
- (ASCellNode *)nodeForPageAtIndex:(NSInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -15,18 +15,23 @@
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
#import "ASPagerFlowLayout.h"
|
||||
|
||||
@interface ASPagerNode () <ASCollectionDataSource, ASCollectionViewDelegateFlowLayout, ASDelegateProxyInterceptor>
|
||||
@interface ASPagerNode () <ASCollectionDataSource, ASCollectionDelegate, ASCollectionViewDelegateFlowLayout, ASDelegateProxyInterceptor>
|
||||
{
|
||||
ASPagerFlowLayout *_flowLayout;
|
||||
ASPagerNodeProxy *_proxy;
|
||||
__weak id <ASPagerNodeDataSource> _pagerDataSource;
|
||||
|
||||
__weak id <ASPagerDataSource> _pagerDataSource;
|
||||
ASPagerNodeProxy *_proxyDataSource;
|
||||
BOOL _pagerDataSourceImplementsNodeBlockAtIndex;
|
||||
BOOL _pagerDataSourceImplementsConstrainedSizeForNode;
|
||||
|
||||
__weak id <ASPagerDelegate> _pagerDelegate;
|
||||
ASPagerNodeProxy *_proxyDelegate;
|
||||
BOOL _pagerDelegateImplementsConstrainedSizeForNode;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASPagerNode
|
||||
|
||||
@dynamic view, delegate, dataSource;
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
@@ -58,6 +63,7 @@
|
||||
[super didLoad];
|
||||
|
||||
ASCollectionView *cv = self.view;
|
||||
cv.asyncDelegate = self;
|
||||
#if TARGET_OS_IOS
|
||||
cv.pagingEnabled = YES;
|
||||
cv.scrollsToTop = NO;
|
||||
@@ -122,9 +128,10 @@
|
||||
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (_pagerDataSourceImplementsConstrainedSizeForNode) {
|
||||
return [_pagerDataSource pagerNode:self constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
if (_pagerDelegateImplementsConstrainedSizeForNode) {
|
||||
return [_pagerDelegate pagerNode:self constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
return ASSizeRangeMake(CGSizeZero, self.view.bounds.size);
|
||||
}
|
||||
|
||||
@@ -135,26 +142,38 @@
|
||||
return _pagerDataSource;
|
||||
}
|
||||
|
||||
- (void)setDataSource:(id <ASPagerDataSource>)pagerDataSource
|
||||
- (void)setDataSource:(id <ASPagerDataSource>)dataSource
|
||||
{
|
||||
if (pagerDataSource != _pagerDataSource) {
|
||||
_pagerDataSource = pagerDataSource;
|
||||
if (dataSource != _pagerDataSource) {
|
||||
_pagerDataSource = dataSource;
|
||||
|
||||
_pagerDataSourceImplementsNodeBlockAtIndex = [_pagerDataSource respondsToSelector:@selector(pagerNode:nodeBlockAtIndex:)];
|
||||
// Data source must implement pagerNode:nodeBlockAtIndex: or pagerNode:nodeAtIndex:
|
||||
ASDisplayNodeAssertTrue(_pagerDataSourceImplementsNodeBlockAtIndex || [_pagerDataSource respondsToSelector:@selector(pagerNode:nodeAtIndex:)]);
|
||||
|
||||
_pagerDataSourceImplementsConstrainedSizeForNode = [_pagerDataSource respondsToSelector:@selector(pagerNode:constrainedSizeForNodeAtIndexPath:)];
|
||||
_proxyDataSource = dataSource ? [[ASPagerNodeProxy alloc] initWithTarget:dataSource interceptor:self] : nil;
|
||||
|
||||
_proxy = pagerDataSource ? [[ASPagerNodeProxy alloc] initWithTarget:pagerDataSource interceptor:self] : nil;
|
||||
super.dataSource = (id <ASCollectionDataSource>)_proxyDataSource;
|
||||
}
|
||||
}
|
||||
|
||||
super.dataSource = (id <ASCollectionDataSource>)_proxy;
|
||||
- (void)setDelegate:(id<ASPagerDelegate>)delegate
|
||||
{
|
||||
if (delegate != _pagerDelegate) {
|
||||
_pagerDelegate = delegate;
|
||||
|
||||
_pagerDelegateImplementsConstrainedSizeForNode = [_pagerDelegate respondsToSelector:@selector(pagerNode:constrainedSizeForNodeAtIndexPath:)];
|
||||
|
||||
_proxyDelegate = delegate ? [[ASPagerNodeProxy alloc] initWithTarget:delegate interceptor:self] : nil;
|
||||
|
||||
super.delegate = (id <ASCollectionDelegate>)_proxyDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)proxyTargetHasDeallocated:(ASDelegateProxy *)proxy
|
||||
{
|
||||
[self setDataSource:nil];
|
||||
[self setDelegate:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@protocol ASCollectionViewLayoutInspecting <NSObject>
|
||||
|
||||
/**
|
||||
* Asks the inspector to provide a constarained size range for the given collection view node.
|
||||
* Asks the inspector to provide a constrained size range for the given collection view node.
|
||||
*/
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView
|
||||
@implementation ASCollectionViewLayoutInspector {
|
||||
struct {
|
||||
unsigned int implementsConstrainedSizeForNodeAtIndexPath:1;
|
||||
} _dataSourceFlags;
|
||||
} _delegateFlags;
|
||||
}
|
||||
|
||||
#pragma mark Lifecycle
|
||||
@@ -43,26 +43,26 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
[self didChangeCollectionViewDataSource:collectionView.asyncDataSource];
|
||||
[self didChangeCollectionViewDelegate:collectionView.asyncDelegate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark ASCollectionViewLayoutInspecting
|
||||
|
||||
- (void)didChangeCollectionViewDataSource:(id<ASCollectionDataSource>)dataSource
|
||||
- (void)didChangeCollectionViewDelegate:(id<ASCollectionDelegate>)delegate
|
||||
{
|
||||
if (dataSource == nil) {
|
||||
memset(&_dataSourceFlags, 0, sizeof(_dataSourceFlags));
|
||||
if (delegate == nil) {
|
||||
memset(&_delegateFlags, 0, sizeof(_delegateFlags));
|
||||
} else {
|
||||
_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath = [dataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||
_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||
}
|
||||
}
|
||||
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
||||
return [collectionView.asyncDataSource collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
||||
return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
return NodeConstrainedSizeForScrollDirection(collectionView);
|
||||
@@ -99,10 +99,10 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView
|
||||
struct {
|
||||
unsigned int implementsReferenceSizeForHeader:1;
|
||||
unsigned int implementsReferenceSizeForFooter:1;
|
||||
unsigned int implementsConstrainedSizeForNodeAtIndexPath:1;
|
||||
} _delegateFlags;
|
||||
|
||||
struct {
|
||||
unsigned int implementsConstrainedSizeForNodeAtIndexPath:1;
|
||||
unsigned int implementsNumberOfSectionsInCollectionView:1;
|
||||
} _dataSourceFlags;
|
||||
}
|
||||
@@ -132,6 +132,7 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView
|
||||
} else {
|
||||
_delegateFlags.implementsReferenceSizeForHeader = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)];
|
||||
_delegateFlags.implementsReferenceSizeForFooter = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)];
|
||||
_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,15 +141,14 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView
|
||||
if (dataSource == nil) {
|
||||
memset(&_dataSourceFlags, 0, sizeof(_dataSourceFlags));
|
||||
} else {
|
||||
_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath = [dataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)];
|
||||
_dataSourceFlags.implementsNumberOfSectionsInCollectionView = [dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)];
|
||||
}
|
||||
}
|
||||
|
||||
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (_dataSourceFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
||||
return [collectionView.asyncDataSource collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) {
|
||||
return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
CGSize itemSize = _layout.itemSize;
|
||||
|
||||
@@ -47,7 +47,7 @@ static UIColor *OverViewASPagerNodeRandomColor() {
|
||||
|
||||
#pragma mark - OverviewASPagerNode
|
||||
|
||||
@interface OverviewASPagerNode () <ASPagerNodeDataSource>
|
||||
@interface OverviewASPagerNode () <ASPagerDataSource, ASPagerDelegate>
|
||||
@property (nonatomic, strong) ASPagerNode *node;
|
||||
@property (nonatomic, copy) NSArray *data;
|
||||
@end
|
||||
@@ -61,6 +61,7 @@ static UIColor *OverViewASPagerNodeRandomColor() {
|
||||
|
||||
_node = [ASPagerNode new];
|
||||
_node.dataSource = self;
|
||||
_node.delegate = self;
|
||||
[self addSubnode:_node];
|
||||
|
||||
return self;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#import "ViewController.h"
|
||||
#import "GradientTableNode.h"
|
||||
|
||||
@interface ViewController () <ASPagerNodeDataSource>
|
||||
@interface ViewController () <ASPagerDataSource, ASPagerDelegate>
|
||||
{
|
||||
ASPagerNode *_pagerNode;
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
_pagerNode = [[ASPagerNode alloc] init];
|
||||
_pagerNode.dataSource = self;
|
||||
_pagerNode.delegate = self;
|
||||
[ASRangeController setShouldShowRangeDebugOverlay:YES];
|
||||
|
||||
// Could implement ASCollectionDelegate if we wanted extra callbacks, like from UIScrollView.
|
||||
|
||||
Reference in New Issue
Block a user