From 295ed22c23bfa38123a859cd7ed919ab6c72cc88 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 27 Jan 2017 15:58:43 -0800 Subject: [PATCH] Improve Our Handling of Flow Layout Headers/Footers (#2939) * Rejigger our flow layout supplementary support to make more sense. * Support old protocol * Update * Update deprecation message * Undeprecate insetForSection method, because it actually _does_ still work * Update the tests * Remove irrelevant junk * Remove cast, add pragma --- AsyncDisplayKit/ASCollectionView.h | 62 ++++++++++--- AsyncDisplayKit/ASCollectionView.mm | 14 ++- AsyncDisplayKit/ASPagerNode.m | 2 +- .../ASCollectionViewFlowLayoutInspector.m | 89 ++++++++++--------- AsyncDisplayKit/Details/ASDelegateProxy.m | 2 + AsyncDisplayKit/Layout/ASDimension.h | 10 +++ AsyncDisplayKit/Layout/ASDimension.mm | 4 + ...ASCollectionViewFlowLayoutInspectorTests.m | 38 ++++---- .../CatDealsCollectionView/Sample/BlurbNode.h | 2 - .../CatDealsCollectionView/Sample/BlurbNode.m | 4 - .../Sample/LoadingNode.h | 2 - .../Sample/LoadingNode.m | 8 -- .../Sample/ViewController.m | 27 +++--- 13 files changed, 156 insertions(+), 108 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 802a6b24b6..72a6d73faa 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -416,33 +416,71 @@ ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASCollectionDelegate.") @end /** - * Defines methods that let you coordinate with a `UICollectionViewFlowLayout` in combination with an `ASCollectionView`. + * Defines methods that let you coordinate a `UICollectionViewFlowLayout` in combination with an `ASCollectionNode`. */ -@protocol ASCollectionViewDelegateFlowLayout +@protocol ASCollectionDelegateFlowLayout @optional /** - * @discussion This method is deprecated and does nothing from 1.9.7 and up - * Previously it applies the section inset to every cells within the corresponding section. - * The expected behavior is to apply the section inset to the whole section rather than - * shrinking each cell individually. - * If you want this behavior, you can integrate your insets calculation into - * `constrainedSizeForNodeAtIndexPath` - * please file a github issue if you would like this to be restored. + * Asks the delegate for the inset that should be applied to the given section. + * + * @see the same method in UICollectionViewDelegate. */ -- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section ASDISPLAYNODE_DEPRECATED_MSG("This method does nothing for 1.9.7+ due to incorrect implementation previously, see the header file for more information."); +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section; + +/** + * Asks the delegate for the size range that should be used to measure the header in the given flow layout section. + * + * @param collectionNode The sender. + * @param section The section. + * + * @return The size range for the header, or @c ASSizeRangeZero if there is no header in this section. + * + * If you want the header to completely determine its own size, return @c ASSizeRangeUnconstrained. + * + * @note Only the scrollable dimension of the returned size range will be used. In a vertical flow, + * only the height will be used. In a horizontal flow, only the width will be used. The other dimension + * will be constrained to fill the collection node. + * + * @discussion If you do not implement this method, ASDK will fall back to calling @c collectionView:layout:referenceSizeForHeaderInSection: + * and using that as the exact constrained size. If you don't implement that method, ASDK will read the @c headerReferenceSize from the layout. + */ +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode sizeRangeForHeaderInSection:(NSInteger)section; + +/** + * Asks the delegate for the size range that should be used to measure the footer in the given flow layout section. + * + * @param collectionNode The sender. + * @param section The section. + * + * @return The size range for the footer, or @c ASSizeRangeZero if there is no footer in this section. + * + * If you want the footer to completely determine its own size, return @c ASSizeRangeUnconstrained. + * + * @note Only the scrollable dimension of the returned size range will be used. In a vertical flow, + * only the height will be used. In a horizontal flow, only the width will be used. The other dimension + * will be constrained to fill the collection node. + * + * @discussion If you do not implement this method, ASDK will fall back to calling @c collectionView:layout:referenceSizeForFooterInSection: + * and using that as the exact constrained size. If you don't implement that method, ASDK will read the @c footerReferenceSize from the layout. + */ +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode sizeRangeForFooterInSection:(NSInteger)section; /** * Asks the delegate for the size of the header in the specified section. */ -- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section; +- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:sizeRangeForHeaderInSection: instead."); /** * Asks the delegate for the size of the footer in the specified section. */ -- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section; +- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:sizeRangeForFooterInSection: instead."); @end +ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASCollectionDelegateFlowLayout.") +@protocol ASCollectionViewDelegateFlowLayout +@end + NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 3a5496e04f..842bafbf48 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -138,7 +138,7 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier"; #pragma mark - #pragma mark ASCollectionView. -@interface ASCollectionView () { +@interface ASCollectionView () { ASCollectionViewProxy *_proxyDataSource; ASCollectionViewProxy *_proxyDelegate; @@ -927,6 +927,16 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier"; return [[self nodeForItemAtIndexPath:indexPath] calculatedSize]; } +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section +{ + return [self supplementaryNodeForElementKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]].calculatedSize; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section +{ + return [self supplementaryNodeForElementKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]].calculatedSize; +} + - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { UICollectionReusableView *view = [self dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:kReuseIdentifier forIndexPath:indexPath]; @@ -936,8 +946,6 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier"; return view; } - - - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { _ASCollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:kReuseIdentifier forIndexPath:indexPath]; diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index 4e8db5d654..1245685713 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -18,7 +18,7 @@ #import "ASCellNode.h" #import "ASCollectionView+Undeprecated.h" -@interface ASPagerNode () +@interface ASPagerNode () { ASPagerFlowLayout *_flowLayout; diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index 30db406497..c6f50778d1 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -24,7 +24,9 @@ @implementation ASCollectionViewFlowLayoutInspector { struct { + unsigned int implementsSizeRangeForHeader:1; unsigned int implementsReferenceSizeForHeader:1; + unsigned int implementsSizeRangeForFooter:1; unsigned int implementsReferenceSizeForFooter:1; unsigned int implementsConstrainedSizeForNodeAtIndexPathDeprecated:1; unsigned int implementsConstrainedSizeForItemAtIndexPath:1; @@ -53,7 +55,9 @@ if (delegate == nil) { memset(&_delegateFlags, 0, sizeof(_delegateFlags)); } else { + _delegateFlags.implementsSizeRangeForHeader = [delegate respondsToSelector:@selector(collectionNode:sizeRangeForHeaderInSection:)]; _delegateFlags.implementsReferenceSizeForHeader = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)]; + _delegateFlags.implementsSizeRangeForFooter = [delegate respondsToSelector:@selector(collectionNode:sizeRangeForFooterInSection:)]; _delegateFlags.implementsReferenceSizeForFooter = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)]; _delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)]; _delegateFlags.implementsConstrainedSizeForItemAtIndexPath = [delegate respondsToSelector:@selector(collectionNode:constrainedSizeForItemAtIndexPath:)]; @@ -84,19 +88,52 @@ - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { - CGSize constrainedSize; - CGSize supplementarySize = [self sizeForSupplementaryViewOfKind:kind inSection:indexPath.section collectionView:collectionView]; - if (_layout.scrollDirection == UICollectionViewScrollDirectionVertical) { - constrainedSize = CGSizeMake(CGRectGetWidth(collectionView.bounds), supplementarySize.height); + ASSizeRange result = ASSizeRangeZero; + if (ASObjectIsEqual(kind, UICollectionElementKindSectionHeader)) { + if (_delegateFlags.implementsSizeRangeForHeader) { + result = [[self delegateForCollectionView:collectionView] collectionNode:collectionView.collectionNode sizeRangeForHeaderInSection:indexPath.section]; + } else if (_delegateFlags.implementsReferenceSizeForHeader) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CGSize exactSize = [[self delegateForCollectionView:collectionView] collectionView:collectionView layout:_layout referenceSizeForHeaderInSection:indexPath.section]; +#pragma clang diagnostic pop + result = ASSizeRangeMake(exactSize); + } else { + result = ASSizeRangeMake(_layout.headerReferenceSize); + } + } else if (ASObjectIsEqual(kind, UICollectionElementKindSectionFooter)) { + if (_delegateFlags.implementsSizeRangeForFooter) { + result = [[self delegateForCollectionView:collectionView] collectionNode:collectionView.collectionNode sizeRangeForFooterInSection:indexPath.section]; + } else if (_delegateFlags.implementsReferenceSizeForFooter) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + CGSize exactSize = [[self delegateForCollectionView:collectionView] collectionView:collectionView layout:_layout referenceSizeForFooterInSection:indexPath.section]; +#pragma clang diagnostic pop + result = ASSizeRangeMake(exactSize); + } else { + result = ASSizeRangeMake(_layout.footerReferenceSize); + } } else { - constrainedSize = CGSizeMake(supplementarySize.width, CGRectGetHeight(collectionView.bounds)); + ASDisplayNodeFailAssert(@"Unexpected supplementary kind: %@", kind); + return ASSizeRangeZero; } - return ASSizeRangeMake(CGSizeZero, constrainedSize); + + if (_layout.scrollDirection == UICollectionViewScrollDirectionVertical) { + result.min.width = result.max.width = CGRectGetWidth(collectionView.bounds); + } else { + result.min.height = result.max.height = CGRectGetHeight(collectionView.bounds); + } + return result; } - (NSUInteger)collectionView:(ASCollectionView *)collectionView supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section { - return [self layoutHasSupplementaryViewOfKind:kind inSection:section collectionView:collectionView] ? 1 : 0; + ASSizeRange constraint = [self collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]]; + if (_layout.scrollDirection == UICollectionViewScrollDirectionVertical) { + return (constraint.max.height > 0 ? 1 : 0); + } else { + return (constraint.max.width > 0 ? 1 : 0); + } } - (ASScrollDirection)scrollableDirections @@ -106,43 +143,9 @@ #pragma mark - Private helpers -- (CGSize)sizeForSupplementaryViewOfKind:(NSString *)kind inSection:(NSUInteger)section collectionView:(ASCollectionView *)collectionView +- (id)delegateForCollectionView:(ASCollectionView *)collectionView { - if (ASObjectIsEqual(kind, UICollectionElementKindSectionHeader)) { - if (_delegateFlags.implementsReferenceSizeForHeader) { - return [[self delegateForCollectionView:collectionView] collectionView:collectionView layout:_layout referenceSizeForHeaderInSection:section]; - } else { - return [self.layout headerReferenceSize]; - } - } else if (ASObjectIsEqual(kind, UICollectionElementKindSectionFooter)) { - if (_delegateFlags.implementsReferenceSizeForFooter) { - return [[self delegateForCollectionView:collectionView] collectionView:collectionView layout:_layout referenceSizeForFooterInSection:section]; - } else { - return [self.layout footerReferenceSize]; - } - } else { - return CGSizeZero; - } -} - -- (BOOL)layoutHasSupplementaryViewOfKind:(NSString *)kind inSection:(NSUInteger)section collectionView:(ASCollectionView *)collectionView -{ - CGSize size = [self sizeForSupplementaryViewOfKind:kind inSection:section collectionView:collectionView]; - return [self usedLayoutValueForSize:size] > 0; -} - -- (CGFloat)usedLayoutValueForSize:(CGSize)size -{ - if (_layout.scrollDirection == UICollectionViewScrollDirectionVertical) { - return size.height; - } else { - return size.width; - } -} - -- (id)delegateForCollectionView:(ASCollectionView *)collectionView -{ - return (id)collectionView.asyncDelegate; + return (id)collectionView.asyncDelegate; } @end diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index 38c32d2f49..4254d88d9b 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -68,6 +68,8 @@ // handled by ASCollectionView node<->cell machinery selector == @selector(collectionView:cellForItemAtIndexPath:) || selector == @selector(collectionView:layout:sizeForItemAtIndexPath:) || + selector == @selector(collectionView:layout:referenceSizeForHeaderInSection:) || + selector == @selector(collectionView:layout:referenceSizeForFooterInSection:) || selector == @selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:) || // Selection, highlighting, menu diff --git a/AsyncDisplayKit/Layout/ASDimension.h b/AsyncDisplayKit/Layout/ASDimension.h index 87a66323c7..c6d2a972e7 100644 --- a/AsyncDisplayKit/Layout/ASDimension.h +++ b/AsyncDisplayKit/Layout/ASDimension.h @@ -201,6 +201,16 @@ typedef struct { CGSize max; } ASSizeRange; +/** + * A size range with all dimensions zero. + */ +extern ASSizeRange const ASSizeRangeZero; + +/** + * A size range from zero to infinity in both directions. + */ +extern ASSizeRange const ASSizeRangeUnconstrained; + /** * Creates an ASSizeRange with provided min and max size. */ diff --git a/AsyncDisplayKit/Layout/ASDimension.mm b/AsyncDisplayKit/Layout/ASDimension.mm index 3fd3f98ac3..c6962de2d0 100644 --- a/AsyncDisplayKit/Layout/ASDimension.mm +++ b/AsyncDisplayKit/Layout/ASDimension.mm @@ -61,6 +61,10 @@ ASLayoutSize const ASLayoutSizeAuto = {ASDimensionAuto, ASDimensionAuto}; #pragma mark - ASSizeRange +ASSizeRange const ASSizeRangeZero = {}; + +ASSizeRange const ASSizeRangeUnconstrained = { {0, 0}, { INFINITY, INFINITY }}; + struct _Range { CGFloat min; CGFloat max; diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index 5c1091bfd6..067be5b52e 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -11,6 +11,7 @@ #import #import #import +#import "ASXCTExtensions.h" #import "ASCollectionView.h" #import "ASCollectionNode.h" @@ -82,7 +83,7 @@ /** * Test Delegate for Header Reference Size Implementation */ -@interface HeaderReferenceSizeTestDelegate : NSObject +@interface HeaderReferenceSizeTestDelegate : NSObject @end @@ -98,7 +99,7 @@ /** * Test Delegate for Footer Reference Size Implementation */ -@interface FooterReferenceSizeTestDelegate : NSObject +@interface FooterReferenceSizeTestDelegate : NSObject @end @@ -144,8 +145,9 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(collectionView.bounds.size.width, 125.0)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the values returned in the delegate implementation"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(collectionView.bounds.size.width, 125.0)); + + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the values returned in the delegate implementation"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -166,8 +168,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(collectionView.bounds.size.width, 125.0)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the values returned in the delegate implementation"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(collectionView.bounds.size.width, 125.0)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the values returned in the delegate implementation"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -189,8 +191,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(collectionView.bounds.size.width, 125.0)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the size set on the layout"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(collectionView.bounds.size.width, 125.0)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the size set on the layout"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -210,8 +212,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(collectionView.bounds.size.width, 125.0)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the size set on the layout"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(collectionView.bounds.size.width, 125.0)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the size set on the layout"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -234,8 +236,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(125.0, collectionView.bounds.size.height)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the values returned in the delegate implementation"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(125.0, collectionView.bounds.size.height)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the values returned in the delegate implementation"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -256,8 +258,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(125.0, collectionView.bounds.size.height)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the values returned in the delegate implementation"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(125.0, collectionView.bounds.size.height)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the values returned in the delegate implementation"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -279,8 +281,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(125.0, collectionView.bounds.size.width)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the size set on the layout"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(125.0, collectionView.bounds.size.width)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the size set on the layout"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; @@ -300,8 +302,8 @@ ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; ASSizeRange size = [inspector collectionView:collectionView constrainedSizeForSupplementaryNodeOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; - ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeZero, CGSizeMake(125.0, collectionView.bounds.size.height)); - XCTAssert(CGSizeEqualToSize(size.min, sizeCompare.min) && CGSizeEqualToSize(size.max, sizeCompare.max), @"should have a size constrained by the size set on the layout"); + ASSizeRange sizeCompare = ASSizeRangeMake(CGSizeMake(125.0, collectionView.bounds.size.height)); + ASXCTAssertEqualSizeRanges(size, sizeCompare, @"should have a size constrained by the size set on the layout"); collectionView.asyncDataSource = nil; collectionView.asyncDelegate = nil; diff --git a/examples/CatDealsCollectionView/Sample/BlurbNode.h b/examples/CatDealsCollectionView/Sample/BlurbNode.h index 762352e76f..e6574bcd05 100644 --- a/examples/CatDealsCollectionView/Sample/BlurbNode.h +++ b/examples/CatDealsCollectionView/Sample/BlurbNode.h @@ -22,6 +22,4 @@ */ @interface BlurbNode : ASCellNode -+ (CGFloat)desiredHeightForWidth:(CGFloat)width; - @end diff --git a/examples/CatDealsCollectionView/Sample/BlurbNode.m b/examples/CatDealsCollectionView/Sample/BlurbNode.m index 262b860184..fc4fed6224 100644 --- a/examples/CatDealsCollectionView/Sample/BlurbNode.m +++ b/examples/CatDealsCollectionView/Sample/BlurbNode.m @@ -39,10 +39,6 @@ static CGFloat kTextPadding = 10.0f; #pragma mark - #pragma mark ASCellNode. -+ (CGFloat)desiredHeightForWidth:(CGFloat)width { - return kFixedHeight; -} - - (instancetype)init { if (!(self = [super init])) diff --git a/examples/CatDealsCollectionView/Sample/LoadingNode.h b/examples/CatDealsCollectionView/Sample/LoadingNode.h index 109cf61a32..d144de01a9 100644 --- a/examples/CatDealsCollectionView/Sample/LoadingNode.h +++ b/examples/CatDealsCollectionView/Sample/LoadingNode.h @@ -21,6 +21,4 @@ @interface LoadingNode : ASCellNode -+ (CGFloat)desiredHeightForWidth:(CGFloat)width; - @end diff --git a/examples/CatDealsCollectionView/Sample/LoadingNode.m b/examples/CatDealsCollectionView/Sample/LoadingNode.m index b9b4f9788f..f37dc8cc80 100644 --- a/examples/CatDealsCollectionView/Sample/LoadingNode.m +++ b/examples/CatDealsCollectionView/Sample/LoadingNode.m @@ -39,10 +39,6 @@ static CGFloat kFixedHeight = 200.0f; #pragma mark - #pragma mark ASCellNode. -+ (CGFloat)desiredHeightForWidth:(CGFloat)width { - return kFixedHeight; -} - - (instancetype)init { if (!(self = [super init])) @@ -61,10 +57,6 @@ static CGFloat kFixedHeight = 200.0f; return self; } -- (void)layout { - [super layout]; -} - - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { ASCenterLayoutSpec *centerSpec = [[ASCenterLayoutSpec alloc] init]; diff --git a/examples/CatDealsCollectionView/Sample/ViewController.m b/examples/CatDealsCollectionView/Sample/ViewController.m index 8726968ef4..986b49e1d8 100644 --- a/examples/CatDealsCollectionView/Sample/ViewController.m +++ b/examples/CatDealsCollectionView/Sample/ViewController.m @@ -29,7 +29,7 @@ static const NSInteger kBatchSize = 20; static const CGFloat kHorizontalSectionPadding = 10.0f; static const CGFloat kVerticalSectionPadding = 20.0f; -@interface ViewController () +@interface ViewController () { ASCollectionNode *_collectionNode; NSMutableArray *_data; @@ -203,27 +203,24 @@ static const CGFloat kVerticalSectionPadding = 20.0f; }]; } -#pragma mark - ASCollectionViewDelegateFlowLayout +#pragma mark - ASCollectionDelegateFlowLayout -- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { - return UIEdgeInsetsMake(kVerticalSectionPadding, kHorizontalSectionPadding, kVerticalSectionPadding, kHorizontalSectionPadding); -} - -- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode referenceConstrainedSizeForHeaderInSection:(NSInteger)section +{ if (section == 0) { - CGFloat width = CGRectGetWidth(self.view.frame) - 2 * kHorizontalSectionPadding; - return CGSizeMake(width, [BlurbNode desiredHeightForWidth:width]); + return ASSizeRangeUnconstrained; + } else { + return ASSizeRangeZero; } - return CGSizeZero; } -- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode referenceConstrainedSizeForFooterInSection:(NSInteger)section +{ if (section == 0) { - CGFloat width = CGRectGetWidth(self.view.frame); - return CGSizeMake(width, [LoadingNode desiredHeightForWidth:width]); + return ASSizeRangeUnconstrained; + } else { + return ASSizeRangeZero; } - return CGSizeZero; } - @end