diff --git a/CHANGELOG.md b/CHANGELOG.md index 85cb7e9c..ff4b9849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag ## Master - Fixed `-[IGListAdapter reloadDataWithCompletion:]` not returning early when `collectionView` or `dataSource` is nil and `completion` is nil. [Ben Asher](https://github.com/benasher44) [#51](https://github.com/Instagram/IGListKit/pull/51) - +- Added `-isFirstSection` and `-isLastSection` APIs to `IGListSectionController` 1.0.0 ----- diff --git a/Source/IGListAdapter.m b/Source/IGListAdapter.m index 05610204..5a088e34 100644 --- a/Source/IGListAdapter.m +++ b/Source/IGListAdapter.m @@ -386,6 +386,9 @@ // for IGListSectionController subclasses after calling [super init] IGListSectionControllerPushThread(self.viewController, self); + id firstObject = objects.firstObject; + id lastObject = objects.lastObject; + for (id object in objects) { // infra checks to see if a controller exists IGListSectionController *sectionController = [map sectionControllerForObject:object]; @@ -403,6 +406,8 @@ // in case the section controller was created outside of -listAdapter:sectionControllerForObject: sectionController.collectionContext = self; sectionController.viewController = self.viewController; + sectionController.isFirstSection = (object == firstObject); + sectionController.isLastSection = (object == lastObject); // check if the item has changed instances or is new const NSUInteger oldSection = [map sectionForObject:object]; diff --git a/Source/IGListSectionController.h b/Source/IGListSectionController.h index 61f8799b..22a2a827 100644 --- a/Source/IGListSectionController.h +++ b/Source/IGListSectionController.h @@ -34,6 +34,16 @@ */ @property (nonatomic, weak, nullable, readonly) id collectionContext; +/** + Returns YES if the section controller is the first section in the list. + */ +@property (nonatomic, assign, readonly) BOOL isFirstSection; + +/** + Returns YES if the section controller is the last section in the list. + */ +@property (nonatomic, assign, readonly) BOOL isLastSection; + /** The margins used to lay out content in the section controller. diff --git a/Source/Internal/IGListSectionControllerInternal.h b/Source/Internal/IGListSectionControllerInternal.h index f7b92d90..73c9cb66 100644 --- a/Source/Internal/IGListSectionControllerInternal.h +++ b/Source/Internal/IGListSectionControllerInternal.h @@ -19,4 +19,8 @@ FOUNDATION_EXTERN void IGListSectionControllerPopThread(void); @property (nonatomic, weak, readwrite) UIViewController *viewController; +@property (nonatomic, assign, readwrite) BOOL isFirstSection; + +@property (nonatomic, assign, readwrite) BOOL isLastSection; + @end diff --git a/Tests/IGListAdapterTests.m b/Tests/IGListAdapterTests.m index de7c307d..8d16fdcf 100644 --- a/Tests/IGListAdapterTests.m +++ b/Tests/IGListAdapterTests.m @@ -452,4 +452,29 @@ XCTAssertNil(weakSectionController); } +- (void)test_whenAdapterUpdatedTwice_withThreeSections_thatSectionsUpdatedFirstLast { + self.dataSource.objects = @[@0, @1, @2]; + [self.adapter reloadDataWithCompletion:nil]; + + XCTAssertTrue([[self.adapter sectionControllerForObject:@0] isFirstSection]); + XCTAssertFalse([[self.adapter sectionControllerForObject:@1] isFirstSection]); + XCTAssertFalse([[self.adapter sectionControllerForObject:@2] isFirstSection]); + + XCTAssertFalse([[self.adapter sectionControllerForObject:@0] isLastSection]); + XCTAssertFalse([[self.adapter sectionControllerForObject:@1] isLastSection]); + XCTAssertTrue([[self.adapter sectionControllerForObject:@2] isLastSection]); + + // update and shift objects to test that first/last flags are also updated + self.dataSource.objects = @[@2, @0, @1]; + [self.adapter performUpdatesAnimated:NO completion:nil]; + + XCTAssertFalse([[self.adapter sectionControllerForObject:@0] isFirstSection]); + XCTAssertFalse([[self.adapter sectionControllerForObject:@1] isFirstSection]); + XCTAssertTrue([[self.adapter sectionControllerForObject:@2] isFirstSection]); + + XCTAssertFalse([[self.adapter sectionControllerForObject:@0] isLastSection]); + XCTAssertTrue([[self.adapter sectionControllerForObject:@1] isLastSection]); + XCTAssertFalse([[self.adapter sectionControllerForObject:@2] isLastSection]); +} + @end