1

I'm trying to pass an object (PFObject) from an view controller to another,

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    RestauCardViewController *restauCard = [[RestauCardViewController alloc]init];
    RestaurantAnnotation *restoAnnotation = (RestaurantAnnotation *)view.annotation;

    restauCard.restaurant = restoAnnotation.restaurant;
    [self performSegueWithIdentifier:@"segueToCard" sender:nil];
}

When I try to display the object in the other view controller I got null:

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>

@interface RestauCardViewController : UIViewController

@property(nonatomic) PFObject *restaurant;

@end

This is my viewDidLoad function

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    NSLog(@"The restaurant name is : %@",_restaurant[@"nom"]);
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
  • See http://stackoverflow.com/questions/14805954/mkannotationview-push-to-view-controller-when-detaildesclosure-button-is-clicked. Instead of using a property or ivar to store the selection, pass the annotation `view` as `sender`. It makes the code more self-contained and uses functionality already provided by the api. –  May 05 '15 at 11:00

3 Answers3

2

You have to set the restaurent inside the UIViewController method "prepareSegue...". It's called after you performeSegueWithIdentifier, so the destination controller is accessible and you can test the segue.identifier and set the restaurent to the controller.

Example :

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@"segueRestaurentDetails"]) {

        RestauCardViewController *destController = (RestaurentDetailsViewController *)segue.destinationViewController;
        destController.restaurant = (RestaurantAnnotation *)view.annotation;
}
David Ansermot
  • 6,052
  • 8
  • 47
  • 82
  • Thank you, but how i can access to the view from the prepareForSegue method ? – Aissa El Ouafi May 05 '15 at 09:30
  • You can store it before calling "performeSegueWithIdentifier" inside a private variable like `@property (nonatomic, strong) UIView *viewToDisplay;` . Then you get it like `(RestaurantAnnotation *)_viewToDisplay.annotation;` – David Ansermot May 05 '15 at 09:32
  • Don't use a property for this, it's accessible from the outside of the class which you don't need. Use an ivar instead ; see my answer for more details. Both our answers are fairly close to each other – Gil Sand May 05 '15 at 09:35
  • Private properties declared in `@interaface` in **.m** are not accessible from outside. ivar are no more needed... update to the last objective-c practices please. – David Ansermot May 05 '15 at 09:42
2

You need to use -prepareForSegue to manage this situation, and you'll need an iVar to keep the restaurant name.

So in the top of your map's .m file, add an ivar NSString

@implementation yourViewController{

    NSString *sRestName;   //This is empty until the user selects a restaurant

}

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    sRestName = //Set the name of your restaurent here, it's just a string. 
                //You could set any other type of object (a restaurent object or a PFOjbect or anything, 
               //just change the ivar accordingly
    [self performSegueWithIdentifier:@"segueToCard" sender:nil];
}

What you're going to do is replace your old code with the code just above, you just need to perform the segue to call the following method.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 

    if([segue.identifier isEqualToString:@"fromHomeToList"]){
        RestauCardViewController *vc = (RestauCardViewController*)segue.destinationViewController;
        vc.restaurant = sRestName; //here you're just giving the property of the new controller the content of your ivar. 
}

That way you can pass an object from your map tap to your next controller. You're also sure it will never be nil because the user tapped it ; if it was nil, well, he couldn't have tapped it in the first place !

Note that I assumed you were using a string for your restaurant name, but if you change the ivar on the top, you can use anything you want, as long as you can retrieve it from tapping on the map. If you can't, I need more details to walk you through another solution.

Ask me if you have any quesiton, otherwise this should work !

Gil Sand
  • 5,802
  • 5
  • 36
  • 78
0

Implement prepareForSegue:sender: method in ViewController

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"segueToCard"]) {
        RestauCardViewController *controller = (RestauCardViewController *)segue.destinationViewController;
        controller.restaurant = (RestaurantAnnotation *)view.annotation;
    }
}
Elliot Li
  • 452
  • 1
  • 5
  • 17