viewForAnnotation Verwirrung und Anpassen der PinColor iterativ
Das Ziel ist es, die Stiftfarben für einige in einem Strukturarray gespeicherte Werte anzupassen.
Als Hilfe hier habe ich die folgende viewForAnnotation-Delegate-Methode implementiert, und das funktioniert hervorragend, wenn diese Delegate-Methode in einer Schleife iterativ aufgerufen wird, die auf der Größe meines Strukturdaten-Arrays basiert. So funktioniert es, wenn ich alle Stifte auf eine Farbe einstellen möchte, zum Beispiel lila (das ist die kommentierte Zeile im Code unten).
Das Problem ist, wenn ich einen Schalter einsetze, um die Farbe basierend auf einem Wert in meinem Array festzulegen, der diesen Code durchläuft, aber keinen der Fallwerte beachtet, um eine alternative Farbe festzulegen, und alles geht an einen roten Stift (anscheinend) der Standard). Ich habe den Status ausgedruckt und getestet, um zu wissen, dass er in den Schalter gelangt und PinColor entsprechend einstellt, aber sie scheinen nicht zu haften.
func mapView(aMapView: MKMapView!,
viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
let theindex = mystructindex // grab the index from a global to be used below
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = aMapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
//println("Pinview was nil")
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
// Preventive if to keep this from being called beyond my arrays index value as the delegate getting called beyond the for loop for some unknown reason
if (theindex < MySupplierData.count) {
// Set the pin color based on the status value in MySupplierData structure array
switch MySupplierData[mystructindex].status {
case 0,1:
println("Case 0 or 1 - setting to Red")
pinView!.pinColor = .Red // Needs help, show red pin
case 2:
println("Case 2 - Setting to Green")
pinView!.pinColor = .Green // Looking Good
case 3:
println("Case 3 - Setting to Purple")
pinView!.pinColor = .Purple // Could use a follow-up
default:
println("Case default - Should Never Happen")
break;
} // end switch
} // end if
// pinView!.pinColor = .Purple // This works fine without the switch and respects any color I set it to.
}
else {
pinView!.annotation = annotation
}
return pinView
}
In meiner for-Schleife im ViewController rufe ich dies wie folgt auf, aber ich mache nichts mit der Rückgabe.
// previous to this I setup some Titles and Subtitle which work fine
self.theMapView.addAnnotation(myAnnotation)
// Call to my mapview
mapView(theMapView, viewForAnnotation: myAnnotation)
Ich mache nichts mit der Rückgabe von Pinview - hätte nicht gedacht, dass ich das tun müsste, aber alle Pins werden an dieser Stelle rot gezeichnet, wenn der Schaltercode verwendet wird. Grundsätzlich muss mir hier etwas fehlen.
7-8-14 Aktualisierungen zur Behebung von Problemen mit überarbeitetem Code gemäß Annas hervorragender Hilfe / Anleitung. TKS!
Es funktioniert fast. Alle Pins in der Karte haben die richtigen Farben, aber diejenigen außerhalb der unmittelbaren Anzeige sind manchmal falsch. Das Posten des gesamten Codes, der hier enthalten ist, kann anderen helfen, da dies eine sehr häufige Frage zur Durchführung benutzerdefinierter Arbeiten in Maps zu sein scheint.
Eine benutzerdefinierte Klasse, die vorgeschlagen wird, um andere Variablen in einer benutzerdefinierten Annotation aufzunehmen - in diesem Fall den Statuswert aus meiner Datenstruktur MySupplierData.
class CustomMapPinAnnotation : NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String
var subtitle: String
var status: Int
init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String, status: Int) {
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
self.status = status
}
}
Die überarbeitete Kartenansicht - verwendet jetzt die neue CustomMapPinAnnotation, die an sie übergeben wird:
func mapView(aMapView: MKMapView!,
viewForAnnotation annotation: CustomMapPinAnnotation!) -> MKAnnotationView! {
let reuseId = "pin"
var pinView = aMapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
//println("Pinview was nil")
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
// Code to catch my custom CustomMapPinAnnotation so we can check the status and set the color
if annotation.isKindOfClass(CustomMapPinAnnotation)
{
println("FOUND OUR CustomMapPinAnnotation CLASS IN mapView")
println(" Custom Title = \(annotation.title)")
println(" Custom status passed = \(annotation.status)")
switch annotation.status {
case 0,1:
println("Case 0 or 1 - Setting to Red")
pinView!.pinColor = .Red
case 2:
println("Case 2 - Setting to Green")
pinView!.pinColor = .Green
case 3:
println("Case 3 - Setting to Purple")
pinView!.pinColor = .Purple
default:
println("Case default - Should Never Happen")
break;
} // switch
} // if
}
else {
pinView!.annotation = annotation
}
return pinView
} //func mapView
In viewDidLoad die Setup- und For-Schleife, um die Anmerkungen einzurichten
override func viewDidLoad() {
super.viewDidLoad()
// setup the region and Span
var theSpan:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
// Set the region to the the first element of the structure array.
var theRegion:MKCoordinateRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(MySupplierData[0].latitude, MySupplierData[0].longitude), theSpan)
// This set the Map Type (Standard, Satellite, Hybrid)
self.theMapView.mapType = MKMapType.Standard
// Now loop through the structure data from 1 top the end of the structure to map the data
var mytitle: String = ""
var mysubtitle: String = ""
var myCustomPinAnnotation: CustomMapPinAnnotation
for mystructindex = 0; mystructindex < MySupplierData.count; ++mystructindex {
println("INSIDE SUPPLIER LOOP INDEX = \(mystructindex)" )
switch MySupplierData[mystructindex].status {
case 0:
mytitle = "(Red) " + MySupplierData[mystructindex].company
case 1:
mytitle = "(Red) " + MySupplierData[mystructindex].company
case 2:
mytitle = "(Geeen) " + MySupplierData[mystructindex].company
case 3:
mytitle = "(Purple) " + MySupplierData[mystructindex].company
default:
mytitle = "? " + MySupplierData[mystructindex].company
}
mysubtitle = MySupplierData[mystructindex].subtitle
// Create the Custom Annotations with my added status code
myCustomPinAnnotation = CustomMapPinAnnotation(
coordinate: CLLocationCoordinate2DMake(MySupplierData[mystructindex].latitude,MySupplierData[mystructindex].longitude),
title: mytitle, // custom title
subtitle: mysubtitle, // custom subtitle
status: MySupplierData[mystructindex].status) // status that will drive pin color
// put this annotation in the view.
self.theMapView.addAnnotation(myCustomPinAnnotation)
} // For
// This line brings up the display with the specific region in mind, otherwise it seems to default to a US Map.
self.theMapView.setRegion(theRegion, animated: true)
} // viewDidLoad
Die Debug-Ausgabe zeigt, dass die For-Schleife wie erwartet vollständig ausgeführt wird, um die myCustomPinAnnotation zu erstellen, bevor die benutzerdefinierte viewForAnnotation in mapView selbstständig ausgeführt wird. Wenn ich die Karte in Bereiche außerhalb der unmittelbaren Ansicht verschiebe, bemerke ich, dass viewForAnnotation in mapView bei Bedarf aufgerufen wird und mein Schalter entsprechend ausgeführt wird, aber die Stiftfarben nicht immer korrekt sind. Alle Stifte in der anfänglichen Anzeigekarte sind jedes Mal korrekt, also sind es diese äußeren Regionen, auf denen ich momentan festhalte, warum sie ausgeschaltet sind.