4

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

Dharmesh Dhorajiya
  • 3,976
  • 9
  • 30
  • 39
AJ112
  • 5,291
  • 7
  • 45
  • 60
  • See dasblinkenlight's edit below, and change your updated code to his. It should take care of what you are trying to do! :) – lnafziger May 05 '13 at 02:21

1 Answers1

10

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];
}
Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    Clearly, that syntax is useful if going to another storyboard. But if the same storyboard, just use `self.storyboard`, e.g., `UIViewController* vc = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];` – Rob May 05 '13 at 00:12
  • should i just remove the segue connection between these view controller? and how can use "vc" to pass data ? – AJ112 May 05 '13 at 00:14
  • @AJ112 Yes, you need to remove the segue. The rest of your method does not change, starting with using `detailViewController.passedData = object;` to pass the data. – Sergey Kalinichenko May 05 '13 at 00:15
  • 1
    @rdelmar Of course I meant `self`, thanks! BTW, feel free to edit answers when you see obviously incorrect small stuff like that :) Thanks again! – Sergey Kalinichenko May 05 '13 at 01:50
  • +1, I changed the variable name "vc" to "detailViewController" in order for it to work with the rest of the method. – lnafziger May 05 '13 at 02:22
  • 2
    @gotnull This is not surprising, considering that the question pre-dates Swift by nearly a year. If you are looking for an answer with Swift, consider asking a separate question. – Sergey Kalinichenko Jun 27 '14 at 01:59