Pushing to a Detail View from a Table View Cell using Xcode Storyboard

flyers picture flyers · Sep 17, 2012 · Viewed 27.7k times · Source

I have a table view inside a View Controller. I can populate all my information inside the table view. However I am a bit lost for setting up the detail views. I believe each table cell needs a segue to a each detail view but not completely sure.

Here is my code. What am I missing to accomplish the segue from the table view to the detail views? Code:

.h 

@interface DetailViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>  
{ 
    IBOutlet UITableView *myTable;
    NSMutableArray *contentArray;
}

@property (strong, nonatomic) IBOutlet UITableView *myTable;

.m


- (void)viewDidLoad 
{
    contentArray = [[NSMutableArray alloc]init];
    [contentArray addObject:@"Espresso"];
    [contentArray addObject:@"Latte"];
    [contentArray addObject:@"Capicino"];
    [super viewDidLoad];
     // Do any additional setup after loading the view.
}

//Table Information
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [contentArray count];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath 
{

     [tableView deselectRowAtIndexPath:indexPath animated:YES];

     if([[contentArray objectAtIndex:indexPath.row]isEqualToString:@"EspressoViewController"])
     {
         EspressoViewController *espresso = [[EspressoViewController alloc]initWithNibName:@"EspressoViewController" bundle:nil];  
         [self.navigationController pushViewController:espresso animated:YES];
     }
     else if ([[contentArray objectAtIndex:indexPath.row] isEqualToString:@"Latte"])
     {
         LatteViewController *latte = [[LatteViewController alloc] initWithNibName:@"Latte" bundle:nil];
         [self.navigationController pushViewController:latte animated:YES];
     }

}

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath 
{
    [self tableView:tableView didSelectRowAtIndexPath:indexPath];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) 
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"CellIdentifier"];
    }

    NSString *cellValue = [contentArray objectAtIndex:indexPath.row];
    cell.textLabel.text = cellValue;

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.font = [UIFont systemFontOfSize:16];
    cell.detailTextLabel.text = @"Hot and ready";

    UIImage *image = [UIImage imageNamed:@"coffeeButton.png"];
    cell.imageView.image = image;

    cell.textLabel.text = [contentArray objectAtIndex:indexPath.row];
    return cell;
}

Answer

JoeBob_OH picture JoeBob_OH · Sep 24, 2012

I think you made this a little too complicated. Don't worry, I do the same thing often.

First, by sending tableView:didSelectRowAtIndexPath: from within tableView:accessoryButtonTappedForRowAtIndexPath: there is no difference between the two methods. Tapping the cell, or it's accessory button performs the same action. If you don't need the accessory button to perform a different action than tapping the cell itself, remove it.

Second, if you're using a storyboard, you do not need to alloc/initWithNib for your view controllers. Instead, use a segue. If you do this through the storyboard, you also don't need to programmatically push viewControllers onto your navigationController

Build your storyboard first:

  1. Drag out a UITableViewController. Make sure you set the class of the UITableViewController you dragged out to your own "DetailViewController" using the inspector pane on the right side.
  2. Then select this controller and using the menus choose "Editor->Embed In->Navigation Controller".
  3. Next, drag out three generic UIViewControllers. Set the class of one to "LatteViewController", another to "EspressoViewController", and a third to "CapicinoViewController" (using the inspector again).
  4. Control+drag from the UITableViewController over to each of these viewControllers and choose PUSH.
  5. Click on the little circle that's on the arrow between your UITableViewController and each of these viewControllers. In the inspector (on the right side), give each segue a unique name in the Identifier field. You will need to remember this name for your code. I would name them "EspressoSegue", "LatteSegue", and "CapicinoSegue". You'll see why in the code below.

Then put the following code in your UITableViewController:

- (void)tableView:(UITableView *)tableView 
didSelectRowAtIndexPath:(NSIndexPath*)indexPath {

//Build a segue string based on the selected cell
NSString *segueString = [NSString stringWithFormat:@"%@Segue",
                        [contentArray objectAtIndex:indexPath.row]];
//Since contentArray is an array of strings, we can use it to build a unique 
//identifier for each segue.

//Perform a segue.
[self performSegueWithIdentifier:segueString
                          sender:[contentArray objectAtIndex:indexPath.row]];
}

How you implement the rest is up to you. You may want to implement prepareForSegue:sender: in your UITableViewController and then use that method send information over to segue.destinationViewController.

Note that I passed the string from your contentArray as the sender for the segue. You can pass whatever you like. The string that identifies the cell seems like the most logical information to pass, but the choice is up to you.

The code posted above should perform the navigation for you.