I have a collection view, and I am trying to get the index of the cell that I am peeking and poping from.
Currently I am using indexPathForItemAtPoint:
however this always returns 0
no mater where I tap on the screen.
- (void)viewDidLoad {
[super viewDidLoad];
[self registerForPreviewingWithDelegate:self sourceView:self.collectionView];
}
- (UIViewController *) previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {
CellEditViewController *CEVC = [self.storyboard instantiateViewControllerWithIdentifier:@"detail"]; //The view I want peek/pop to
NSLog(@"Location: %f,%f", location.x, location.y);
NSLog(@"Index of: %lu", [[self.collectionView indexPathForItemAtPoint:location] row]);
[CEVC setPreferredContentSize:CGSizeMake(0.0, 320.0)];
return CEVC;
}
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
[self showViewController:viewControllerToCommit sender:self];
}
registerForPreviewingWithDelegate:sourceView:
to where I create each cell.previewingContext:viewControllerForLocation:
and previewingContext:commitViewController:
to the cell view method, this did not work for other reasons.I do not think this is an issue with previewing, because when I implemented the same thing with a UITapGestureRecognizer
, I got a similar output:
- (void) processDoubleTap:(UITapGestureRecognizer *)sender {
NSLog(@"Got tapped twice");
if (sender.state == UIGestureRecognizerStateEnded) {
CGPoint point = [sender locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point];
NSLog(@"Index was: %lu", [indexPath row]);
if (indexPath) {
NSLog(@"Index was double tapped");
}
}
}
2017-12-25 10:48:13.990523-0800 quickthings[3052:356150] Got tapped twice
2017-12-25 10:48:13.990843-0800 quickthings[3052:356150] Index was: 0
Here is what does happen, this is exactly what I want. The only other thing I would like to do is when the cell is tapped also be able to get the index of the tapped cell.
The (blue) UIView
is "linked" to the Collection View Controller (the top view controller in the second screenshot below).
The Cause: The main cause of the problem is how the CollectionViewController is setup in the storyboard. In summary these are the main issues with it:
So why is this causing the problem you are seeing. In the CollectionViewController when you refer to self.collectionView you are referring to the top level one which is not the one that is displaying the cells. That's not the one displaying the cells and in fact has no displayed cells so when you ask for the cell at a particular point it will always return nil and hence you get a row value of zero. If you were able to get access to the UICollectionView actually displaying the cells you could get the correct value.
Other than that there will be other issues that you haven't come across yet.
The Solution: There are basically two main solutions to this problem...
I have tried method 2 and this is what I had to do to get it working correctly:
Change the CollectionViewController from subclassing UICollectionViewController to subclassing UIViewController as it will just become a holder for the UICollectionView. You also need to make it support UICollectionViewDataSource and UICollectionViewDelegate directly as the UICollectionViewController already does this but the UIViewController doesn't. So change this line in CollectionViewController.m:
@interface CollectionViewController : UICollectionViewController
to this:
@interface CollectionViewController : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource>
Next in the storyboard change the top level view of the CollectionViewController back to a UIView (i.e. delete the UICollectionView in the class property). It's now just a holder for the real UICollectionView.
Next link the remaining UICollectionView that is setup in the storyboard to an IBOutlet in CollectionViewController.h called 'collectionView' so that all the references to self.collectionView are now referring to the correct thing.
One extra thing I had to do but I'm not sure why is change the cell identifier for the UITableViewController and UICollectionViewController so that they are not both 'Cell'. I just used 'TableCell' and 'CollectionCell'. If you don't do this they both get confused for some reason.
(I think that is all I did but if not I'm sure you will be able to handle any other issues)
Once all that has been done then the self.collectionView will be referring to the correct thing and you will get the correct index path in the - (UIViewController *) previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
method.
Bonus Round: Now some extra bonus comments. You appear to also have the same kind of issue with the TableViewController although it doesn't appear to be causing any issues at the moment. You may want to fix it though.
When I first ran the project I could not see anyway to add anything to the table because the text field and 'add' button were missing. This turned out to be because I was using an iPhone 8 simulator not an iPhone X simulator and once I switched everything was ok and I could see the text field and 'add' button. What this means is your interface is not adapting to the different device sizes correctly (at all really) and you should really address that.
Phew that ended up longer than I thought but hopefully will clear up the problem. Also as I had access to the git repository I could clone it and make my changes. I obviously haven't committed them as it's your repository but if you have any trouble understanding what I have done to get it to work I can commit them ether into your main branch or as a new branch.