Skip to content

Commit

Permalink
Adds viewForSupplementaryElementOfKind method to IGListCollectionContext
Browse files Browse the repository at this point in the history
Summary:
Returns the supplementary view in the collection at the specified index for the section controller.

 param `elementKind` The element kind of the supplementary view.
 param `index` The index of the desired cell.
 param `sectionController` The section controller requesting this information.

 return The collection reusable view, or `nil` if not found.

 warning This method may return `nil` if the cell is offscreen.

Reviewed By: maxolls

Differential Revision: D42726375

fbshipit-source-id: d9873440bd94140b88e7d2d56c0737ecf94925a8
  • Loading branch information
Ryan Mathews authored and facebook-github-bot committed Feb 1, 2023
1 parent a1b9c2d commit c708a10
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag
```

### Enhancements
- Added `viewForSupplementaryElementOfKind:atIndex:sectionController:` to `IGListAdapter`. [ryanmathews]

- Added `shouldDeselectItemAtIndex:` to `IGListSectionController` . [bladeofky](https://github.com/bladeofky)

- Added `shouldSelectItemAtIndex:` to `IGListSectionController` . [dirtmelon](https://github.com/dirtmelon)
Expand Down
31 changes: 31 additions & 0 deletions Source/IGListKit/IGListAdapter.m
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,37 @@ - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index
return nil;
}

- (__kindof UICollectionReusableView *)viewForSupplementaryElementOfKind:(NSString *)elementKind
atIndex:(NSInteger)index
sectionController:(IGListSectionController *)sectionController {
IGAssertMainThread();
IGParameterAssert(sectionController != nil);

// if this is accessed while a cell is being dequeued or displaying working range elements, just return nil
if (_isDequeuingSupplementaryView || _isSendingWorkingRangeDisplayUpdates) {
return nil;
}

NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:YES];
// prevent querying the collection view if it isn't fully reloaded yet for the current data set
if (indexPath != nil
&& indexPath.section < [self.collectionView numberOfSections]) {
// only return a supplementary view if it belongs to the section controller
UICollectionReusableView *view = [self.collectionView supplementaryViewForElementKind:elementKind atIndexPath:indexPath];

if (IGListExperimentEnabled(_experiments, IGListExperimentSkipViewSectionControllerMap)) {
if ([self sectionControllerForSection:indexPath.section] == sectionController) {
return view;
}
} else {
if ([self sectionControllerForView:view] == sectionController) {
return view;
}
}
}
return nil;
}

- (NSArray<UICollectionViewCell *> *)fullyVisibleCellsForSectionController:(IGListSectionController *)sectionController {
const NSInteger section = [self sectionForSectionController:sectionController];
if (section == NSNotFound) {
Expand Down
15 changes: 15 additions & 0 deletions Source/IGListKit/IGListCollectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ NS_SWIFT_NAME(ListCollectionContext)
- (nullable __kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index
sectionController:(IGListSectionController *)sectionController;

/**
Returns the supplementary view in the collection at the specified index for the section controller.
@param elementKind The element kind of the supplementary view.
@param index The index of the desired cell.
@param sectionController The section controller requesting this information.
@return The collection reusable view, or `nil` if not found.
@warning This method may return `nil` if the cell is offscreen.
*/
- (nullable __kindof UICollectionReusableView *)viewForSupplementaryElementOfKind:(NSString *)elementKind
atIndex:(NSInteger)index
sectionController:(IGListSectionController *)sectionController;

/**
Returns the fully visible cells for the given section controller.
Expand Down
5 changes: 5 additions & 0 deletions Source/IGListKit/Internal/IGListAdapter+UICollectionView.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section];
id <IGListSupplementaryViewSource> supplementarySource = [sectionController supplementaryViewSource];

// flag that a supplementary view is being dequeued in case it tries to access a supplementary view in the process
_isDequeuingSupplementaryView = YES;
UICollectionReusableView *view = [supplementarySource viewForSupplementaryElementOfKind:kind atIndex:indexPath.item];
_isDequeuingSupplementaryView = NO;

IGAssert(view != nil, @"Returned a nil supplementary view at indexPath <%@> from section controller: <%@>, supplementary source: <%@>", indexPath, sectionController, supplementarySource);

// associate the section controller with the cell so that we know which section controller is using it
Expand Down
2 changes: 2 additions & 0 deletions Source/IGListKit/Internal/IGListAdapterInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ IGListBatchContext
{
__weak UICollectionView *_collectionView;
BOOL _isDequeuingCell;
BOOL _isDequeuingSupplementaryView;

BOOL _isSendingWorkingRangeDisplayUpdates;
}

Expand Down
16 changes: 16 additions & 0 deletions Tests/IGListAdapterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -2146,4 +2146,20 @@ - (void)test_whenSectionControllerRemoved_thatDoesNotCrashOnInvalidatingLayout {
[sectionController.collectionContext invalidateLayoutForSectionController:sectionController completion:nil];
}

- (void)test_whenSettingSupplementaryView_thatViewForSupplementaryElementExists {
self.dataSource.objects = @[@0];
[self.adapter reloadDataWithCompletion:nil];

IGTestSupplementarySource *supplementarySource = [IGTestSupplementarySource new];
supplementarySource.collectionContext = self.adapter;
supplementarySource.supportedElementKinds = @[UICollectionElementKindSectionHeader];

IGListSectionController *controller = [self.adapter sectionControllerForObject:@0];
controller.supplementaryViewSource = supplementarySource;
supplementarySource.sectionController = controller;

[self.adapter performUpdatesAnimated:NO completion:nil];
XCTAssertNotNil([self.adapter viewForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndex:0 sectionController:controller]);
}

@end

0 comments on commit c708a10

Please # to comment.