1

I'm trying to pass an annotation's title to the second view controller with the calloutAccessoryControlTapped method like this:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
    //My second VC's UILabel outlet
    self.lblAnnotationTitle.text = view.annotation.title;
    [self performSegueWithIdentifier:@"gymDetails" sender:self];

}

When the view controller shows up, the label is not updated yet. Why is that so?

Also, is this the right way to pass properties to another view controller? If not, what is a better way to do this?

iamhx
  • 472
  • 6
  • 24

3 Answers3

1

The better way to do that is to do inside the -prepareForSegue method.
Inside that method by looking at the identifier you can grab the destinationViewController and update with you model.
Pay attention those aspects:

  1. if your view controller is contained inside a container view controller the destination view controller is the container view controller, so you need to extract your view controller from it
  2. Until the segue is finished your view controller view is not loaded, this means that the connections between the outlet are still at nil, so if you force the label to be updated with the text, nothing will happen. One way to do is pass the text as a "model" and update the label inside the -viewDidLoad method of the destination view controller.
Andrea
  • 26,120
  • 10
  • 85
  • 131
  • Is storyboard considered a container view controller? Because my second VC is also in the same storyboard as my first VC. – iamhx Feb 10 '17 at 08:50
  • Storyboard are simply a representation of your flow and UI, it's a sort of XML file, so no they are not a container view controller. For instance if you are presenting modally your view controller and it's contained a navigation controller, the navigation controller is the container returned from the destination view controller. – Andrea Feb 10 '17 at 08:53
  • I see... Yes I do have a navigation controller. How can I point it to the view controller if this is the case? – iamhx Feb 10 '17 at 08:55
  • Check navigation controller properties in the documentation, there is a stack of all your VC pushed and if I remember well there is also a topViewController property – Andrea Feb 10 '17 at 09:15
1

You should implement prepareForSegue and pass the value there

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"gymDetails"]) {
        GymDetailViewController *destViewController = segue.destinationViewController;
        destViewController.ivar = @"Your Text here";
    }
}

Then in your view did load you should do like

lblAnnotationTitle.text = ivar;
Inder Kumar Rathore
  • 39,458
  • 17
  • 135
  • 184
  • Does that mean that I will have to create a new UIViewController Class and define it in my storyboard? – iamhx Feb 10 '17 at 08:59
  • @iamhx without a class how you will update your second view controller's UILabel. You need to create a UIViewController Class for your second controller. – Antony Raphel Feb 10 '17 at 09:05
  • You have written `self.lblAnnotationTitle.text = view.annotation.title;` in your first view controller, where you are saying that `lblAnnotationTitle` is an IBOutlet of second view controller. It is not possible to assign the `IBOutlet`'s content from a different view controller's `self`. You need to create an object of second view controller, then only you can update the `IBOutlet`'s contents. @InderKumarRathore have shown you the perfect way to achieve your goal. :) – iPeter Feb 10 '17 at 09:08
  • @AntonyRaphel yes. I've went ahead to create a class for my second view controller. I imported the secondVC.h in my firstVC.m file and put my text into the ivar. But in the viewDidLoad my text is a null value. – iamhx Feb 10 '17 at 09:09
  • @iPeter, I linked the label to an IBOutlet in the FirstVC.h. My second VC is also using the same class which felt like a dumb thing to do so I added a new class. – iamhx Feb 10 '17 at 09:12
  • @iamhx check that you are passing `view.annotation.title` from 1st VC to 2nd VC. With debug mode check _annotation.title_ you are getting or not and pass it over 2nd VC. – Antony Raphel Feb 10 '17 at 09:14
  • @AntonyRaphel it's not. I declared a variable `CustomAnnotation *myAnnotation` in interface of FirstVC.m, and on `calloutAccessoryControlTapped`, I passed `view.annotation.title` to `myAnnotation.title`. In the secondVC.h interface, I declared an `NSString *myTitle` and on `viewDidLoad` I would pass the string to `self.lblTitle.text`. In the `prepareForSegue` I did `secondVC *vc = segue.destinationViewController` and passed `myAnnotation` to the secondVC's NSString. – iamhx Feb 10 '17 at 09:23
  • @iamhx with `NSLog` check before passing to 2nd VC, when you are tapped. – Antony Raphel Feb 10 '17 at 09:48
  • @AntonyRaphel, it's null until I initialized it with `[[CustomAnnotation alloc]init]` however the label is empty in the secondVC. – iamhx Feb 10 '17 at 09:49
  • @AntonyRaphel, it worked all of the sudden! Instead of declaring the global object `CustomAnnotation *myAnnotation`, i figured it would be better to use NSString instead since I just want the value of the string. – iamhx Feb 10 '17 at 09:53
  • 1
    I'm glad you found it! – Antony Raphel Feb 10 '17 at 09:55
0

Try this:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "xxx" {
        if let destination = segue.destination as? XXX {
            destination.xx = xx
        }
    }
}
jia ma
  • 198
  • 5