diff --git a/CHANGELOG.md b/CHANGELOG.md index ea272a08..5bca331e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The changelog for `IGListKit`. Also see the [releases](https://github.com/instag ### Enhancements - Added `-[IGListSectionController didDeselectItemAtIndex:]` API to support default `UICollectionView` cell deselection. [Ryan Nystrom](https://github.com/rnystrom) (tbd) +- Added `-[IGListCollectionContext selectItemAtIndex:]` Select an item through IGListCollectionContext like `-[IGListCollectionContext deselectItemAtIndex:]`. [Marvin Nazari](https://github.com/MarvinNazari) (tbd) 3.0.0 ----- diff --git a/Source/IGListAdapter.m b/Source/IGListAdapter.m index 46b5efab..38aca16c 100644 --- a/Source/IGListAdapter.m +++ b/Source/IGListAdapter.m @@ -807,6 +807,16 @@ [self.collectionView deselectItemAtIndexPath:indexPath animated:animated]; } +- (void)selectItemAtIndex:(NSInteger)index + sectionController:(IGListSectionController *)sectionController + animated:(BOOL)animated + scrollPosition:(UICollectionViewScrollPosition)scrollPosition { + IGAssertMainThread(); + IGParameterAssert(sectionController != nil); + NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; + [self.collectionView selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; +} + - (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { diff --git a/Source/IGListCollectionContext.h b/Source/IGListCollectionContext.h index 60a3a183..e137e81c 100644 --- a/Source/IGListCollectionContext.h +++ b/Source/IGListCollectionContext.h @@ -99,6 +99,19 @@ NS_SWIFT_NAME(ListCollectionContext) sectionController:(IGListSectionController *)sectionController animated:(BOOL)animated; +/** + Selects a cell in the collection. + + @param index The index of the item to select. + @param sectionController The section controller requesting this information. + @param animated Pass `YES` to animate the change, `NO` otherwise. + @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. + */ +- (void)selectItemAtIndex:(NSInteger)index + sectionController:(IGListSectionController *)sectionController + animated:(BOOL)animated + scrollPosition:(UICollectionViewScrollPosition)scrollPosition; + /** Dequeues a cell from the collection view reuse pool. diff --git a/Source/IGListStackedSectionController.m b/Source/IGListStackedSectionController.m index fcf720d0..8ab555c2 100644 --- a/Source/IGListStackedSectionController.m +++ b/Source/IGListStackedSectionController.m @@ -225,6 +225,14 @@ static void * kStackedSectionControllerIndexKey = &kStackedSectionControllerInde [self.collectionContext deselectItemAtIndex:offsetIndex sectionController:self animated:animated]; } +- (void)selectItemAtIndex:(NSInteger)index + sectionController:(IGListSectionController *)sectionController + animated:(BOOL)animated + scrollPosition:(UICollectionViewScrollPosition)scrollPosition { + const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + [self.collectionContext selectItemAtIndex:offsetIndex sectionController:self animated:animated scrollPosition:scrollPosition]; +} + - (UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { diff --git a/Tests/IGListAdapterTests.m b/Tests/IGListAdapterTests.m index 14a9e1d9..2fe33f47 100644 --- a/Tests/IGListAdapterTests.m +++ b/Tests/IGListAdapterTests.m @@ -986,6 +986,15 @@ XCTAssertFalse([[self.collectionView cellForItemAtIndexPath:path] isSelected]); } +- (void)test_whenSelectingThroughContext_thatCellSelected { + self.dataSource.objects = @[@1, @2, @3]; + [self.adapter reloadDataWithCompletion:nil]; + + NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:0]; + [self.adapter selectItemAtIndex:0 sectionController:[self.adapter sectionControllerForObject:@1] animated:NO scrollPosition:UICollectionViewScrollPositionTop]; + XCTAssertTrue([[self.collectionView cellForItemAtIndexPath:path] isSelected]); +} + - (void)test_whenScrollingToIndex_withSectionController_thatPositionCorrect { self.dataSource.objects = @[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19]; [self.adapter reloadDataWithCompletion:nil]; diff --git a/Tests/IGListStackSectionControllerTests.m b/Tests/IGListStackSectionControllerTests.m index 759d9866..ae275f51 100644 --- a/Tests/IGListStackSectionControllerTests.m +++ b/Tests/IGListStackSectionControllerTests.m @@ -826,6 +826,20 @@ static const CGRect kStackTestFrame = (CGRect){{0.0, 0.0}, {100.0, 100.0}}; XCTAssertFalse([[self.collectionView cellForItemAtIndexPath:path] isSelected]); } +- (void)test_whenSelectingChildSectionControllerIndex_thatCorrectCellSelected { + [self setupWithObjects:@[ + [[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]], + [[IGTestObject alloc] initWithKey:@1 value:@[@1, @1]] + ]]; + + NSIndexPath *path = [NSIndexPath indexPathForItem:1 inSection:1]; + + IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects.lastObject]; + IGListSectionController *section = stack.sectionControllers.lastObject; + [section.collectionContext selectItemAtIndex:0 sectionController:section animated:NO scrollPosition:UICollectionViewScrollPositionTop]; + XCTAssertTrue([[self.collectionView cellForItemAtIndexPath:path] isSelected]); +} + - (void)test_whenRemovingSection_withWorkingRange_thatChildSectionControllersReceiveEvents { [self setupWithObjects:@[ [[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],