iOS: Storyboard CollectionView segue not being triggered

10,868

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

Share:
10,868
phil swenson
Author by

phil swenson

Updated on July 28, 2022

Comments

  • phil swenson
    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
    Pahnev over 9 years
    So 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
    preynolds over 8 years
    @Claude Do you know why using collectionView:didSelectItemAtIndePath: overwrites what storyboard sets up?
  • Wael Showair
    Wael Showair almost 8 years
    This answer is outdated. Definitely, you can create segues directly in Storyboard.