Send values from mapview to a detailview?

Discussion in 'iOS Programming' started by akesson, Oct 22, 2010.

  1. akesson macrumors newbie

    Joined:
    Oct 22, 2010
    #1
    Hi guys,

    I have a mapview with a few pins on it. The pins are loading its data from a plist-file (title, longitude and latitude). I've also added a detailview where you get more info about the pin that gets tapped.
    The pins are showing just fine on the map and I can tap on them to get to the detailview so my question is how do I send the, for example, the title from the mapview to my detailview when the disclosebutton is tapped?

    I know it's something like this detailViewController.title = annotation.title, but I don't know how to fetch the annotation data.

    Hope that somebody can get me on the right track :)

    Here's my code:

    RootViewController.h
    Code:
    @interface RootViewController : UIViewController <MKMapViewDelegate> {
    	IBOutlet MKMapView *map;
    	
    	NSArray *cam;
    }
    
    @end
    RootViewController.m
    Code:
    - (void)viewDidLoad {
        [super viewDidLoad];
    	
            map.delegate = self;
    	
    	cam = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] 
    														 pathForResource:@"Cam" 
    														 ofType:@"plist"]];
    	
    	double minLat = [[cam valueForKeyPath:@"@min.latitude"] doubleValue];
    	double maxLat = [[cam valueForKeyPath:@"@max.latitude"] doubleValue];
    	double minLon = [[cam valueForKeyPath:@"@min.longitude"] doubleValue];
    	double maxLon = [[cam valueForKeyPath:@"@max.longitude"] doubleValue];
    	
    	MKCoordinateRegion region;
    	region.center.latitude = (maxLat + minLat) / 2.0;
    	region.center.longitude = (maxLon + minLon) / 2.0;
    	region.span.latitudeDelta = (maxLat - minLat) * 1.05;
    	region.span.longitudeDelta = (maxLon - minLon) * 1.05;
    	map.region = region;
    	
    	for (NSDictionary *camDict in cam){
    		MyAnnotation *annotation = [[MyAnnotation alloc] initWithDictionary:camDict];
    		[map addAnnotation:annotation];
    		[annotation release];
    	}
    }
    
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
    	MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
        [annView setAnimatesDrop:YES];
        [annView setCanShowCallout:YES];
        [annView setSelected:YES];
        [annView setUserInteractionEnabled: YES];
        
        UIButton *discloseButton = [UIButton buttonWithType: UIButtonTypeDetailDisclosure];
        [discloseButton addTarget: self action: @selector(showMyView:) forControlEvents: UIControlEventTouchUpInside];
        annView.rightCalloutAccessoryView = discloseButton;
        
        return annView;
    }
    
    // Push to detailView with some data
    - (IBAction)showMyView:(id)sender {
    		
    	DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    	
            // something like this.
    	//detailViewController.title = annotation.title;
    	//detailViewController.tempAdress = annotation.subtitle;
    	
    	[self.navigationController pushViewController:detailViewController animated:YES];
    	[detailViewController release];
    												  
    }
    MyAnnotation.h
    Code:
    @interface MyAnnotation : NSObject <MKAnnotation> {
    	CLLocationCoordinate2D coordinate;
    	NSString *title;
    	NSString *subtitle;
    }
    
    @property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
    @property (nonatomic, copy) NSString *title;
    @property (nonatomic, copy) NSString *subtitle;
    MyAnnotation.m
    Code:
    - (id) initWithDictionary:(NSDictionary *) dict
    {
    	self = [super init];
    	if (self != nil) {
    		coordinate.latitude = [[dict objectForKey:@"latitude"] doubleValue];
    		coordinate.longitude = [[dict objectForKey:@"longitude"] doubleValue];
    		self.title = [dict objectForKey:@"name"];
    		self.subtitle = [dict objectForKey:@"address"];
    	}
    	return self;
    }
     
  2. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @
    #2
    I normally do this:
    Code:
    pin.rightCalloutAccessoryView =
        [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    
    And:
    Code:
    - (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {
        NSLog(@"%@", pin.annotation.title);
        ...
    }
    
    Hope this clarifies things :)
     
  3. akesson thread starter macrumors newbie

    Joined:
    Oct 22, 2010
    #3
    Thanks for a quick answer :)

    Hm, I get that I can fetch the title(s) in the viewForAnnotation-method. Seems very logical.
    Code:
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
    	
        MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
        [pin setAnimatesDrop:YES];
        [pin setCanShowCallout:YES];
        [pin setSelected:YES];
        [pin setUserInteractionEnabled: YES];
        
        UIButton *discloseButton = [UIButton buttonWithType: UIButtonTypeDetailDisclosure];
        [discloseButton addTarget: self action: @selector(showMyView:) forControlEvents: UIControlEventTouchUpInside];
        pin.rightCalloutAccessoryView = discloseButton;
    
        NSLog(@"%@", pin.annotation.title);
    	
        return pin;
    }
    However I can't figure out how to fetch it in my action-method. Feels like I banged my head agains the wall all day...
    Code:
    - (IBAction)showMyView:(id)sender {
        DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    	
        // Something like this --
        //detailViewController.title = pin.annotation.title;
    	
        [self.navigationController pushViewController:detailViewController animated:YES];
        [detailViewController release];
    												  
    } 
     
  4. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @
    #4
    Did you notice method mapView:annotationView:calloutAccessoryControlTapped: in my original reply?
     
  5. akesson thread starter macrumors newbie

    Joined:
    Oct 22, 2010
    #5
    Doh! Didn't notice that, I was probably to tired :rolleyes:

    Thank you very much ianray, it's working! :) :)


    Here's the code btw

    Code:
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
    	
        MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
        [pin setAnimatesDrop:YES];
        [pin setCanShowCallout:YES];
        [pin setSelected:YES];
        [pin setUserInteractionEnabled: YES];
        
        pin.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    	
        return pin;
    }
    Code:
    - (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {	
    	DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    	
    	detailViewController.title = pin.annotation.title;	
    	
    	[self.navigationController pushViewController:detailViewController animated:YES];
    	[detailViewController release];
    }
     
  6. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @
  7. akesson thread starter macrumors newbie

    Joined:
    Oct 22, 2010
    #7
    Hmm, still have one problem I can't figure out.

    If I want to add more than the title and the subtitle, a url for example (to be shown in the detailview).

    Shouldn't I be able just do like this to add a url:

    I'm getting an error saying: error: accessing unknown 'detailUrl' getter method

    MyAnnotation.h
    Code:
    @interface MyAnnotation : NSObject <MKAnnotation> {
    	CLLocationCoordinate2D coordinate;
    	NSString *title;
    	NSString *subtitle;
    	NSString *detailUrl;
    }
    
    @property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
    @property (nonatomic, copy) NSString *title;
    @property (nonatomic, copy) NSString *subtitle;
    @property (nonatomic, retain) NSString *detailUrl;
    MyAnnotation.m
    Code:
    - (id) initWithDictionary:(NSDictionary *) dict
    {
    	self = [super init];
    	if (self != nil) {
    		coordinate.latitude = [[dict objectForKey:@"latitude"] doubleValue];
    		coordinate.longitude = [[dict objectForKey:@"longitude"] doubleValue];
    		self.title = [dict objectForKey:@"name"];
    		self.subtitle = [dict objectForKey:@"adress"];
    		self.detailUrl = [dict objectForKey:@"url"];
    	}
    	return self;
    }
    and in my RootViewController.m
    Code:
    - (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {	
    	DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    	
    	detailViewController.title = pin.annotation.title;	
    	detailViewController.theUrl = pin.annotation.detailUrl;
    	
    	[self.navigationController pushViewController:detailViewController animated:YES];
    	[detailViewController release];
    }
    Thanks!
     
  8. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @
    #8
    The pin.annotation has type
    Code:
    id <MKAnnotation>
    You will need to cast to your data type (MyAnnotation).
     
  9. akesson thread starter macrumors newbie

    Joined:
    Oct 22, 2010
    #9
    I'm not by my computer atm, but I'm not really sure what you mean. Can you explain abit more? Sorry if I'm being stupid :eek:
     
  10. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @
    #10
    The type of pin.annotation is 'id <MKAnnotation>' -- you can check this from the documentation at: http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html%23//apple_ref/occ/intf/MKAnnotation.

    Now the object itself was allocated by you (and passed to MKMapView method addAnnotation).

    So we know that we can safely type-cast from 'id <MKAnnotation>' to MyAnnotation.

    Is that clearer? :)
     
  11. akesson thread starter macrumors newbie

    Joined:
    Oct 22, 2010
    #11
    YES! Thank you very very vey much :):):)

    (Don't know if this is what you meant, but it's working :D)

    Code:
    - (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {	
    	DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    	
    	MyAnnotation *theAnnotation = (MyAnnotation *) pin.annotation;
    	
    	detailViewController.title = theAnnotation.title;
    	detailViewController.url = theAnnotation.theUrl;
    	
    	[self.navigationController pushViewController:detailViewController animated:YES];
    	[detailViewController release];
    }
     
  12. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @

Share This Page