Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added -[IGListAdapter visibleCellsForObject:] API #442

Closed
wants to merge 5 commits into from

Conversation

Sherlouk
Copy link
Contributor

Changes in this pull request

  • Added -[IGListAdapter visibleCellsForObject:] API

Approach

  1. Get all visible cells
  2. Get the section for the object
  3. Filter cells where indexPath.section of cell is equal to the object
  4. Return

Pull request checklist

  • All tests pass. Demo project builds and runs.
  • I added test(s), an experiment, or detailed why my change isn't tested.
  • I added an entry to the CHANGELOG.md for any breaking changes, enhancements, or bug fixes.
  • I have reviewed the contributing guide

Purely additive, can go in 2.2.0 release? Hold off on changelog until agreed.
Wanting to learn some more ObjC so gave this a shot, would appreciate some nit picking/feedback

Closes #437

@Sherlouk Sherlouk added this to the 2.2.0 milestone Jan 22, 2017
Copy link

@zhubofei zhubofei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@Sherlouk
Copy link
Contributor Author

Turns out there's already a method for -[IGListCollectionContext visibleCellsForSectionController:]

https://instagram.github.io/IGListKit/Protocols/IGListCollectionContext.html#/c:objc(pl)IGListCollectionContext(im)visibleCellsForSectionController:

https://github.com/Instagram/IGListKit/blob/master/Source/IGListAdapter.m#L777-L788

Considering you can quite easily get the section controller from object using -[IGListAdapter sectionControllerForObject:] it doesn't seem too difficult to do this already?

@rnystrom Suggestions?

@rnystrom
Copy link
Contributor

@Sherlouk doh. Ya, maybe we should just recommend people use that API instead...

@Sherlouk
Copy link
Contributor Author

@rnystrom Was your API request, if you think the need is no longer necessary then close this and that issue 😄

@rnystrom
Copy link
Contributor

Lol I know, forgot that API existed. Might still be valuable to cut out the middle-layer steps. Could also return early if sectionController is nil.

@Sherlouk
Copy link
Contributor Author

Sorry, lost track here...

We saying in the old API to return early?
What steps do we want to take here

(Also pardon the test name 😂, only just realised I didn't change it)

@rnystrom
Copy link
Contributor

The old API will end up asserting if the section controller is nil. If you used this method by first getting the object, then the SC (in ObjC) you might assert:

id controller = [self.adapter sectionControllerForObject:object]; // can be nil
NSArray *cells = [self.adapter visibleCellsForSectionController:controller]; // assert if nil

Which means all your callsites have to look like:

id controller = [self.adapter sectionControllerForObject:object]; // can be nil
if (controller != nil) {
  NSArray *cells = [self.adapter visibleCellsForSectionController:controller]; // assert if nil
}

Which is kind of gross. Swift will be just as bad. Options are:

  • Remove the assert
  • Add visibleCellsForObject: method that returns early if a section controller isn't found for the object

We should also add a unit test that sends nil to visibleCellsForSectionController: even tho the param marked nonnull, in ObJC-land that can still happen and the compiler wont help you.

@rnystrom
Copy link
Contributor

@Sherlouk ok thought about it more. Let's do option 2 and move forward w/ this for 2.2 if you think that's doable 😄

@Sherlouk
Copy link
Contributor Author

Option 2 is good, want to raise a new issue to track progress on amending old functionality?
Will add another unit test as well testing if an object is not found that it returns empty


@return An array of collection view cells.
*/
- (NSArray<UICollectionViewCell *> *)visibleCellsForObject:(id)item;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: object as param name

IGAssert(section != NSNotFound, @"Section not found for object %@", item);

NSPredicate *controllerPredicate = [NSPredicate predicateWithBlock:^BOOL(UICollectionViewCell* cell, NSDictionary* bindings) {
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: calling self.collectionView inside this block will execute an extra objc_msgSend(...) every execution. Instead let's capture the collection view in a local variable that the block uses:

UICollectionView *collectionView = self.collectionView;
NSPredicate *predicate = [... ^{
  NSIndexPath *path = [collectionView indexPathForCell:cell];
}];


NSArray<UICollectionViewCell *> *visibleCells = [self.collectionView visibleCells];
NSInteger section = [self.sectionMap sectionForObject:item];
IGAssert(section != NSNotFound, @"Section not found for object %@", item);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually let's remove this. A use might be holding a ref to an expired object. I think it's ok to return an empty array in that case.

IGParameterAssert(item != nil);

NSArray<UICollectionViewCell *> *visibleCells = [self.collectionView visibleCells];
NSInteger section = [self.sectionMap sectionForObject:item];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: const

}];

NSArray<UICollectionViewCell *> *filteredCells = [visibleCells filteredArrayUsingPredicate:controllerPredicate];
return filteredCells;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: IMO just return [visibleCells filteredArrayUsingPredicate:controllerPredicate];

@Sherlouk
Copy link
Contributor Author

All valid comments, will work on it tonight!

@facebook-github-bot
Copy link
Contributor

@Sherlouk updated the pull request - view changes

@Sherlouk
Copy link
Contributor Author

@rnystrom Just updated, should address all of your points!

Not sure if this is the best code to return an empty array, but it does seem to work?

return [NSArray new];

Copy link
Contributor

@jessesquires jessesquires left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

Let's add a changelog for 2.2.0

@facebook-github-bot
Copy link
Contributor

@Sherlouk updated the pull request - view changes

@facebook-github-bot
Copy link
Contributor

@jessesquires has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

1 similar comment
@facebook-github-bot
Copy link
Contributor

@jessesquires has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

jessesquires pushed a commit that referenced this pull request Feb 7, 2017
Summary:
- Added `-[IGListAdapter visibleCellsForObject:]` API

1. Get all visible cells
2. Get the section for the object
3. Filter cells where indexPath.section of cell is equal to the object
4. Return

- [x] All tests pass. Demo project builds and runs.
- [x] I added test(s), an experiment, or detailed why my change isn't tested.
- [ ] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)

-------------

Purely additive, can go in 2.2.0 release? Hold off on changelog until agreed.
Wanting to learn some more ObjC so gave this a shot, would appreciate some nit picking/feedback

Closes #437
Closes #442

Differential Revision: D4450259

Pulled By: jessesquires

fbshipit-source-id: 521583c669fc1160212a7c46a50d62d951cafa2e
@jessesquires jessesquires removed this from the 2.2.0 milestone Feb 23, 2017
@jessesquires jessesquires modified the milestones: 3.0.0, 2.2.0 Feb 23, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add -[IGListAdapter visibleCellsForObject:] API
5 participants