MKMapView andere Pin Farbe

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • MKMapView andere Pin Farbe

    Hallo liebe Leute!

    Ich habe eine Karte, die mit Pins aus einer Datenbank befüllt wird.
    Darüber hinaus wird die Position des Users angezeigt. Dieser hat auch die Möglichkeit, neue Pins zu setzen.
    Jetzt möchte ich aber, dass die Farbe der Pins sich unterscheidet.

    Dazu habe ich eine Delegate method von MKMapView überschrieben:

    Quellcode

    1. - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
    2. {
    3. MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"thisPin"];
    4. if ([needleColor isEqualToString:@"red"]) {
    5. pinView.pinColor = MKPinAnnotationColorRed;
    6. }
    7. else if ([needleColor isEqualToString:@"green"]) {
    8. pinView.pinColor = MKPinAnnotationColorGreen;
    9. }
    10. else if ([needleColor isEqualToString:@"purple"]) {
    11. pinView.pinColor = MKPinAnnotationColorPurple;
    12. }
    13. else {
    14. pinView.pinColor = MKPinAnnotationColorRed;
    15. }
    16. return pinView;
    17. }
    Alles anzeigen


    Um zu entscheiden, welche Farbe ein Pin haben soll, schreibe ich vor dem Setzen der Pin die entsprechende Farbe in den String und setze hinterher auf Rot zurück:

    Quellcode

    1. needleColor = @"green";
    2. [mapView addAnnotation:tabsCurrentNeedle];
    3. needleColor = @"red";


    Jetzt habe ich damit das Problem, dass auch die Userlocation überschrieben wird und mit einem roten Pin angezeigt wird.
    Um das zu umgehen, habe ich in die mapView:viewForAnnotation: folgende Abfrage eingebaut:

    Quellcode

    1. if ([annotation isKindOfClass:[MKPointAnnotation class]]) {
    2. // Hier der gesamte code von ganz oben
    3. }
    4. else
    5. {
    6. return pinView;
    7. }


    Leider funktioniert das nicht…
    Scheinbar ist die userlocation auch mit der Klasse MKPointAnnotation deklariert.


    Hat jemand von euch vllt. 'ne Ahnung, wie ich diese Abfrage umgestalten könnte, damit ich das gewünschte Ergebnis erziele?
    Ich freu mich riesig über eure Hilfe!

    Vielen lieben Danke, mit Grüßen
    Julian
  • julian.weinert schrieb:

    Um zu entscheiden, welche Farbe ein Pin haben soll, schreibe ich vor dem Setzen der Pin die entsprechende Farbe in den String und setze hinterher auf Rot zurück:

    Quellcode

    1. needleColor = @"green";
    2. [mapView addAnnotation:tabsCurrentNeedle];
    3. needleColor = @"red";

    Die Methode mapView:viewForAnnotation: wird nicht direkt nach dem Setzen eines neuen Pins bzw. einer Annotation aufgerufen, sondern quasi irgendwann asynchron, wenn der Pin bzw. View für die Anzeiger der Annotation vom MapView benötigt wird. Evtl. werden dann auch mehrere Pins hintereinander angefordert. Wenn Du die Farben aller Pins also in einer einzigen Variable des ViewControllers speicherst, dann wird es unmöglich sein, die Farbe für jeden einzelnen Pin festzulegen. ;)

    Ein guter Platz zum Speichern der Farbe eines Pins ist sicherlich Dein Annotation Objekt, da es für jeden Pin ein eigenes Annotation Objekt gibt. Von der Model Logik würde es dort auch sehr gut passen, da die Farbe des Pins eigentlich doch eine Eigenschaft der Annotation ist, oder?
  • Ah, alles klar…
    Ich bin da noch recht neu, komme ursprünglich aus der Webprogrammierung. Und da sind die Anläufe immer recht linear den Code herunter :)

    Ich wollte die Eigenschaft auch eigentlich direkt zuweisen.
    Das geht allerdings leider nicht, wenn ich keine MKPinAnnotionView, sondern MKPointAnnotation verwende.

    Wie kann ich denn das Annotationobjekt von MKPointAnnotationView ansprechen?!
    Bzw. wie erstelle ich eine MKPointAnnotation aus einer MKPinAnnotationView heraus?

    Denn ich verwende folgenden Code, um einen Pin zu setzen:

    Quellcode

    1. currentNeedle = [[MKPointAnnotation alloc] init];
    2. currentNeedle.title = [attributeDict objectForKey:@"title"];
    3. currentNeedle.subtitle = [attributeDict objectForKey:@"subtitle"];

    Da kann ich ja nicht einfach sagen:

    Quellcode

    1. currentNeedle.pinColor = MKPinColorGreen;
    Das geht nicht.

    Wie sollte ich das dann umsetzen?
  • Genau wie bisher in der Methode mapView:viewForAnnotation:

    Allerdings solltest dort noch dequeueReusableAnnotationViewWithIdentifier: verwenden, um zu prüfen ob Du einen bereits erzeuge MKAnnotationView evtl. erneut verwenden kannst oder einen neuen erzeugen musst.

    Schau mal in die Sample Codes zum MapKit Framework. Dort wird sicherlich auch dequeueReusableAnnotationViewWithIdentifier: in der Methode mapView:viewForAnnotation: verwendet.
  • Spitze, danke, MCDan!

    Hier noch mal meine fertige Lösung für andere suchende:

    Quellcode

    1. - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
    2. {
    3. MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"thisPin"];
    4. if ([annotation isKindOfClass:[MKPointAnnotationColored class]]) {
    5. MKPointAnnotationColored *point = (MKPointAnnotationColored *)annotation;
    6. if (point.pinColor == MKPinAnnotationColorGreen) {
    7. pinView.pinColor = MKPinAnnotationColorGreen;
    8. }
    9. else if (point.pinColor == MKPinAnnotationColorPurple) {
    10. pinView.pinColor = MKPinAnnotationColorPurple;
    11. }
    12. else {
    13. pinView.pinColor = MKPinAnnotationColorRed;
    14. }
    15. return pinView;
    16. }
    17. else {
    18. return pinView;
    19. }
    20. }
    Alles anzeigen


    Das mit dem dequeueReusableAnnotationViewWithIdentifier hab ich jetzt noch nicht eingebaut.
    Da kann ich mich grad Zeitlich noch nicht mit beschäftigen.


    Leider hat sich jetzt aber, seit ich die custom class verwende, ein anderes Problem aufgetan.
    Jetzt kann ich die Pins nicht mehr programmatisch anwählen, es funktioniert einfach nicht mehr.

    Quellcode

    1. [mapView addAnnotation:currentNeedle];
    2. [mapView selectAnnotation:currentNeedle animated:YES];


    Und, wenn ich eine neue Nadel setze (per IBAction), werden die Labels auch nicht mehr angefügt.
    Ich hab zwei Textfelder (Titel und Untertitel), deren Inhalte früher beim Setzen einer Nadel auch wunderbar übernommen wurden, das geht auch nicht mehr:

    Quellcode

    1. currentNeedle.title = title.text;
    2. currentNeedle.subtitle = subtitle.text;
    3. currentNeedle.pinColor = MKPinAnnotationColorGreen;
    4. [mapView addAnnotation:currentNeedle];
    5. [mapView selectAnnotation:currentNeedle animated:YES];


    Ich habe mal ein wenig herumgespielt.
    Wenn ich meine Subclass verwende, werden die Pins nicht mehr programmatisch ausgewählt.
    Und wenn ich mapView:ViewForAnnotation: implementiere, werden die Labels nicht gesetzt (nur beim nachträglich hinzufügen von Pins. Die aus der Datenbank bekommen ihre Labels).


    Muss ich sowohl in meiner subclass (wg. auswählen), als auch in dem override der o.g. Methode (wg. labels) irgendwelche Attribute, Methoden o.Ä. übernehmen?!


    Vielen Dank noch mal, liebe Grüße
    Julian

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von julian.weinert ()

  • Und ein weiteres Problem mit der Verwendung von mapView:ViewForAnnotation:
    Wenn ich aus dem Bild raus scrolle und dann wieder die userlocation anzeigen lasse, wird der blaue Punkt auch als Nadel angezeigt.

    Weiterhin werden alle Nadeln, die ich aus der Datenbank heraus erstelle, mit rot dargestellt, nicht in lila, wie ich es angegeben habe:

    Quellcode

    1. currentNeedle.pinColor = MKPinAnnotationColorPurple;


    Ich bin echt kurz davor, die custom class zu löschen und einfach alles in rot zu machen... Hier funktioniert einfach nix :(
    Das ist doch echt beschissen, dass die 3 verschiedene Annotations implementieren. Wieso machen die nicht einfach eine Annotation, die einfach alle Attribute und Funktionen zusammenfasst?! Aber damit würde man es ja den Programmierern zu einfach machen :/

    Naja, wie auch immer. Das musste ich jetzt mal los werden :)