how to display data from plist in detail view using segue when map view annotation is pressed

620 views Asked by At

as the title describes i am having trouble displaying the data that i have in my plist for annotations in the map view project i am working on using segue in storyboard. i have the map view and all the annotations (pins) are showing their co ordinates properly. now i want to use segue to transition into a detail view when the user has pressed the detail disclosure button. so far i have the following which is an empty perform segue:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
[self performSegueWithIdentifier:@"Details" sender:view];
}

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

the details i want to display in detail view are declared as strings. as follows

@interface ItalyMapDetail : UIViewController{
IBOutlet UIImageView *appImage;
IBOutlet UITextView *appText;
IBOutlet UILabel *appName;

NSString *appImageString;
NSString *appTextString;
NSString *appNameString;

}

@property (nonatomic, retain) NSString *appImageString;
@property (nonatomic, retain) NSString *appTextString;
@property (nonatomic, retain) NSString *appNameString;
@property (nonatomic, strong) UIImage* image;

@end

and in .m file it is as follows

@synthesize appImageString, appTextString, appNameString;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
    // Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

appImage.image = [UIImage imageNamed:appImageString];
appText.text = appTextString;
appName.text = appNameString;
}

which is truly generic declaration of some strings in detail view. the segue identifier fires and the view transitions to detail view and back properly since i have a navigation controller already. now i know how to declare the strings in prepare for segue when it comes to tableview but i don't know how to declare these details from my plist in the segue in order to display the annotation details in the detail view controller. can anyone give me a hand with this.

oh by the way here is the decleration of the annotations which i derive from plist in my view did load if that helps.

NSMutableArray *annotations = [[NSMutableArray alloc]init];
NSString *path = [[NSBundle mainBundle] pathForResource:@"Map" ofType:@"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *anns = [dict objectForKey:@"Italy"];

for(int i = 0; i < [anns count]; i++) {
    float realLatitude = [[[anns objectAtIndex:i] objectForKey:@"Latitude"] floatValue];
    float realLongitude = [[[anns objectAtIndex:i] objectForKey:@"Longitude"] floatValue];

    Annotation *myAnnotation = [[Annotation alloc] init];
    CLLocationCoordinate2D theCoordinate;
    theCoordinate.latitude = realLatitude;
    theCoordinate.longitude = realLongitude;
    myAnnotation.coordinate = theCoordinate;
    myAnnotation.title = [[anns objectAtIndex:i] objectForKey:@"Title"];
    myAnnotation.subtitle = [[anns objectAtIndex:i] objectForKey:@"Subtitle"];
    [myMapView addAnnotation:myAnnotation];
    [annotations addObject:myAnnotation];
}

i know this might be very easy for most of you guys out there but i am truly stuck and i can use some help in code level.

Edit 1:

here is the code after the changes suggested :

    NSMutableArray *annotations = [[NSMutableArray alloc]init];
    NSString *path = [[NSBundle mainBundle] pathForResource:@"ItalyMap" ofType:@"plist"];
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
    NSArray *anns = [dict objectForKey:@"Italy"];

    for(int i = 0; i < [anns count]; i++) {
    float realLatitude = [[[anns objectAtIndex:i] objectForKey:@"Latitude"] floatValue];
    float realLongitude = [[[anns objectAtIndex:i] objectForKey:@"Longitude"] floatValue];

    Annotation *myAnnotation = [[Annotation alloc] init];
    CLLocationCoordinate2D theCoordinate;
    theCoordinate.latitude = realLatitude;
    theCoordinate.longitude = realLongitude;
    myAnnotation.coordinate = theCoordinate;
    myAnnotation.title = [[anns objectAtIndex:i] objectForKey:@"Title"];
    myAnnotation.subtitle = [[anns objectAtIndex:i] objectForKey:@"Subtitle"];
    [myMapView addAnnotation:myAnnotation];
    [annotations addObject:myAnnotation];

    myAnnotation.annotationData = [anns objectAtIndex:i];
}

}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(@"view for annotation works");

if([annotation isKindOfClass:[MKUserLocation class]])
    return nil;

static NSString *annotationIdentifier = @"AnnotationIdentifier";

MKPinAnnotationView *pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];

if (!pinView)
{
    pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];

    [pinView setPinColor:MKPinAnnotationColorGreen];
    pinView.animatesDrop = YES;
    pinView.canShowCallout = YES;

    UIImageView *iconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"acolon1.png"]];
    pinView.leftCalloutAccessoryView = iconView;

    pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
else
{
    pinView.annotation = annotation;
}

return pinView;
}

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
// Keep a reference to the callout's annotation data
self.selectedAnnotationData = [(Annotation *)view.annotation annotationData];

[self performSegueWithIdentifier:@"Details" sender:self];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"Details"])
{
    ItalyMapDetail *controller = segue.destinationViewController;
    controller.annotationData = self.selectedAnnotationData;
}
}

now i have added the dic to the annotation and detail view is imported. the only thing that is not showing still is the strings and the image in the detail view.

1

There are 1 answers

5
Steve Wilford On BEST ANSWER

You could pass the particular data object to the Annotation using

myAnnotation.annotationData = [anns objectAtIndex:i];

Then in prepareForSegue:sender: you could access the annotation data and pass it to the detail view controller.


Edit: Added sample code

Declare a property on the Annotation class:

@property (nonatomic, strong) NSDictionary *annotationData;

Declare a property on the same view controller as your map view:

@property (nonatomic, strong) NSDictionary *selectedAnnotationData;

And implement the map view delegate method:

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
    // Keep a reference to the callout's annotation data
    self.selectedAnnotationData = [(Annotation *)view.annotation annotationData];

    [self performSegueWithIdentifier:@"MY_SEGUE_IDENTIFIER" sender:self];
}

Then pass the annotation data to the subsequent controller in the prepareForSegue:sender: method:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"showPlattegrondDetails"])
    {
        ItalyMapDetail *controller = segue.destinationViewController;
        controller.annotationData = self.selectedAnnotationData;
    }
}

Edit 2: Based on edited question.

Without knowing the names of the keys in the plist, I can only point you in the direction you should be looking.

Your ItalyMapDetail controller should have the annotation data dictionary as provided in prepareForSegue:sender: of the previous controller, it should just be a case of using values from that dictionary to populate your UI...

Update your viewDidLoad method of the ItalyMapDetail controller as follows:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // temporary test: print out the annotation data so
    // we can see what we've got. This shouldn't be nil.
    NSLog("Annotation Data: %@", self.annotationData);

    // replace these keys with appropriate ones for your plist
    appImage.image = [UIImage imageNamed:self.annotationData[@"imageName"]];
    appText.text = self.annotationData[@"appText"];
    appName.text = self.annotationData[@"appName"];
}