iOS: Storyboard CollectionView segue not being triggered
Solution 1
You cannot create segues directly from cells in a storyboard because the collectionview is populated dynamically through the data source. You should use the collectionView:didSelectItemAtIndexPath:
and perform the segue programatically using performSegueWithIdentifier:sender:
. Something like this:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:@"MySegueIdentifier" sender:self];
}
where MySegueIdentifier
is the identifier of the segue defined in storyboard.
Solution 2
TLDR: FOR A STORYBOARD, do not call registerClass:forCellWithReuseIdentifier:. It overrides what the storyboard sets up for the cell (including how segues are handled): How to set a UILabel in UICollectionViewCell
Brief setup
- Used a storyboard
- Created a new collection view controller using the Xcode template, setting it as a subclass of UICollectionViewController.
- Initially used the default UICollectionViewCell, adding a UILabel programmatically.
The generated UICollectionViewController code registered the cell in viewDidLoad:
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
First Issue: The prepareForSegue:sender: event was not firing, which brought me to this answer . I implemented the UICollectionViewDelegate and collectionView:didSelectItemAtIndexPath: event, then called the segue programmatically. This fixed my first issue.
Second Issue: I switched to a custom cell containing one label. After hooking everything up, the cell label was not displaying. After some digging, I found a solution contained in the link at the top of my answer.
Third Issue and Solution: I removed the registerClass:forCellWithReuseIdentifier: line. When I ran my app, the label appeared correctly, but when I tapped a cell, it called the prepareForSegue:sender event twice. By removing the registerClass:forCellWithReuseIdentifier line, the cell was processing cell touches directly, without the need of the delegate method. This is how I expected the storyboard to work. I deleted the collectionView:didSelectItemAtIndexPath: event, which resolved the double-firing of prepareForSegue:sender:. If you are using a storyboard, do not register the cell class. It overwrites what storyboard sets up.
Solution 3
Have you made your CollectionView Cell's connection in Triggered Segues
on selection
?
You can also trigger a segue programatically using
[self performSegueWithIdentifier:@"segueIdentifier" sender:nil]
in
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
phil swenson
Updated on July 28, 2022Comments
-
phil swenson almost 2 years
I have a UICollectionView controller embedded inside a navigation controller. The collectionView lists projects and each cell is supposed to segue to a ProjectDetail screen.
I simply cannot get the segue to trigger. If I simply drop a button on the nav bar and hook up a segue to the detail, it works. But triggering from my CollectionView cell doesn't.
Here is what the storyboard looks like: http://cl.ly/RfcM I do have a segue hooked up from the CollectionViewCell to the ProjectDetailViewController
Here's the relevant code inside my ProjectDetailViewController:
@interface ProjectCollectionViewController () { NSArray *feedPhotos; Projects *projects; } @end @implementation ProjectCollectionViewController - (void)viewDidLoad { [super viewDidLoad]; [self.collectionView registerClass:[FeedViewCell class] forCellWithReuseIdentifier:@"cell"]; [self loadData]; } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"selected %d", indexPath.row); Project *project = [projects getProject:indexPath.row]; NSLog(@"project = %@", project); } - (void)loadData { [self.projectLoader loadFeed:self.username onSuccess:^(Projects *loadedProjects) { NSLog(@"view did load on success : projects %@", loadedProjects); projects = loadedProjects; [self.collectionView reloadData]; } onFailure:^(NSError *error) { [self handleConnectionError:error]; }]; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return projects.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier = @"cell"; FeedViewCell *cell = (FeedViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]; cell.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0]; UIImageView *cellImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; Project *project = [projects getProject:indexPath.row]; NSString *imageUrl = [project coverPhotoUrl:200 forHeight:200]; NSLog(@"imageurl =>%@", imageUrl); if (imageUrl) { [cellImageView setImageWithURL:[NSURL URLWithString:imageUrl]]; } [cell addSubview:cellImageView]; cell.imageView = cellImageView; return cell; }
I'm guessing the problem is somewhere in how I'm hooking up the Cells to the CollectionView.
Any help would be greatly appreciated!
-
Pahnev over 9 yearsSo can someone tell me what has changed? Because here appcoda.com/ios-collection-view-tutorial we can see clearly that the connection is made in
Storyboard
and it works. -
preynolds over 8 years@Claude Do you know why using collectionView:didSelectItemAtIndePath: overwrites what storyboard sets up?
-
Wael Showair almost 8 yearsThis answer is outdated. Definitely, you can create segues directly in Storyboard.