2013-03-08 19 views
40

Mam listę adnotacji (MKPointAnnotation). Mam kontroler UIView, który jest dla całego widoku, kontroler implementujący MKMapView, który uważałem za przydatny do wykrywania interakcji użytkowników z mapą, mojego własnego kontrolera implementującego (podklasy) MKPointAnnotation, który mówi, jak wyświetlić adnotację.MKMapView MKPointAnnotation stuknij wydarzenie

Uderzyło mnie jednak wykrycie zdarzenia dotknięcia przez użytkownika.

Googling powiedział mi, że muszę coś zrobić, realizując poniższą funkcję.

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

oraz że muszę to zaimplementować w klasie, która implementuje MapViewDelegate (Protocol).

Ale jestem zdezorientowany i nie jestem w stanie iść naprzód. Czy ktoś może mi powiedzieć, gdzie co robić?

Przepraszamy za całe zamieszanie!

+0

trzeba ustawić znaczniki dla każdej adnotacji, tak że po dotknięciu żadnej adnotacji można uzyskać tag z powrotem z adnotacją i wywołać odpowiedni element danych z tablicy generowanie tych adnotacji. – yunas

+0

- (void) mapView: (MKMapView *) mapView annotationView: (MKAnnotationView *) view calloutAccessoryControlTapped: (UIControl *) control { NSLog (@ "tutaj"); } ..... Umieszczam tę funkcję we wszystkich trzech kontrolerach, ale żaden z nich nie jest wywoływany ... czy możesz mi powiedzieć, gdzie powinienem zdefiniować tę funkcję? –

Odpowiedz

95

Istnieją dwa sposoby wykrywania interakcji użytkownika z widoku opisu. Powszechną techniką jest zdefiniowanie objaśnienia (tej standardowej małej bańki popover, którą widzisz po kliknięciu pinezki w typowej aplikacji mapowej) dla swojej MKAnnotationView. I utworzeniu widoku opisu dla 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; 
} 

W ten sposób można uzyskać objaśnienie, ale jesteś dodając odpowiednie akcesoria, które jest, w moim przykładzie powyżej, ujawnienia wskaźnik. W ten sposób dotkną twojego widoku adnotacji (w moim przykładzie powyżej, pinezkę na mapie), zobaczą objaśnienie, a kiedy klikną na odpowiednie akcesorium objaśnienia (ten mały wskaźnik ujawnienia w tym przykładzie), twoja calloutAccessoryControlTapped jest nazywana (w moim przykładzie poniżej, wykonując segue do jakiegoś szczegółu widoku kontrolera):

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

to bardzo typowe doświadczenia użytkownika na ekranie małego iPhone.

Ale jeśli nie podoba ci się ten UX i nie chcesz standardowego objaśnienia, ale chcesz, aby coś innego się wydarzyło, możesz zdefiniować swój MKAnnotationView, aby nie wyświetlać objaśnienia, ale zamiast tego przechwycić to i zrób coś innego (na przykład na aplikacjach do map na iPada możesz pokazać bardziej wyrafinowany popover zamiast standardowego objaśnienia). Na przykład, można mieć swój MKAnnotationView nie wykazują objaśnienie:

- (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żna następnie ręcznie obsługiwać didSelectAnnotationView wykryć, kiedy użytkownik podsłuchu na MKAnnotationView w tym przykładzie pokazano popover:

- (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 migawek ekranu dla interfejsu użytkownika uzyskanych przez powyższy kod w my answer here.

+0

Witam, Wydaje się, że to nie działa dla iOS7 i wyżej. Wszelkie sugestie dotyczące poprawki dla iOS8? – roshi

+0

@roshi Przetestowałem to i działa dobrze w iOS 8. Czy ustawiłeś delegata widoku mapy? Jeśli nadal masz problemy, może opublikuj własne pytanie na temat S.O. ze szczegółowymi przykładami kodu, opisem tego, co próbowaliście, itp. – Rob

+0

@Rob Czy możecie rzucić okiem na http://stackoverflow.com/questions/30396754/ios-custom-annotation-a-view-below-the -annotation-pin i pomóż mi rozwiązać mój problem – iYoung

3

przycisk Add 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]; 

} 
+0

Czy możesz mi powiedzieć, gdzie powinienem je wdrożyć? Kontroler MKMapView? –

+0

@RaviVooda yaa Są nałożone na kodowanie MapViewpart. wszelkie inne problemy, które możesz mi zadać :) – Bajaj

+0

@RaviVooda Powinieneś zaimplementować je w 'delegacie' dla twojego' MKMapView'. Często określa się 'delegate' dla kontrolera widoku' MKMapView' dla widoku, który ma widok mapy na nim. Ale nie zapomnij ustawić delegata widoku mapy (w kodzie lub poprzez Konstruktor interfejsu). – Rob

4

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) 
    } 
}