Add -[IGListAdapter sectionControllerForSection:]

Summary:
Before the diff, you can lookup the object for a given section, and then lookup the section controller for that object, but this seems like a pretty valuable/common operation.
Closes https://github.com/Instagram/IGListKit/pull/477

Differential Revision: D4537479

Pulled By: rnystrom

fbshipit-source-id: ad47a243f0bb0fc72a362863dff2f00b0b640fab
This commit is contained in:
Adlai Holler 2017-02-09 11:25:11 -08:00 committed by Facebook Github Bot
parent e05cf1e320
commit 106054c181
4 changed files with 36 additions and 10 deletions

View file

@ -38,6 +38,8 @@ This release closes the [2.2.0 milestone](https://github.com/Instagram/IGListKit
- Added `-[IGListAdapter visibleCellsForObject:]` API. [Sherlouk](https://github.com/Sherlouk) [(#442)](https://github.com/Instagram/IGListKit/pull/442)
- Added `-[IGListAdapter sectionControllerForSection:]` API. [Adlai-Holler](https://github.com/Adlai-Holler) [(#477)](https://github.com/Instagram/IGListKit/pull/477)
### Fixes
- Fix bug where emptyView's hidden status is not updated after the number of items is changed with `insertInSectionController:atIndexes:` or related methods. [Peter Edmonston](https://github.com/edmonston) [(#395)](https://github.com/Instagram/IGListKit/pull/395)

View file

@ -126,6 +126,15 @@ IGLK_SUBCLASSING_RESTRICTED
*/
- (void)reloadObjects:(NSArray *)objects;
/**
Query the section controller at a given section index. Constant time lookup.
@param section A section in the list.
@return An section controller or `nil` if the section does not exist.
*/
- (nullable IGListSectionController <IGListSectionType> *)sectionControllerForSection:(NSInteger)section;
/**
Query the section index of a list. Constant time lookup.

View file

@ -339,6 +339,12 @@
#pragma mark - List Items & Sections
- (nullable IGListSectionController <IGListSectionType> *)sectionControllerForSection:(NSInteger)section {
IGAssertMainThread();
return [self.sectionMap sectionControllerForSection:section];
}
- (NSInteger)sectionForSectionController:(IGListSectionController <IGListSectionType> *)sectionController {
IGAssertMainThread();
IGParameterAssert(sectionController != nil);
@ -381,7 +387,7 @@
}
- (id<IGListSupplementaryViewSource>)supplementaryViewSourceAtIndexPath:(NSIndexPath *)indexPath {
IGListSectionController<IGListSectionType> *sectionController = [self.sectionMap sectionControllerForSection:indexPath.section];
IGListSectionController<IGListSectionType> *sectionController = [self sectionControllerForSection:indexPath.section];
return [sectionController supplementaryViewSource];
}
@ -443,7 +449,7 @@
- (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
IGAssertMainThread();
IGListSectionController <IGListSectionType> *sectionController = [self.sectionMap sectionControllerForSection:indexPath.section];
IGListSectionController <IGListSectionType> *sectionController = [self sectionControllerForSection:indexPath.section];
return [sectionController sizeForItemAtIndex:indexPath.item];
}
@ -641,7 +647,7 @@
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
IGListSectionController <IGListSectionType> * sectionController = [self.sectionMap sectionControllerForSection:section];
IGListSectionController <IGListSectionType> * sectionController = [self sectionControllerForSection:section];
IGAssert(sectionController != nil, @"Nil section controller for section %zi for item %@. Check your -diffIdentifier and -isEqual: implementations.",
section, [self.sectionMap objectForSection:section]);
const NSInteger numberOfItems = [sectionController numberOfItems];
@ -650,7 +656,7 @@
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
IGListSectionController<IGListSectionType> *sectionController = [self.sectionMap sectionControllerForSection:indexPath.section];
IGListSectionController<IGListSectionType> *sectionController = [self sectionControllerForSection:indexPath.section];
// flag that a cell is being dequeued in case it tries to access a cell in the process
_isDequeuingCell = YES;
@ -666,7 +672,7 @@
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
IGListSectionController<IGListSectionType> *sectionController = [self.sectionMap sectionControllerForSection:indexPath.section];
IGListSectionController<IGListSectionType> *sectionController = [self sectionControllerForSection:indexPath.section];
id <IGListSupplementaryViewSource> supplementarySource = [sectionController supplementaryViewSource];
UICollectionReusableView *view = [supplementarySource viewForSupplementaryElementOfKind:kind atIndex:indexPath.item];
IGAssert(view != nil, @"Returned a nil supplementary view at indexPath <%@> from section controller: <%@>, supplementary source: <%@>", indexPath, sectionController, supplementarySource);
@ -683,7 +689,7 @@
[collectionViewDelegate collectionView:collectionView didSelectItemAtIndexPath:indexPath];
}
IGListSectionController <IGListSectionType> * sectionController = [self.sectionMap sectionControllerForSection:indexPath.section];
IGListSectionController <IGListSectionType> * sectionController = [self sectionControllerForSection:indexPath.section];
[sectionController didSelectItemAtIndex:indexPath.item];
}
@ -698,7 +704,7 @@
// if the section controller relationship was destroyed, reconnect it
// this happens with iOS 10 UICollectionView display range changes
if (sectionController == nil) {
sectionController = [self.sectionMap sectionControllerForSection:indexPath.section];
sectionController = [self sectionControllerForSection:indexPath.section];
[self mapCell:cell toSectionController:sectionController];
}
@ -1054,17 +1060,17 @@
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd));
return [[self.sectionMap sectionControllerForSection:section] inset];
return [[self sectionControllerForSection:section] inset];
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd));
return [[self.sectionMap sectionControllerForSection:section] minimumLineSpacing];
return [[self sectionControllerForSection:section] minimumLineSpacing];
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd));
return [[self.sectionMap sectionControllerForSection:section] minimumInteritemSpacing];
return [[self sectionControllerForSection:section] minimumInteritemSpacing];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {

View file

@ -783,6 +783,15 @@ XCTAssertEqual(CGPointEqualToPoint(point, p), YES); \
XCTAssertEqual([self.adapter sectionForObject:@3], NSNotFound);
}
- (void)test_whenQueryingSectionControllerForSection_thatControllerReturned {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
XCTAssertEqual([self.adapter sectionControllerForSection:0], [self.adapter sectionControllerForObject:@0]);
XCTAssertEqual([self.adapter sectionControllerForSection:1], [self.adapter sectionControllerForObject:@1]);
XCTAssertEqual([self.adapter sectionControllerForSection:2], [self.adapter sectionControllerForObject:@2]);
}
- (void)test_whenReloadingData_withNoDataSource_thatCompletionCalledWithNO {
self.dataSource.objects = @[@1];
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListReloadDataUpdater new]