1
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{    
    //if it's user location, return nil
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    //try to dequeue an existing pin view first
    static NSString* AnnotationIdentifier = @"AnnotationIdentifier";
    MKPinAnnotationView* pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
    pinView.animatesDrop = YES;
    pinView.canShowCallout = YES;
    pinView.pinColor = MKPinAnnotationColorRed;

    //button on the right for popup for pins
    UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [rightButton setTitle:annotation.title forState:UIControlStateNormal];
    [rightButton addTarget:self 
                    action:@selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
    pinView.rightCalloutAccessoryView = rightButton;

    //zoom button on the left of popup for pins
    UIButton* leftButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
    [leftButton setTitle:annotation.title forState:UIControlStateNormal];
    [leftButton addTarget:self 
                    action:@selector(zoomToLocation:) forControlEvents:UIControlEventTouchUpInside];
    pinView.leftCalloutAccessoryView = leftButton;

    return pinView;
}

//for map view annotation right button
-(void)showDetails:(id)sender{
    NSLog(@"Annotation Click");
    //fypAppDelegate *appDelegate = (fypAppDelegate *)[[UIApplication sharedApplication] delegate];
    //Attraction *attraction = (Attraction *)[appDelegate.attractions objectAtIndex:sender];

    infoViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"info"];
    self.infoView = viewController;
    [self.navigationController pushViewController:infoView animated:true];
}

//for map view annotation left button
-(void)zoomToLocation:(id)sender{
    NSLog(@"Annotation Click");
}

Above is the delegate for the map annotations. I am able to show the pins and show the map annotation view but I don't know how to link the button events to the next view (infoViewController). So as you guys can see, the right button is the one I want to use to enable user to view more information about that place while the left button, I want to allow user to zoom in into the coordinates of that pin.

The data are from the database I've created. Below is how I did it just for reference (in case you guys might need it)

-(void)putPins
{
    fypAppDelegate *appDelegate = (fypAppDelegate *)[[UIApplication sharedApplication] delegate];   //get data
    [appDelegate readTopAttractions];   
    int i = 0;
    int count = appDelegate.attractions.count;
    self.mapAnnotations = [[NSMutableArray alloc] initWithCapacity:appDelegate.attractions.count];
    while (i < count) {
        Attraction *attraction = (Attraction *)[appDelegate.attractions objectAtIndex:i];
        i++;

        //Set coordinates for pin
        CLLocationCoordinate2D location;
        location.latitude = (double)[[attraction xCoor] doubleValue];
        location.longitude = (double)[[attraction yCoor] doubleValue];
        MapPin *mapPin = [[MapPin alloc] init];
        [mapPin setCoordinate:location];
        [mapPin setName: [attraction name]];
        NSString *desc = [attraction description];
        int i = 0, position;
        while(i < 50){
            if ([desc characterAtIndex:i] == ' '){
                position = i;
                i++;
            }
            else
                i++;
        }
        desc = [@"" stringByAppendingFormat:@"%@%@", [desc substringToIndex:position], @"..."];
        [mapPin setDescription: desc];
        [self.mapAnnotations addObject:mapPin];
    }

    [self.mapView addAnnotations:self.mapAnnotations];
}

please do tell me if you guys need more details. Thank you! =)

mLjH
  • 425
  • 2
  • 7
  • 11

2 Answers2

2

In your showDetails: and zoomToLocation: methods, you can get a reference to the annotation whose callout button was tapped by doing the following:

MapPin *ann = (MapPin *)[mapView.selectedAnnotations objectAtIndex:0];


In zoomToLocation: you can then zoom in to that annotation using:

[mapView setRegion:
    MKCoordinateRegionMakeWithDistance(ann.coordinate, 500, 500) 
        //500 meters vertical span, 500 meters horizontal span
    animated:YES];

In showDetails:, you can pass ann or its properties to the detail view.


By the way, instead of calling custom methods using addTarget in viewForAnnotation, you can use the map view's calloutAccessoryControlTapped delegate method which gives more direct access to the annotation that was tapped. For example:

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view 
    calloutAccessoryControlTapped:(UIControl *)control
{
    MapPin *ann = (MapPin *)view.annotation;

    if (control == view.rightCalloutAccessoryView)
    {
        NSLog(@"calloutAccessoryControlTapped: control=RIGHT");
        //show detail view (or you can call your custom method here)...
    }
    else
        if (control == view.leftCalloutAccessoryView)
        {
            NSLog(@"calloutAccessoryControlTapped: control=LEFT");
            //zoom in (or you can call your custom method here)...
        }
        else
        {
            NSLog(@"calloutAccessoryControlTapped: unknown control");
        }
}

Make sure you remove the addTarget calls from viewForAnnotation if you decide to use the calloutAccessoryControlTapped delegate method.

  • hi i tried using the calloutAccessoryControlTapped. but now i have another problem. The zooming part works fine now. well for the rightCalloutAccessoryView, I can't seem to 'push' to the next view by [self.navigationalController pushViewController:infoView animated:YES]. But I can [self.view addSubview:infoView.view], which is what I do not want. – mLjH Feb 04 '12 at 14:08
  • The current view controller must be in a navigation controller for the push to work. Or, you can use presentModalViewController instead. Or if you're using storyboard, you'll need to do it another way. –  Feb 04 '12 at 15:39
0

You want to zoom in to the particular pin? Is that right?

Therefore you can use the setRegion:animated: - method from MKMapView.

Example:

mapView = MKMapView   
location = CLLLocationCoordinate2D  
METERS_PER_MILE = 1609.344 (defined as a Constant)

MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(location, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:region];

[mapView setRegion:adjustedRegion animated:YES];

AppleDocs
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html

http://developer.apple.com/library/IOs/#documentation/MapKit/Reference/MapKitDataTypesReference/Reference/reference.html

Adrian P
  • 6,479
  • 4
  • 38
  • 55
matzino
  • 3,544
  • 1
  • 18
  • 37
  • i mean after I click the pin, and it pops up a annotation view which have a button. and I want to use that button to zoom into the pin. how do i even define 'location' – mLjH Feb 01 '12 at 16:41
  • You have location already defined in your putPins-Method. Use the same way to define the location again or check if you can reuse this property. – matzino Feb 02 '12 at 08:28