MKMapView mkpointannotation tap event

Mam listę adnotacji (MKPointAnnotation). Mam UIViewController, który jest dla całego widoku, kontroler wykonawczy MKMapView, który moim zdaniem jest przydatny do wykrywania interakcji użytkowników z mapą, mój własny kontroler implementacyjny (podklasa) MKPointAnnotation, który mówi, jak pokazać adnotację.

Jednak uderza mnie wykrycie zdarzenia dotknięcia przez użytkownika.

Googling powiedział mi, że muszę coś zrobić, wdrażając następujące funkcja.

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control

A także, że muszę to zaimplementować w jakiejś klasie, która implementuje MapViewDelegate (protokół).

Ale jestem zdezorientowany i nie mogę ruszyć do przodu. Czy ktoś może mi powiedzieć gdzie mam co robić? Przepraszam za to całe zamieszanie!
Author: iDroid, 2013-03-08

3 answers

Istnieją dwa sposoby wykrywania interakcji użytkownika z widokiem adnotacji. Typową techniką jest zdefiniowanie przycisku (standardowego małego bańki wyskakującego, który widzisz po dotknięciu pinu w typowej aplikacji map) dla twojego MKAnnotationView. I tworzysz widok adnotacji dla swojej adnotacji w standardowej metodzie viewForAnnotation:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
    annotationView.canShowCallout = YES;
    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

    return annotationView;
}

Robiąc to, dostajesz wezwanie, ale dodajesz odpowiednie akcesorium, które jest, w moim przykładzie powyżej, wskaźnikiem ujawnienia. W ten sposób stukają w twoje widok adnotacji (w moim przykładzie powyżej, pin na mapie), widzą wywołanie, a gdy dotkną prawego akcesorium tego wywołania (mały wskaźnik ujawnienia w tym przykładzie), Twój calloutAccessoryControlTapped jest wywoływany (w moim przykładzie poniżej, wykonując segue do kontrolera widoku szczegółów): {]}

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

To bardzo typowe doświadczenie użytkownika na małym ekranie iPhone ' a.

Ale jeśli nie podoba Ci się ten UX i nie chcesz standardowego wywołania, ale raczej chcesz, aby stało się coś innego, możesz można zdefiniować swój MKAnnotationView tak, że wywołanie nie jest wyświetlany, ale zamiast przechwycić go i zrobić coś innego(na przykład w aplikacjach iPad maps, możesz pokazać trochę bardziej wyrafinowane popover zamiast standardowego wywołania). Na przykład, możesz mieć MKAnnotationView nie pokazywać wywołania:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
    annotationView.canShowCallout = NO;

    return annotationView;
}

Ale możesz ręcznie obsługiwać didSelectAnnotationView, aby wykryć, kiedy użytkownik dotknął twojego MKAnnotationView, w tym przykładzie pokazując wyskakujące okienko:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    [mapView deselectAnnotation:view.annotation animated:YES];

    DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"];
    controller.annotation = view.annotation;
    self.popover = [[UIPopoverController alloc] initWithContentViewController:controller];
    self.popover.delegate = self;
    [self.popover presentPopoverFromRect:view.frame
                                  inView:view.superview
                permittedArrowDirections:UIPopoverArrowDirectionAny
                                animated:YES];
}

Dołączam kilka zrzutów ekranu dla interfejsu użytkownika powyższy kod znajduje się w moja odpowiedź tutaj .

 101
Author: Rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:22

Robs przykład dla Swift 3:

class MapViewController: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()

        // Create map view in storyboard
        view.delegate = self
    }
}

extension MapViewController: MKMapViewDelegate
{
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
    {
        let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "annotationView")
        annotationView.canShowCallout = true
        annotationView.rightCalloutAccessoryView = UIButton.init(type: UIButtonType.detailDisclosure)

        return annotationView
    }

    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)
    {
        guard let annotation = view.annotation else
        {
            return
        }

        let urlString = "http://maps.apple.com/?sll=\(annotation.coordinate.latitude),\(annotation.coordinate.longitude)"
        guard let url = URL(string: urlString) else
        {
            return
        }

        UIApplication.shared.openURL(url)
    }
}
 5
Author: RhodanV5500,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-30 10:53:38

Dodaj przycisk w tej metodzie

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation 
{
  pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
  pinView.canShowCallout = YES;
}

Then callout method
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
      InfoView *infoView = [[InfoView alloc]initWithNibName:@"InfoView" bundle:nil];
        [self.navigationController pushViewController:infoView animated:YES];

} 
 4
Author: Bajaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-24 11:26:36