Adds viewForSupplementaryElementOfKind method to IGListCollectionContext

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
This commit is contained in:
Ryan Mathews 2023-02-01 14:15:50 -08:00 committed by Facebook GitHub Bot
parent a1b9c2ddb3
commit c708a10757
6 changed files with 71 additions and 0 deletions

View file

@ -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)

View file

@ -1051,6 +1051,37 @@ typedef struct OffsetRange {
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) {

View file

@ -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.

View file

@ -61,7 +61,12 @@
- (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

View file

@ -30,6 +30,8 @@ IGListBatchContext
{
__weak UICollectionView *_collectionView;
BOOL _isDequeuingCell;
BOOL _isDequeuingSupplementaryView;
BOOL _isSendingWorkingRangeDisplayUpdates;
}

View file

@ -2146,4 +2146,20 @@
[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