Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: Storyboard CollectionView segue not being triggered

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!

like image 413
phil swenson Avatar asked Sep 28 '13 19:09

phil swenson


3 Answers

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.

like image 51
Pulkit Goyal Avatar answered Nov 16 '22 12:11

Pulkit Goyal


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.

like image 33
Luke Avatar answered Nov 16 '22 13:11

Luke


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

like image 24
mmackh Avatar answered Nov 16 '22 13:11

mmackh