diff --git a/CHANGELOG.md b/CHANGELOG.md index 10206ede..b0eb4dc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ This release closes the [3.0.0 milestone](https://github.com/Instagram/IGListKit This release closes the [2.2.0 milestone](https://github.com/Instagram/IGListKit/milestone/4). +### Enhancements + +- Added `-[IGListAdapter visibleCellsForObject:]` API. [Sherlouk](https://github.com/Sherlouk) [(#442)](https://github.com/Instagram/IGListKit/pull/442) + ### 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) diff --git a/Source/IGListAdapter.h b/Source/IGListAdapter.h index 3e0f3722..7ed5422b 100644 --- a/Source/IGListAdapter.h +++ b/Source/IGListAdapter.h @@ -194,6 +194,15 @@ IGLK_SUBCLASSING_RESTRICTED */ - (NSArray *)visibleObjects; +/** + An unordered array of the currently visible cells for a given object. + + @param object An object in the list + + @return An array of collection view cells. + */ +- (NSArray *)visibleCellsForObject:(id)object; + /** Scrolls to the sepcified object in the list adapter. diff --git a/Source/IGListAdapter.m b/Source/IGListAdapter.m index 557f6ee6..0e121e68 100644 --- a/Source/IGListAdapter.m +++ b/Source/IGListAdapter.m @@ -414,6 +414,25 @@ return [visibleObjects allObjects]; } +- (NSArray *)visibleCellsForObject:(id)object { + IGAssertMainThread(); + IGParameterAssert(object != nil); + + const NSInteger section = [self.sectionMap sectionForObject:object]; + if (section == NSNotFound) { + return [NSArray new]; + } + + NSArray *visibleCells = [self.collectionView visibleCells]; + UICollectionView *collectionView = self.collectionView; + NSPredicate *controllerPredicate = [NSPredicate predicateWithBlock:^BOOL(UICollectionViewCell* cell, NSDictionary* bindings) { + NSIndexPath *indexPath = [collectionView indexPathForCell:cell]; + return indexPath.section == section; + }]; + + return [visibleCells filteredArrayUsingPredicate:controllerPredicate]; +} + #pragma mark - Layout diff --git a/Tests/IGListAdapterTests.m b/Tests/IGListAdapterTests.m index 82c38453..403ef24f 100644 --- a/Tests/IGListAdapterTests.m +++ b/Tests/IGListAdapterTests.m @@ -596,6 +596,46 @@ XCTAssertEqual(CGPointEqualToPoint(point, p), YES); \ XCTAssertEqualObjects(visibleObjects, expectedObjects); } +- (void)test_whenAdapterUpdated_thatVisibleCellsForObjectAreFound { + // each section controller returns n items sized 100x10 + self.dataSource.objects = @[@2, @10, @5]; + [self.adapter reloadDataWithCompletion:nil]; + self.collectionView.contentOffset = CGPointMake(0, 80); + [self.collectionView layoutIfNeeded]; + + UICollectionView *collectionView = self.collectionView; + NSArray *visibleCellsForObject = [[self.adapter visibleCellsForObject:@10] sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewCell* lhs, UICollectionViewCell* rhs) { + NSIndexPath *lhsIndexPath = [collectionView indexPathForCell:lhs]; + NSIndexPath *rhsIndexPath = [collectionView indexPathForCell:rhs]; + + if (lhsIndexPath.section == rhsIndexPath.section) { + return lhsIndexPath.item > rhsIndexPath.item; + } + + return lhsIndexPath.section > rhsIndexPath.section; + }]; + + XCTAssertEqual(visibleCellsForObject.count, 4); + XCTAssertEqual([self.collectionView indexPathForCell:visibleCellsForObject[0]].item, 6); + XCTAssertEqual([self.collectionView indexPathForCell:visibleCellsForObject[1]].item, 7); + XCTAssertEqual([self.collectionView indexPathForCell:visibleCellsForObject[2]].item, 8); + XCTAssertEqual([self.collectionView indexPathForCell:visibleCellsForObject[3]].item, 9); + + NSArray *visibleCellsForObjectTwo = [self.adapter visibleCellsForObject:@5]; + XCTAssertEqual(visibleCellsForObjectTwo.count, 5); +} + +- (void)test_whenAdapterUpdated_thatVisibleCellsForNilObjectIsEmpty { + // each section controller returns n items sized 100x10 + self.dataSource.objects = @[@2, @10, @5]; + [self.adapter reloadDataWithCompletion:nil]; + self.collectionView.contentOffset = CGPointMake(0, 80); + [self.collectionView layoutIfNeeded]; + + NSArray *visibleCellsForObject = [self.adapter visibleCellsForObject:@3]; + XCTAssertEqual(visibleCellsForObject.count, 0); +} + - (void)test_whenScrollVerticallyToItem { // # of items for each object == [item integerValue], so @2 has 2 items (cells) self.dataSource.objects = @[@1, @2, @3, @4, @5, @6];