diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 2ce5ad2830..ac58f4a2f1 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -407,6 +407,7 @@ B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; }; B350625F1B0111800018CF92 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; }; C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC0AEEA41D66316E005D1C78 /* ASUICollectionViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */; }; CC3B20841C3F76D600798563 /* ASPendingStateController.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3B20811C3F76D600798563 /* ASPendingStateController.h */; }; CC3B20851C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; }; CC3B20861C3F76D600798563 /* ASPendingStateController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B20821C3F76D600798563 /* ASPendingStateController.mm */; }; @@ -1076,6 +1077,7 @@ B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B35061DD1B010EDF0018CF92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../AsyncDisplayKit-iOS/Info.plist"; sourceTree = ""; }; BDC2D162BD55A807C1475DA5 /* Pods-AsyncDisplayKitTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.profile.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.profile.xcconfig"; sourceTree = ""; }; + CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASUICollectionViewTests.m; sourceTree = ""; }; CC3B20811C3F76D600798563 /* ASPendingStateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPendingStateController.h; sourceTree = ""; }; CC3B20821C3F76D600798563 /* ASPendingStateController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPendingStateController.mm; sourceTree = ""; }; CC3B20871C3F7A5400798563 /* ASWeakSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakSet.h; sourceTree = ""; }; @@ -1322,6 +1324,7 @@ 058D09C5195D04C000B7D73C /* AsyncDisplayKitTests */ = { isa = PBXGroup; children = ( + CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */, CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */, 83A7D95D1D446A6E00BF333E /* ASWeakMapTests.m */, DBC453211C5FD97200B16017 /* ASDisplayNodeImplicitHierarchyTests.m */, @@ -2195,6 +2198,7 @@ 058D0A3C195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m in Sources */, 697B315A1CFE4B410049936F /* ASEditableTextNodeTests.m in Sources */, ACF6ED611B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm in Sources */, + CC0AEEA41D66316E005D1C78 /* ASUICollectionViewTests.m in Sources */, ACF6ED621B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm in Sources */, 7AB338691C55B97B0055FDE8 /* ASRelativeLayoutSpecSnapshotTests.mm in Sources */, 254C6B541BF8FF2A003EC431 /* ASTextKitTests.mm in Sources */, diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index dd12112668..7ddcf1d5af 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -1033,11 +1033,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; return [self.layoutInspector collectionView:self supplementaryNodesOfKind:kind inSection:section]; } -- (NSUInteger)dataController:(ASCollectionDataController *)dataController numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind; -{ - return [self.layoutInspector collectionView:self numberOfSectionsForSupplementaryNodeOfKind:kind]; -} - #pragma mark - ASRangeControllerDataSource - (ASRangeController *)rangeController diff --git a/AsyncDisplayKit/Details/ASCollectionDataController.h b/AsyncDisplayKit/Details/ASCollectionDataController.h index 92c31f1feb..b99bb9e5dc 100644 --- a/AsyncDisplayKit/Details/ASCollectionDataController.h +++ b/AsyncDisplayKit/Details/ASCollectionDataController.h @@ -26,8 +26,6 @@ - (NSArray *)supplementaryNodeKindsInDataController:(ASCollectionDataController *)dataController; -- (NSUInteger)dataController:(ASCollectionDataController *)dataController numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind; - - (NSUInteger)dataController:(ASCollectionDataController *)dataController supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section; @optional diff --git a/AsyncDisplayKit/Details/ASCollectionDataController.mm b/AsyncDisplayKit/Details/ASCollectionDataController.mm index 8f5d505815..170af2b319 100644 --- a/AsyncDisplayKit/Details/ASCollectionDataController.mm +++ b/AsyncDisplayKit/Details/ASCollectionDataController.mm @@ -65,7 +65,7 @@ [self deleteSectionsOfKind:kind atIndexSet:indexSet completion:nil]; // Insert each section - NSUInteger sectionCount = [self.collectionDataSource dataController:self numberOfSectionsForSupplementaryNodeOfKind:kind]; + NSUInteger sectionCount = self.itemCountsFromDataSource.size(); NSMutableArray *sections = [NSMutableArray arrayWithCapacity:sectionCount]; for (int i = 0; i < sectionCount; i++) { [sections addObject:[NSMutableArray array]]; @@ -194,7 +194,7 @@ ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection; id source = self.collectionDataSource; - NSUInteger sectionCount = [source dataController:self numberOfSectionsForSupplementaryNodeOfKind:kind]; + NSUInteger sectionCount = self.itemCountsFromDataSource.size(); for (NSUInteger i = 0; i < sectionCount; i++) { NSUInteger rowCount = [source dataController:self supplementaryNodesOfKind:kind inSection:i]; for (NSUInteger j = 0; j < rowCount; j++) { diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h index 608a93cea1..0dafa8cbff 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h @@ -33,11 +33,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath; -/** - * Asks the inspector for the number of supplementary sections in the collection view for the given kind. - */ -- (NSUInteger)collectionView:(ASCollectionView *)collectionView numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind; - /** * Asks the inspector for the number of supplementary views for the given kind in the specified section. */ @@ -57,6 +52,16 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)didChangeCollectionViewDataSource:(nullable id)dataSource; +#pragma mark Deprecated Methods + +/** + * Asks the inspector for the number of supplementary sections in the collection view for the given kind. + * + * @deprecated This method will not be called, and it is only deprecated as a reminder to remove it. + * Supplementary elements must exist in the same sections as regular collection view items i.e. -numberOfSectionsInCollectionView: + */ +- (NSUInteger)collectionView:(ASCollectionView *)collectionView numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind ASDISPLAYNODE_DEPRECATED; + @end /** diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index 9ae4d1e158..4d8aa8e287 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -74,12 +74,6 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView return ASSizeRangeMake(CGSizeZero, CGSizeZero); } -- (NSUInteger)collectionView:(ASCollectionView *)collectionView numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind -{ - ASDisplayNodeAssert(NO, @"To support supplementary nodes in ASCollectionView, it must have a layoutInspector for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)"); - return 0; -} - - (NSUInteger)collectionView:(ASCollectionView *)collectionView supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section { ASDisplayNodeAssert(NO, @"To support supplementary nodes in ASCollectionView, it must have a layoutInspector for layout inspection. (See ASCollectionViewFlowLayoutInspector for an example.)"); @@ -171,15 +165,6 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView return ASSizeRangeMake(CGSizeZero, constrainedSize); } -- (NSUInteger)collectionView:(ASCollectionView *)collectionView numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind -{ - if (_dataSourceFlags.implementsNumberOfSectionsInCollectionView) { - return [collectionView.asyncDataSource numberOfSectionsInCollectionView:collectionView]; - } else { - return 1; - } -} - - (NSUInteger)collectionView:(ASCollectionView *)collectionView supplementaryNodesOfKind:(NSString *)kind inSection:(NSUInteger)section { return [self layoutHasSupplementaryViewOfKind:kind inSection:section collectionView:collectionView] ? 1 : 0; diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index ba02de42e7..58de30ff19 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -294,34 +294,6 @@ collectionView.asyncDelegate = nil; } -#pragma mark - #collectionView:numberOfSectionsForSupplementaryNodeOfKind: - -- (void)testThatItRespondsWithTheDefaultNumberOfSections -{ - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; - ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; - NSUInteger sections = [inspector collectionView:collectionView numberOfSectionsForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; - XCTAssert(sections == 1, @"should return 1 by default"); - - collectionView.asyncDataSource = nil; - collectionView.asyncDelegate = nil; -} - -- (void)testThatItProvidesTheNumberOfSectionsInTheDataSource -{ - InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init]; - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; - collectionView.asyncDataSource = dataSource; - ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout]; - NSUInteger sections = [inspector collectionView:collectionView numberOfSectionsForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; - XCTAssert(sections == 2, @"should return 2"); - - collectionView.asyncDataSource = nil; - collectionView.asyncDelegate = nil; -} - #pragma mark - #collectionView:supplementaryNodesOfKind:inSection: - (void)testThatItReturnsOneWhenAValidSizeIsImplementedOnTheDelegate diff --git a/AsyncDisplayKitTests/ASUICollectionViewTests.m b/AsyncDisplayKitTests/ASUICollectionViewTests.m new file mode 100644 index 0000000000..e325265741 --- /dev/null +++ b/AsyncDisplayKitTests/ASUICollectionViewTests.m @@ -0,0 +1,70 @@ +// +// ASUICollectionViewTests.m +// AsyncDisplayKit +// +// Created by Adlai Holler on 8/18/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +#import +#import + +@interface ASUICollectionViewTests : XCTestCase + +@end + +@implementation ASUICollectionViewTests + +/// Test normal item-affiliated supplementary node +- (void)testNormalTwoIndexSupplementaryElement +{ + [self _testSupplementaryNodeAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1] sectionCount:2 expectException:NO]; +} + +/// If your supp is indexPathForItem:inSection:, the section index must be in bounds +- (void)testThatSupplementariesWithItemIndexesMustBeWithinNormalSections +{ + [self _testSupplementaryNodeAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:3] sectionCount:2 expectException:YES]; +} + +/// If your supp is indexPathWithIndex:, that's OK even if that section is out of bounds! +- (void)testThatSupplementariesWithOneIndexAreOKOutOfSectionBounds +{ + [self _testSupplementaryNodeAtIndexPath:[NSIndexPath indexPathWithIndex:3] sectionCount:2 expectException:NO]; +} + +- (void)_testSupplementaryNodeAtIndexPath:(NSIndexPath *)indexPath sectionCount:(NSInteger)sectionCount expectException:(BOOL)shouldFail +{ + UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:@"SuppKind" withIndexPath:indexPath]; + attr.frame = CGRectMake(0, 0, 20, 20); + UICollectionViewLayout *layout = [[UICollectionViewLayout alloc] init]; + id layoutMock = [OCMockObject partialMockForObject:layout]; + + [[[[layoutMock expect] ignoringNonObjectArgs] andReturn:@[ attr ]] layoutAttributesForElementsInRect:CGRectZero]; + UICollectionView *cv = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) collectionViewLayout:layoutMock]; + [cv registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:@"SuppKind" withReuseIdentifier:@"ReuseID"]; + + id dataSource = [OCMockObject niceMockForProtocol:@protocol(UICollectionViewDataSource)]; + __block id view = nil; + [[[dataSource expect] andDo:^(NSInvocation *invocation) { + NSIndexPath *indexPath = nil; + [invocation getArgument:&indexPath atIndex:4]; + view = [cv dequeueReusableSupplementaryViewOfKind:@"SuppKind" withReuseIdentifier:@"ReuseID" forIndexPath:indexPath]; + [invocation setReturnValue:&view]; + }] collectionView:cv viewForSupplementaryElementOfKind:@"SuppKind" atIndexPath:indexPath]; + [[[dataSource expect] andReturnValue:[NSNumber numberWithInteger:sectionCount]] numberOfSectionsInCollectionView:cv]; + + cv.dataSource = dataSource; + if (shouldFail) { + XCTAssertThrowsSpecificNamed([cv layoutIfNeeded], NSException, NSInternalInconsistencyException); + } else { + [cv layoutIfNeeded]; + XCTAssertEqualObjects(attr, [cv layoutAttributesForSupplementaryElementOfKind:@"SuppKind" atIndexPath:indexPath]); + XCTAssertEqual(view, [cv supplementaryViewForElementKind:@"SuppKind" atIndexPath:indexPath]); + } + + [dataSource verify]; + [layoutMock verify]; +} + +@end