diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index 4d8aa8e287..b1e00770c1 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -63,6 +63,9 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView { if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) { return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; + } else { + // With 2.0 `collectionView:constrainedSizeForNodeAtIndexPath:` was moved to the delegate. Assert if not implemented on the delegate but on the data source + ASDisplayNodeAssert([collectionView.asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] == NO, @"collectionView:constrainedSizeForNodeAtIndexPath: was moved from the ASCollectionDataSource to the ASCollectionDataSource."); } return NodeConstrainedSizeForScrollDirection(collectionView); @@ -143,6 +146,9 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView { if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) { return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; + } else { + // With 2.0 `collectionView:constrainedSizeForNodeAtIndexPath:` was moved to the delegate. Assert if not implemented on the delegate but on the data source + ASDisplayNodeAssert([collectionView.asyncDataSource respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)] == NO, @"collectionView:constrainedSizeForNodeAtIndexPath: was moved from the ASCollectionDataSource to the ASCollectionDataSource."); } CGSize itemSize = _layout.itemSize; diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index 58de30ff19..027b40fe29 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -10,6 +10,7 @@ #import #import +#import #import "ASCollectionView.h" #import "ASCollectionViewFlowLayoutInspector.h" @@ -45,6 +46,27 @@ @end +@protocol InspectorTestDataSourceDelegateProtocol + +@end + +@interface InspectorTestDataSourceDelegateWithoutNodeConstrainedSize : NSObject +@end + +@implementation InspectorTestDataSourceDelegateWithoutNodeConstrainedSize + +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath +{ + return ^{ return [[ASCellNode alloc] init]; }; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +{ + return 0; +} + +@end + @interface ASCollectionViewFlowLayoutInspectorTests : XCTestCase @end @@ -345,4 +367,50 @@ collectionView.asyncDelegate = nil; } +- (void)testThatItThrowsIfNodeConstrainedSizeIsImplementedOnDataSourceButNotOnDelegateLayoutInspector +{ + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + + id dataSourceAndDelegate = [OCMockObject mockForProtocol:@protocol(InspectorTestDataSourceDelegateProtocol)]; + ASSizeRange constrainedSize = ASSizeRangeMake(CGSizeZero, CGSizeZero); + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + NSValue *value = [NSValue value:&constrainedSize withObjCType:@encode(ASSizeRange)]; + [[[dataSourceAndDelegate stub] andReturnValue:value] collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; + collectionView.asyncDataSource = dataSourceAndDelegate; + + id delegate = [InspectorTestDataSourceDelegateWithoutNodeConstrainedSize new]; + collectionView.asyncDelegate = delegate; + + ASCollectionViewLayoutInspector *inspector = [[ASCollectionViewLayoutInspector alloc] initWithCollectionView:collectionView]; + + collectionView.layoutInspector = inspector; + XCTAssertThrows([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); + + collectionView.asyncDelegate = dataSourceAndDelegate; + XCTAssertNoThrow([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); +} + +- (void)testThatItThrowsIfNodeConstrainedSizeIsImplementedOnDataSourceButNotOnDelegateFlowLayoutInspector +{ + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + + id dataSourceAndDelegate = [OCMockObject mockForProtocol:@protocol(InspectorTestDataSourceDelegateProtocol)]; + ASSizeRange constrainedSize = ASSizeRangeMake(CGSizeZero, CGSizeZero); + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + NSValue *value = [NSValue value:&constrainedSize withObjCType:@encode(ASSizeRange)]; + [[[dataSourceAndDelegate stub] andReturnValue:value] collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; + collectionView.asyncDataSource = dataSourceAndDelegate; + + id delegate = [InspectorTestDataSourceDelegateWithoutNodeConstrainedSize new]; + collectionView.asyncDelegate = delegate; + + ASCollectionViewFlowLayoutInspector *inspector = collectionView.layoutInspector; + XCTAssertThrows([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); + + collectionView.asyncDelegate = dataSourceAndDelegate; + XCTAssertNoThrow([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); +} + @end