Ich arbeite an einem MKMapView
mit dem üblichen farbigen Stift als Standortpunkt. Ich möchte, dass das Callout angezeigt wird, ohne den Pin zu berühren.
Wie soll ich das machen Das Aufrufen setSelected:YES
der Anmerkungsansicht hat nichts bewirkt. Ich denke darüber nach, eine Berührung des Stifts zu simulieren, bin mir aber nicht sicher, wie ich vorgehen soll.
Antworten:
Aber es gibt einen Haken, um die Lösung von benvolioT zum Laufen zu bringen, den Code
for (id<MKAnnotation> currentAnnotation in mapView.annotations) { if ([currentAnnotation isEqual:annotationToSelect]) { [mapView selectAnnotation:currentAnnotation animated:FALSE]; } }
sollte von
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
und nirgendwo anders angerufen werden .Die Reihenfolge, in der die verschiedenen Methoden wie
viewWillAppear
,viewDidAppear
vonUIViewController
und- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
aufgerufen werden, unterscheidet sich zwischen dem ersten Laden der Karte mit einem bestimmten Ort und dem anschließenden Anzeigen der Karte mit demselben Ort. Das ist etwas knifflig.quelle
mapView:didAddAnnotationViews:
. Dadurch wird sichergestellt, dass die Kartenansicht geladen wird und die Anmerkungsansichten platziert und bereit sind, die Callout-Blase anzuzeigen. Jede andere Möglichkeit kann funktionieren oder nicht, abhängig von der Verbindungsgeschwindigkeit, dem Cache-System, Anwendungsunterbrechungen usw.Ok, hier ist die Lösung für dieses Problem.
Verwenden Sie
MKMapView
dieselectAnnotation:animated
Methode, um das Callout anzuzeigen .quelle
Angenommen, Sie möchten, dass die letzte Anmerkungsansicht ausgewählt wird, können Sie den folgenden Code eingeben:
[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
im Delegierten unten:
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { //Here [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES]; }
quelle
Ok, um das Callout erfolgreich hinzuzufügen, müssen Sie selectAnnotation aufrufen: animiert, nachdem alle Annotationsansichten hinzugefügt wurden, mit den didAddAnnotationViews des Delegaten:
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{ for (id<MKAnnotation> currentAnnotation in mapView.annotations) { if ([currentAnnotation isEqual: annotationToSelect]) { [mapView selectAnnotation:currentAnnotation animated:YES]; } } }
quelle
Nachdem ich verschiedene Antworten auf diesen Thread ausprobiert hatte, kam ich schließlich auf diese Idee. Es funktioniert sehr zuverlässig, ich habe noch nicht gesehen, dass es fehlschlägt:
- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views; { for(id<MKAnnotation> currentAnnotation in aMapView.annotations) { if([currentAnnotation isEqual:annotationToSelect]) { NSLog(@"Yay!"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^ { [aMapView selectAnnotation:currentAnnotation animated:YES]; }); } } }
Der Block wird verwendet, um geringfügig zu verzögern, da ohne ihn das Callout möglicherweise nicht korrekt angezeigt wird.
quelle
Das funktioniert bei mir nicht. Ich vermute einen Fehler in der MapKit-API.
Unter diesem Link finden Sie Details zu anderen Personen, für die dies nicht funktioniert: http://www.iphonedevsdk.com/forum/iphone-sdk-development/19740-trigger-mkannotationview-callout-bubble.html#post110447
--bearbeiten--
Okay, nachdem ich eine Weile damit geschraubt habe, ist hier, was ich in der Lage war, Arbeit zu machen:
for (id<MKAnnotation> currentAnnotation in mapView.annotations) { if ([currentAnnotation isEqual:annotationToSelect]) { [mapView selectAnnotation:currentAnnotation animated:FALSE]; } }
Beachten Sie, dass hierfür eine Implementierung
- (BOOL)isEqual:(id)anObject
für Ihre Klasse erforderlich ist , die das MKAnnotation-Protokoll implementiert.quelle
Wenn Sie nur das Callout für die zuletzt hinzugefügte Anmerkung öffnen möchten, versuchen Sie dies, funktioniert für mich.
[mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
quelle
Das Problem beim Aufrufen
selectAnnotation
von- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
besteht darin, dass dieses Ereignis, wie der Name schon sagt, erst ausgelöst wird, wenn MapView zum ersten Mal geladen wird. Sie können das Callout der Anmerkung also nicht auslösen, wenn Sie es hinzufügen, nachdem MapView vollständig geladen wurde.Das Problem beim Aufrufen von
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
ist, dass Ihre Anmerkung möglicherweise nicht auf dem Bildschirm angezeigt wird, wenn sieselectAnnotation
aufgerufen wird, was dazu führen würde, dass sie keine Auswirkung hat. Selbst wenn Sie die Region Ihres MapView vor dem Hinzufügen der Anmerkung auf die Koordinate der Anmerkung zentrieren, reicht die geringfügige Verzögerung zum Festlegen der Region der MapView ausselectAnnotation
, um aufgerufen zu werden, bevor die Anmerkung auf dem Bildschirm angezeigt wird, insbesondere wenn Sie animierensetRegion
.Einige Leute haben dieses Problem gelöst, indem sie
selectAnnotation
nach einer Verzögerung als solche angerufen haben :-(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views { [self performSelector:@selector(selectLastAnnotation) withObject:nil afterDelay:1]; } -(void)selectLastAnnotation { [myMapView selectAnnotation: [[myMapView annotations] lastObject] animated:YES]; }
Aber selbst dann können seltsame Ergebnisse erzielt werden, da es mehr als eine Sekunde dauern kann, bis die Anmerkung auf dem Bildschirm angezeigt wird. Dies hängt von verschiedenen Faktoren ab, z. B. der Entfernung zwischen der Region Ihres vorherigen MapView und der neuen Region oder der Geschwindigkeit Ihrer Internetverbindung.
Ich habe mich
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
stattdessen für den Anruf entschieden, da dadurch sichergestellt wird, dass die Anmerkung tatsächlich auf dem Bildschirm angezeigt wird (vorausgesetzt, Sie setzen die Region Ihres MapView auf die Koordinate Ihrer Anmerkung), da dieses Ereignis nach AbschlusssetRegion
(und seiner Animation) ausgelöst wird. Allerdings wirdregionDidChangeAnimated
ausgelöst, wenn Ihre MapView der Region ändert, auch wenn der Benutzer schwenkt gleich um die Karte , so dass Sie sicher, müssen Sie eine Bedingung, um richtig zu identifizieren , wenn der richtige Zeitpunkt ist die Anmerkung des callout auszulösen.So habe ich es gemacht:
MKPointAnnotation *myAnnotationWithCallout; - (void)someMethod { MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init]; [myAnnotation setCoordinate: someCoordinate]; [myAnnotation setTitle: someTitle]; MKCoordinateRegion someRegion = MKCoordinateRegionMakeWithDistance (someCoordinate, zoomLevel, zoomLevel); myAnnotationWithCallout = myAnnotation; [myMapView setRegion: someRegion animated: YES]; [myMapView addAnnotation: myAnnotation]; } - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { if (myAnnotationWithCallout) { [mapView selectAnnotation: myAnnotationWithCallout animated:YES]; myAnnotationWithCallout = nil; } }
Auf diese Weise wird Ihre Anmerkung im Moment garantiert auf dem Bildschirm angezeigt
selectAnnotation
des Aufrufs wird, und derif (myAnnotationWithCallout)
Teil stellt sicher, dass keine andere- (void)someMethod
Regionseinstellung als die in das Callout auslöst.quelle
Ich habe die API sorgfältig gelesen und schließlich das Problem gefunden:
Wenn die angegebene Anmerkung nicht auf dem Bildschirm angezeigt wird und daher keine Anmerkungsansicht zugeordnet ist, hat diese Methode keine Auswirkung.
Sie können also einige Zeit warten (z. B. 3 Sekunden) und dann diese Aktion ausführen. Dann funktioniert es.
quelle
Aufgrund des von benvolioT angezeigten Codes, von dem ich vermute, dass er im System vorhanden ist, wurde bei Verwendung der Methode selectAnnotation: animation: der Aufruf von callOut nicht angezeigt. Der Grund dafür war vermutlich, dass er bereits ausgewählt war und vermieden wurde Bitten Sie die MapView, den CallOut auf der Karte unter Verwendung des Anmerkungstitels und des Untertitels neu zu zeichnen.
Die Lösung bestand also einfach darin, die Auswahl zuerst aufzuheben und erneut auszuwählen.
Beispiel: Zuerst musste ich dies in Apples touchMoved-Methode tun (dh wie man eine AnnotationView zieht), um callOut auszublenden. (Die einfache Verwendung von annotation.canShowAnnotation = NO allein funktioniert nicht, da ich vermute, dass es neu gezeichnet werden muss. Die AbwahlAnnotierung bewirkt die erforderliche Aktion. Auch die Abwahl allein hat diesen Trick nicht ausgeführt, der Aufruf ist nur einmal verschwunden und wurde sofort neu gezeichnet war der Hinweis, dass es automatisch wiedergewählt wurde).
annotationView.canShowAnnotation = NO; [mapView deselectAnnotation:annotation animated:YES];
Wenn Sie dann einfach den folgenden Code in der touchEnded-Methode verwenden, wird callOut nicht zurückgebracht (Die Anmerkung wurde zu diesem Zeitpunkt vom System automatisch ausgewählt, und vermutlich tritt das Neuzeichnen des callOut nie auf):
annotationView.canShowAnnotation = YES; [mapView selectAnnotation:annotation animated:YES];
Die Lösung war:
annotationView.canShowAnnotation = YES; [mapView deselectAnnotation:annotation animated:YES]; [mapView selectAnnotation:annotation animated:YES];
Dadurch wurde das callOut einfach zurückgekauft, vermutlich wurde der Vorgang des erneuten Zeichnens des callOut durch die mapView erneut eingeleitet.
Genau genommen sollte ich feststellen, ob die Annotation die aktuelle Annotation ist oder nicht (ausgewählt, was ich weiß) und ob callOut tatsächlich angezeigt wird oder nicht (was ich nicht weiß), und mich dazu entschließen, sie entsprechend neu zu zeichnen sei besser. Ich habe die CallOut-Erkennungsmethode jedoch noch nicht gefunden, und es ist zu diesem Zeitpunkt nur ein wenig unnötig, dies selbst zu versuchen.
quelle
Die Antwort von Steve Shi machte mir klar, dass selectAnnotation von der mapViewDidFinishLoadingMap-Methode aufgerufen werden muss. Leider kann ich nicht abstimmen, aber ich möchte mich hier bedanken.
quelle
Fügen Sie einfach [mapView selectAnnotation: Punkt animiert: JA] hinzu;
quelle
Durch das Zurücksetzen der Anmerkungen wird auch die Beschriftung nach vorne gebracht.
[mapView removeAnnotation: currentMarker]; [mapView addAnnotation:currentMarker];
quelle