Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass prepareForSegue: an object

I have many annotations in a mapview (with rightCalloutAccessory buttons). The button will perform a segue from this mapview to a tableview. I want to pass the tableview a different object (that holds data) depending on which callout button was clicked.

For example: (totally made up)

  • annotation1 (Austin) -> pass data obj 1 (relevant to Austin)
  • annotation2 (Dallas) -> pass data obj 2 (relevant to Dallas)
  • annotation3 (Houston) -> pass data obj 3 and so on... (you get the idea)

I am able to detect which callout button was clicked.

I'm using prepareForSegue: to pass the data obj to the destination ViewController. Since I cannot make this call take an extra argument for the data obj I require, what are some elegant ways to achieve the same effect (dynamic data obj)?

Any tip would be appreciated.

like image 930
chizzle Avatar asked Oct 23 '11 04:10

chizzle


People also ask

What is segue in Objective C?

A segue defines a transition between two view controllers in your app's storyboard file. The starting point of a segue is the button, table row, or gesture recognizer that initiates the segue. The end point of a segue is the view controller you want to display.


2 Answers

Simply grab a reference to the target view controller in prepareForSegue: method and pass any objects you need to there. Here's an example...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {     // Make sure your segue name in storyboard is the same as this line     if ([[segue identifier] isEqualToString:@"YOUR_SEGUE_NAME_HERE"])     {         // Get reference to the destination view controller         YourViewController *vc = [segue destinationViewController];          // Pass any objects to the view controller here, like...         [vc setMyObjectHere:object];     } } 

REVISION: You can also use performSegueWithIdentifier:sender: method to activate the transition to a new view based on a selection or button press.

For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBAction in your code which uses performSegueWithIdentifier: method, like this...

// When any of my buttons are pressed, push the next view - (IBAction)buttonPressed:(id)sender {     [self performSegueWithIdentifier:@"MySegue" sender:sender]; }  // This will get called too before the view appears - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {     if ([[segue identifier] isEqualToString:@"MySegue"]) {          // Get destination view         SecondView *vc = [segue destinationViewController];          // Get button tag number (or do whatever you need to do here, based on your object         NSInteger tagIndex = [(UIButton *)sender tag];          // Pass the information to your destination view         [vc setSelectedButton:tagIndex];     } } 

EDIT: The demo application I originally attached is now six years old, so I've removed it to avoid any confusion.

like image 168
Simon Avatar answered Sep 24 '22 10:09

Simon


Sometimes it is helpful to avoid creating a compile-time dependency between two view controllers. Here's how you can do it without caring about the type of the destination view controller:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {     if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {         [segue.destinationViewController performSelector:@selector(setMyData:)                                                withObject:myData];     }  } 

So as long as your destination view controller declares a public property, e.g.:

@property (nonatomic, strong) MyData *myData; 

you can set this property in the previous view controller as I described above.

like image 25
TotoroTotoro Avatar answered Sep 24 '22 10:09

TotoroTotoro