mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Merge pull request #762 from levi/supplementary-views
Respond to supplementary node feedback
This commit is contained in:
commit
7d013a70ac
@ -90,7 +90,7 @@
|
||||
* collection view layout subclasses will need to provide their own implementation of an inspector object for their
|
||||
* supplementary views to be compatible with `ASCollectionView`'s supplementary node support.
|
||||
*/
|
||||
@property (nonatomic, weak) id<ASCollectionViewLayoutInspecting> layoutDelegate;
|
||||
@property (nonatomic, weak) id<ASCollectionViewLayoutInspecting> layoutInspector;
|
||||
|
||||
/**
|
||||
* Perform a batch of updates asynchronously, optionally disabling all animations in the batch. This method must be called from the main thread.
|
||||
|
||||
@ -153,7 +153,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
CGSize _maxSizeForNodesConstrainedSize;
|
||||
BOOL _ignoreMaxSizeChange;
|
||||
|
||||
NSMutableArray *_registeredSupplementaryKinds;
|
||||
NSMutableSet *_registeredSupplementaryKinds;
|
||||
|
||||
/**
|
||||
* If YES, the `UICollectionView` will reload its data on next layout pass so we should not forward any updates to it.
|
||||
@ -229,10 +229,10 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
// Register the default layout inspector delegate for flow layouts only, custom layouts
|
||||
// will need to roll their own ASCollectionViewLayoutInspecting implementation and set a layout delegate
|
||||
if ([layout asdk_isFlowLayout]) {
|
||||
_layoutDelegate = [self flowLayoutInspector];
|
||||
_layoutInspector = [self flowLayoutInspector];
|
||||
}
|
||||
|
||||
_registeredSupplementaryKinds = [NSMutableArray array];
|
||||
_registeredSupplementaryKinds = [NSMutableSet set];
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
@ -256,6 +256,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
{
|
||||
if (_flowLayoutInspector == nil) {
|
||||
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionViewLayout;
|
||||
ASDisplayNodeAssertNotNil(layout, @"Collection view layout must be a flow layout to use the built-in inspector");
|
||||
_flowLayoutInspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:self
|
||||
flowLayout:layout];
|
||||
}
|
||||
@ -333,16 +334,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
_asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0);
|
||||
}
|
||||
|
||||
[_flowLayoutInspector cacheSelectorsForCollectionView:self];
|
||||
}
|
||||
|
||||
- (void)setCollectionViewLayout:(UICollectionViewLayout *)collectionViewLayout
|
||||
{
|
||||
[super setCollectionViewLayout:collectionViewLayout];
|
||||
if ([collectionViewLayout asdk_isFlowLayout]) {
|
||||
_flowLayoutInspector = nil;
|
||||
_layoutDelegate = [self flowLayoutInspector];
|
||||
}
|
||||
[_layoutInspector didChangeCollectionViewDelegate:asyncDelegate];
|
||||
}
|
||||
|
||||
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType
|
||||
@ -745,25 +737,25 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
|
||||
- (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController
|
||||
{
|
||||
return _registeredSupplementaryKinds;
|
||||
return [_registeredSupplementaryKinds allObjects];
|
||||
}
|
||||
|
||||
- (ASSizeRange)dataController:(ASCollectionDataController *)dataController constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
ASDisplayNodeAssert(_layoutDelegate != nil, @"To support supplementary nodes in ASCollectionView, it must have a layoutDelegate for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
||||
return [_layoutDelegate collectionView:self constrainedSizeForSupplementaryNodeOfKind:kind atIndexPath:indexPath];
|
||||
ASDisplayNodeAssert(_layoutInspector != nil, @"To support supplementary nodes in ASCollectionView, it must have a layoutDelegate for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
||||
return [_layoutInspector collectionView:self constrainedSizeForSupplementaryNodeOfKind:kind atIndexPath:indexPath];
|
||||
}
|
||||
|
||||
- (NSUInteger)dataController:(ASCollectionDataController *)dataController supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section
|
||||
{
|
||||
ASDisplayNodeAssert(_layoutDelegate != nil, @"To support supplementary nodes in ASCollectionView, it must have a layoutDelegate for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
||||
return [_layoutDelegate collectionView:self supplementaryNodesOfKind:kind inSection:section];
|
||||
ASDisplayNodeAssert(_layoutInspector != nil, @"To support supplementary nodes in ASCollectionView, it must have a layoutDelegate for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
||||
return [_layoutInspector collectionView:self supplementaryNodesOfKind:kind inSection:section];
|
||||
}
|
||||
|
||||
- (NSUInteger)dataController:(ASCollectionDataController *)dataController numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind;
|
||||
{
|
||||
ASDisplayNodeAssert(_layoutDelegate != nil, @"To support supplementary nodes in ASCollectionView, it must have a layoutDelegate for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
||||
return [_layoutDelegate collectionView:self numberOfSectionsForSupplementaryNodeOfKind:kind];
|
||||
ASDisplayNodeAssert(_layoutInspector != nil, @"To support supplementary nodes in ASCollectionView, it must have a layoutDelegate for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)");
|
||||
return [_layoutInspector collectionView:self numberOfSectionsForSupplementaryNodeOfKind:kind];
|
||||
}
|
||||
|
||||
#pragma mark - ASRangeControllerDelegate.
|
||||
|
||||
@ -61,7 +61,7 @@
|
||||
NSUInteger sectionCount = [self.collectionDataSource dataController:self numberOfSectionsForSupplementaryNodeOfKind:kind];
|
||||
NSMutableArray *sections = [NSMutableArray arrayWithCapacity:sectionCount];
|
||||
for (int i = 0; i < sectionCount; i++) {
|
||||
[sections addObject:[[NSMutableArray alloc] init]];
|
||||
[sections addObject:[NSMutableArray array]];
|
||||
}
|
||||
[self insertSections:sections ofKind:kind atIndexSet:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)] completion:nil];
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#import <AsyncDisplayKit/ASDimension.h>
|
||||
|
||||
@class ASCollectionView;
|
||||
@protocol ASCollectionViewDelegate;
|
||||
|
||||
@protocol ASCollectionViewLayoutInspecting <NSObject>
|
||||
|
||||
@ -29,6 +30,13 @@
|
||||
*/
|
||||
- (NSUInteger)collectionView:(ASCollectionView *)collectionView supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section;
|
||||
|
||||
/**
|
||||
* Allow the inspector to respond to delegate changes.
|
||||
*
|
||||
* @discussion A great time to update perform selector caches!
|
||||
*/
|
||||
- (void)didChangeCollectionViewDelegate:(id<ASCollectionViewDelegate>)delegate;
|
||||
|
||||
@end
|
||||
|
||||
@interface ASCollectionViewFlowLayoutInspector : NSObject <ASCollectionViewLayoutInspecting>
|
||||
@ -37,6 +45,4 @@
|
||||
|
||||
- (instancetype)initWithCollectionView:(ASCollectionView *)collectionView flowLayout:(UICollectionViewFlowLayout *)flowLayout;
|
||||
|
||||
- (void)cacheSelectorsForCollectionView:(ASCollectionView *)collectionView;
|
||||
|
||||
@end
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#import "ASCollectionViewFlowLayoutInspector.h"
|
||||
|
||||
#import "ASCollectionView.h"
|
||||
#import "ASAssert.h"
|
||||
#import "ASEqualityHelpers.h"
|
||||
|
||||
@implementation ASCollectionViewFlowLayoutInspector {
|
||||
BOOL _delegateImplementsReferenceSizeForHeader;
|
||||
@ -24,24 +26,24 @@
|
||||
self = [super init];
|
||||
|
||||
if (flowLayout == nil) {
|
||||
return nil;
|
||||
ASDisplayNodeAssert(NO, @"Should never create a layout inspector without a layout");
|
||||
}
|
||||
|
||||
if (self != nil) {
|
||||
[self cacheSelectorsForCollectionView:collectionView];
|
||||
[self didChangeCollectionViewDelegate:collectionView.asyncDelegate];
|
||||
_layout = flowLayout;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)cacheSelectorsForCollectionView:(ASCollectionView *)collectionView
|
||||
- (void)didChangeCollectionViewDelegate:(id<ASCollectionViewDelegate>)delegate;
|
||||
{
|
||||
if (collectionView == nil) {
|
||||
_delegateImplementsReferenceSizeForHeader = nil;
|
||||
_delegateImplementsReferenceSizeForFooter = nil;
|
||||
if (delegate == nil) {
|
||||
_delegateImplementsReferenceSizeForHeader = NO;
|
||||
_delegateImplementsReferenceSizeForFooter = NO;
|
||||
} else {
|
||||
_delegateImplementsReferenceSizeForHeader = [[self delegateForCollectionView:collectionView] respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)];
|
||||
_delegateImplementsReferenceSizeForFooter = [[self delegateForCollectionView:collectionView] respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)];
|
||||
_delegateImplementsReferenceSizeForHeader = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)];
|
||||
_delegateImplementsReferenceSizeForFooter = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)];
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,13 +79,13 @@
|
||||
|
||||
- (CGSize)sizeForSupplementaryViewOfKind:(NSString *)kind inSection:(NSUInteger)section collectionView:(ASCollectionView *)collectionView
|
||||
{
|
||||
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
|
||||
if (ASObjectIsEqual(kind, UICollectionElementKindSectionHeader)) {
|
||||
if (_delegateImplementsReferenceSizeForHeader) {
|
||||
return [[self delegateForCollectionView:collectionView] collectionView:collectionView layout:_layout referenceSizeForHeaderInSection:section];
|
||||
} else {
|
||||
return [self.layout headerReferenceSize];
|
||||
}
|
||||
} else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
|
||||
} else if (ASObjectIsEqual(kind, UICollectionElementKindSectionFooter)) {
|
||||
if (_delegateImplementsReferenceSizeForFooter) {
|
||||
return [[self delegateForCollectionView:collectionView] collectionView:collectionView layout:_layout referenceSizeForFooterInSection:section];
|
||||
} else {
|
||||
|
||||
@ -74,8 +74,8 @@
|
||||
/**
|
||||
* Notifies the subclass to perform any work needed before the data controller is reloaded entirely
|
||||
*
|
||||
* @discussion This method will be performed before the data controller enters its editing queue, usually on the main
|
||||
* thread. The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||
* @discussion This method will be performed before the data controller enters its editing queue.
|
||||
* The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||
* data stores before entering into editing the backing store on a background thread.
|
||||
*/
|
||||
- (void)prepareForReloadData;
|
||||
@ -92,8 +92,8 @@
|
||||
/**
|
||||
* Notifies the subclass to perform setup before sections are inserted in the data controller
|
||||
*
|
||||
* @discussion This method will be performed before the data controller enters its editing queue, usually on the main
|
||||
* thread. The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||
* @discussion This method will be performed before the data controller enters its editing queue.
|
||||
* The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||
* data stores before entering into editing the backing store on a background thread.
|
||||
*
|
||||
* @param sections Indices of sections to be inserted
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#import "ASDisplayNode.h"
|
||||
#import "ASMultidimensionalArrayUtils.h"
|
||||
#import "ASDisplayNodeInternal.h"
|
||||
#import "ASLayout.h"
|
||||
|
||||
//#define LOG(...) NSLog(__VA_ARGS__)
|
||||
#define LOG(...)
|
||||
@ -185,8 +186,9 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
dispatch_group_wait(layoutGroup, DISPATCH_TIME_FOREVER);
|
||||
free(nodeBoundSizes);
|
||||
|
||||
if (completionBlock)
|
||||
if (completionBlock) {
|
||||
completionBlock(nodes, indexPaths);
|
||||
}
|
||||
}
|
||||
|
||||
- (ASSizeRange)constrainedSizeForNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||
@ -218,8 +220,10 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
- (void)deleteNodesOfKind:(NSString *)kind atIndexPaths:(NSArray *)indexPaths completion:(void (^)(NSArray *nodes, NSArray *indexPaths))completionBlock
|
||||
{
|
||||
if (indexPaths.count == 0)
|
||||
if (indexPaths.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(@"_deleteNodesAtIndexPaths:%@ ofKind:%@, full index paths in _editingNodes = %@", indexPaths, kind, ASIndexPathsForMultidimensionalArray(_editingNodes[kind]));
|
||||
NSMutableArray *editingNodes = _editingNodes[kind];
|
||||
ASDeleteElementsInMultidimensionalArrayAtIndexPaths(editingNodes, indexPaths);
|
||||
@ -818,8 +822,8 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
[section enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger rowIndex, BOOL *stop) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:kind atIndexPath:indexPath];
|
||||
[node measureWithSizeRange:constrainedSize];
|
||||
node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height);
|
||||
ASLayout *layout = [node measureWithSizeRange:constrainedSize];
|
||||
node.frame = CGRectMake(0.0f, 0.0f, layout.size.width, layout.size.height);
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
@ -849,7 +853,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
- (NSArray *)indexPathsForEditingNodesOfKind:(NSString *)kind
|
||||
{
|
||||
return _editingNodes[kind] != nil ? ASIndexPathsForMultidimensionalArray(_editingNodes[kind]) : [NSArray array];
|
||||
return _editingNodes[kind] != nil ? ASIndexPathsForMultidimensionalArray(_editingNodes[kind]) : nil;
|
||||
}
|
||||
|
||||
- (NSMutableArray *)editingNodesOfKind:(NSString *)kind
|
||||
|
||||
@ -91,15 +91,15 @@
|
||||
{
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
XCTAssert(collectionView.layoutDelegate != nil, @"should automatically set a layout delegate for flow layouts");
|
||||
XCTAssert([collectionView.layoutDelegate isKindOfClass:[ASCollectionViewFlowLayoutInspector class]], @"should have a flow layout inspector by default");
|
||||
XCTAssert(collectionView.layoutInspector != nil, @"should automatically set a layout delegate for flow layouts");
|
||||
XCTAssert([collectionView.layoutInspector isKindOfClass:[ASCollectionViewFlowLayoutInspector class]], @"should have a flow layout inspector by default");
|
||||
}
|
||||
|
||||
- (void)testThatItDoesNotSetALayoutInspectorForCustomLayouts
|
||||
{
|
||||
UICollectionViewLayout *layout = [[UICollectionViewLayout alloc] init];
|
||||
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
XCTAssert(collectionView.layoutDelegate == nil, @"should not set a layout delegate for custom layouts");
|
||||
XCTAssert(collectionView.layoutInspector == nil, @"should not set a layout delegate for custom layouts");
|
||||
}
|
||||
|
||||
- (void)testThatRegisteringASupplementaryNodeStoresItForIntrospection
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user