Passing Data Between View Controllers DidSelectRowsAtIndexPath Storyboards

AJ112 picture AJ112 · May 5, 2013 · Viewed 7.4k times · Source

In a simple test app, i have tried to pass an array object named "thisArray" from the MasterViewController to the a string named "passedData" in the DetailViewController. I am using Storyboards and the UIViewController are embedded inside the navigation controller. Using the prepareForSegue method, i successfully passed the data between the UIViewController:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"pushData"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        DetailViewController *destViewController = segue.destinationViewController;
        destViewController.passedData = [thisArray objectAtIndex:indexPath.row];
    }
}

Now for some reasons i want to use didSelectRowsAtIndexPath instead of prepareForSegue. I have used this:

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSMutableString *object = thisArray[indexPath.row];
    detailViewController.passedData = object;   
}

But it didn't work. I have used the following:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
     detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    NSMutableString *object = thisArray[indexPath.row];
    detailViewController.passedData = object;
    [self.navigationController pushViewController:detailViewController animated:YES];  
}

But it also didn't work.

QUESTION:

1) How to correctly write didSelectRowsAtIndexPath to replace prepareForSegue?

2) If i use didSelectRowsAtIndexPath, do i need to remove the segue connection between the UIViewController in the Storyboard?

3) What if there is really no segue connection between the view controllers, how can i still pass the data between them using didSelectRowAtIndexPath?

Thanks!

UPDATE: Based on the answer and the comments i received, i have wrote the following:

First i have removed the segue connection between the controllers, set the StoryBoard id DetailViewController, the name of the class is also DetailViewController.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIStoryboard*  sb = [UIStoryboard storyboardWithName:@"DetailViewController"
                                                  bundle:nil];
    UIViewController* vc = [sb instantiateViewControllerWithIdentifier:@"DetailViewController"];

    NSMutableString *object = thisArray[indexPath.row];
    detailViewController.passedData = object;
    [self.navigationController pushViewController:detailViewController animated:YES];
}

but its getting crashed with the following error:

*** Terminating app due to uncaught exception NSInvalidArgumentException, reason: 'Could not find a storyboard named DetailViewController in bundle

Answer

Sergey Kalinichenko picture Sergey Kalinichenko · May 5, 2013

Your second attempt is nearly right. The only thing that's not quite correct is the way you instantiate a view controller from a storyboard: you use initWithNibNamed:, which is what you use with NIBs but not with storyboards. For storyboards, you need this:

UIStoryboard*  sb = [UIStoryboard storyboardWithName:@"theStoryboardId"
                                          bundle:nil];
// If this code is inside a method called by a controller that is itself instantiated
// from a storyboard, you can replace the above line with this.storyboard
UIViewController* detailViewController = [sb instantiateViewControllerWithIdentifier:@"DetailViewController"];

See this question for details.

Once you make the replacement, your code should work as expected.

EDIT :: Here is how your method would look:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIViewController* detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
    NSMutableString *object = thisArray[indexPath.row];
    detailViewController.passedData = object;
    [self.navigationController pushViewController:detailViewController animated:YES];
}