Add IGListCollectionContext API to get visible indexes.

Summary:
Add IGListCollectionContext API to get visible indexes:
`- (NSArray<NSIndexPath *> *)visiblePathsForSectionController:(IGListSectionController<IGListSectionType> *) sectionController`

Issue fixed: #465

- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)
Closes https://github.com/Instagram/IGListKit/pull/507

Differential Revision: D4621418

Pulled By: jessesquires

fbshipit-source-id: 4b55500c83ca1b911c418e5857756bb076fc80e4
This commit is contained in:
Alex Mathers 2017-02-28 14:26:18 -08:00 committed by Facebook Github Bot
parent f639cdd287
commit 2a0b4c990a
6 changed files with 97 additions and 0 deletions

View file

@ -39,6 +39,9 @@ This release closes the [3.0.0 milestone](https://github.com/Instagram/IGListKit
- Invalidate the layout of a section controller and control the transition with `UIView` animation APIs. [Ryan Nystrom](https://github.com/rnystrom) [(#499)](https://github.com/Instagram/IGListKit/pull/499)
- Added `-[IGListAdapter visibleIndexPathsForSectionController:]` API. [Malecks](https://github.com/Malecks) [(#465)](https://github.com/Instagram/IGListKit/pull/465)
### Fixes
- Gracefully handle a `nil` section controller returned by an `IGListAdapterDataSource`. [Ryan Nystrom](https://github.com/rnystrom) [(tbd)](https://github.com/Instagram/IGListKit/pull/tbd)

View file

@ -865,6 +865,19 @@
return cells;
}
- (NSArray<NSIndexPath *> *)visibleIndexPathsForSectionController:(IGListSectionController<IGListSectionType> *) sectionController {
NSMutableArray *paths = [NSMutableArray new];
UICollectionView *collectionView = self.collectionView;
NSArray *visiblePaths = [collectionView indexPathsForVisibleItems];
const NSInteger section = [self sectionForSectionController:sectionController];
for (NSIndexPath *path in visiblePaths) {
if (path.section == section) {
[paths addObject:path];
}
}
return paths;
}
- (void)deselectItemAtIndex:(NSInteger)index
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
animated:(BOOL)animated {

View file

@ -58,6 +58,14 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (NSArray<UICollectionViewCell *> *)visibleCellsForSectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Returns the visible paths for the given section controller.
@param sectionController The section controller requesting this information.
@return An array of visible index paths, or an empty array if none are found.
*/
- (NSArray<NSIndexPath *> *)visibleIndexPathsForSectionController:(IGListSectionController<IGListSectionType> *) sectionController;
/**
Deselects a cell in the collection.

View file

@ -187,6 +187,18 @@ static void * kStackedSectionControllerIndexKey = &kStackedSectionControllerInde
return cells;
}
- (NSArray<NSIndexPath *> *)visibleIndexPathsForSectionController:(IGListSectionController<IGListSectionType> *)sectionController {
NSMutableArray *paths = [NSMutableArray new];
id<IGListCollectionContext> collectionContext = self.collectionContext;
NSArray *visiblePaths = [collectionContext visibleIndexPathsForSectionController:self];
for (NSIndexPath *path in visiblePaths) {
if (self.sectionControllersForItems[path.item] == sectionController) {
[paths addObject:path];
}
}
return paths;
}
- (void)deselectItemAtIndex:(NSInteger)index sectionController:(IGListSectionController<IGListSectionType> *)sectionController animated:(BOOL)animated {
const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index];
[self.collectionContext deselectItemAtIndex:offsetIndex sectionController:self animated:animated];

View file

@ -313,6 +313,21 @@ XCTAssertEqual(CGPointEqualToPoint(point, p), YES); \
XCTAssertEqual([self.adapter visibleCellsForSectionController:sectionController6].count, 0);
}
- (void)test_whenCellsExtendBeyondBounds_thatVisibleIndexPathsExistForSectionControllers {
self.dataSource.objects = @[@2, @3, @4, @5, @6];
[self.adapter reloadDataWithCompletion:nil];
id sectionController2 = [self.adapter sectionControllerForObject:@2];
id sectionController3 = [self.adapter sectionControllerForObject:@3];
id sectionController4 = [self.adapter sectionControllerForObject:@4];
id sectionController5 = [self.adapter sectionControllerForObject:@5];
id sectionController6 = [self.adapter sectionControllerForObject:@6];
XCTAssertEqual([self.adapter visibleIndexPathsForSectionController:sectionController2].count, 2);
XCTAssertEqual([self.adapter visibleIndexPathsForSectionController:sectionController3].count, 3);
XCTAssertEqual([self.adapter visibleIndexPathsForSectionController:sectionController4].count, 4);
XCTAssertEqual([self.adapter visibleIndexPathsForSectionController:sectionController5].count, 1);
XCTAssertEqual([self.adapter visibleIndexPathsForSectionController:sectionController6].count, 0);
}
- (void)test_whenDataSourceAddsItems_thatEmptyViewBecomesVisible {
self.dataSource.objects = @[];
UIView *background = [UIView new];

View file

@ -416,6 +416,52 @@ static const CGRect kStackTestFrame = (CGRect){{0.0, 0.0}, {100.0, 100.0}};
XCTAssertEqual([stack visibleCellsForSectionController:section5].count, 0);
}
- (void)test_whenQueryingVisibleSectionControllers_withIndexPathsOffscreen_thatOnlyVisibleReturned {
[self setupWithObjects:@[
[[IGTestObject alloc] initWithKey:@0 value:@[@3, @4, @0, @5, @6]]
]];
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
IGListTestSection *section1 = stack.sectionControllers[0];
IGListTestSection *section2 = stack.sectionControllers[1];
IGListTestSection *section3 = stack.sectionControllers[2];
IGListTestSection *section4 = stack.sectionControllers[3];
IGListTestSection *section5 = stack.sectionControllers[4];
NSSet *visible1 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section1]];
NSSet *expected1 = [NSSet setWithArray:@[
[NSIndexPath indexPathForItem:0 inSection:0],
[NSIndexPath indexPathForItem:1 inSection:0],
[NSIndexPath indexPathForItem:2 inSection:0],
]];
XCTAssertEqualObjects(visible1, expected1);
NSSet *visible2 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section2]];
NSSet *expected2 = [NSSet setWithArray:@[
[NSIndexPath indexPathForItem:3 inSection:0],
[NSIndexPath indexPathForItem:4 inSection:0],
[NSIndexPath indexPathForItem:5 inSection:0],
[NSIndexPath indexPathForItem:6 inSection:0],
]];
XCTAssertEqualObjects(visible2, expected2);
NSSet *visible3 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section3]];
NSSet *expected3 = [NSSet setWithArray:@[]];
XCTAssertEqualObjects(visible3, expected3);
NSSet *visible4 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section4]];
NSSet *expected4 = [NSSet setWithArray:@[
[NSIndexPath indexPathForItem:7 inSection:0],
[NSIndexPath indexPathForItem:8 inSection:0],
[NSIndexPath indexPathForItem:9 inSection:0],
]];
XCTAssertEqualObjects(visible4, expected4);
NSSet *visible5 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section5]];
NSSet *expected5 = [NSSet setWithArray:@[]];
XCTAssertEqualObjects(visible5, expected5);
}
- (void)test_whenPerformingItemUpdates_thatMutationsMapToSectionControllers {
[self setupWithObjects:@[
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],