confusão de viewForAnnotation e personalização do pinColor iterativamente

O objetivo é personalizar as cores dos pinos de acordo com alguns valores armazenados em uma matriz de estrutura.

Por alguma ajuda aqui, implementei o seguinte método delegado viewForAnnotation e que funciona muito bem chamando esse método delegado iterativamente em um loop com base no tamanho da minha matriz de dados de estrutura. Portanto, funciona se eu quiser definir todos os pinos para uma cor, roxa, por exemplo (que é a linha comentada no código abaixo).

O problema é que, quando eu coloco uma opção para definir a cor com base em um valor da minha matriz, ele passa por esse código, mas não respeita nenhum dos valores de maiúsculas e minúsculas para defini-lo para uma cor alternativa e tudo passa para um alfinete vermelho (aparentemente o padrão). Eu imprimi o status e depurei para saber que ele está entrando no comutador e configurando o pinColor de acordo, mas eles não parecem grudar.

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
}

Dentro do meu loop for no ViewController, chamo isso da seguinte maneira, mas não faço nada com o retorno.

        // previous to this I setup some Titles and Subtitle which work fine
        self.theMapView.addAnnotation(myAnnotation)
        // Call to my mapview   
        mapView(theMapView, viewForAnnotation: myAnnotation)

Eu não faço nada com o Pinview de retorno - acho que não precisava, mas todos os pinos ficam vermelhos nesse momento ao usar o código do switch. Fundamentalmente, devo estar faltando alguma coisa aqui.

7-8-14 Atualizações para resolver problemas com o código revisado pela grande ajuda / tutoria de Anna. TKS!

Quase funciona. Todos os pinos no mapa têm as cores certas, mas as que estão fora da exibição imediata às vezes estão erradas. A publicação de todo o código envolvido aqui, pois isso pode ajudar outras pessoas, pois essa parece ser uma pergunta muito comum sobre como fazer um trabalho personalizado no Maps.

Uma classe personalizada, conforme sugerido, para manter outra variável em uma anotação personalizada - nesse caso, o valor do status proveniente da minha estrutura de dados, 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

  }
}

O mapView revisado - agora utilizando o novo CustomMapPinAnnotation que está sendo passado para ele:

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

No viewDidCarregue a configuração e o loop For para configurar as anotações

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

A saída de depuração mostra que o loop For é executado até o final conforme o esperado para criar os myCustomPinAnnotation antes que o viewForAnnotation personalizado no mapView seja executado internamente por conta própria. À medida que movo o mapa para áreas fora da visualização imediata, noto que a viewForAnnotation no mapView é chamada conforme necessário e vejo meu switch sendo executado adequadamente, mas as cores dos pinos nem sempre estão corretas. Todos os pinos no mapa de exibição inicial estão corretos todas as vezes, então é sobre esses da região externa que eu estou preso no momento em que eles estão desligados.

questionAnswers(1)

yourAnswerToTheQuestion