Skip to content

Commit

Permalink
Add isLast/FirstSection API to IGListSectionController
Browse files Browse the repository at this point in the history
Summary: Product needs show that section controllers need some sort of awarenes when they are the first/last section in a list (e.g. for cell borders). Adding this simple API, non-breaking.

Reviewed By: jessesquires

Differential Revision: D4016023

fbshipit-source-id: c75f9298fc73875a1cabad191fe2db6cb9ee4376
  • Loading branch information
Ryan Nystrom authored and Facebook Github Bot committed Oct 13, 2016
1 parent 4863974 commit 3947600
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----
Expand Down
5 changes: 5 additions & 0 deletions Source/IGListAdapter.m
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ - (void)updateObjects:(NSArray *)objects {
// 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 <IGListSectionType> *sectionController = [map sectionControllerForObject:object];
Expand All @@ -403,6 +406,8 @@ - (void)updateObjects:(NSArray *)objects {
// 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];
Expand Down
10 changes: 10 additions & 0 deletions Source/IGListSectionController.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
*/
@property (nonatomic, weak, nullable, readonly) id <IGListCollectionContext> 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.
Expand Down
4 changes: 4 additions & 0 deletions Source/Internal/IGListSectionControllerInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
25 changes: 25 additions & 0 deletions Tests/IGListAdapterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,29 @@ - (void)test_whenAdapterReleased_withSectionControllerStrongRefToCollectionView_
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

0 comments on commit 3947600

Please sign in to comment.