viewForAnnotation混淆和迭代自定义pinColor



目标是根据存储在结构数组中的一些值定制引脚颜色。

在这里我实现了下面的viewForAnnotation委托方法,并且根据我的结构数据数组的大小在循环中迭代地调用这个委托方法。因此,如果我想将所有引脚设置为一种颜色,例如紫色(即下面代码中的注释行),它就可以工作。

问题是,当我放入一个开关来根据数组中的值设置颜色时,它会通过此代码,但不尊重任何将其设置为替代颜色的大小写值,并且所有内容都变为红色引脚(似乎是默认的)。我已经打印出状态并进行调试,以知道它正在进入开关并相应地设置pinColor,但它们似乎不坚持。

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
}

在ViewController的for循环中,我像下面这样调用它,但是我没有对返回做任何事情。

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

我没有对返回Pinview做任何事情-我认为我不需要这样做,但是在使用开关代码时,所有的引脚都在此时被绘制为红色。从根本上说,我肯定遗漏了什么。


7-8-14根据Anna的大力帮助/辅导,更新以解决修改代码的问题。谢谢!

它几乎工作,地图内的所有引脚都有正确的颜色,但外面的即时显示有时是错误的。张贴这里涉及的所有代码,因为它可能会帮助别人因为这似乎是一个关于如何在地图中做自定义工作的非常常见的问题。

建议在自定义注释中保存其他变量的自定义类-在本例中,状态值来自我的数据结构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
  }
}

修改后的mapView——现在使用传递给它的新的CustomMapPinAnnotation:

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

在viewDidLoad设置和For循环中设置注释

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

调试输出显示For循环按照预期执行完成,以便在mapView中的自定义viewForAnnotation获得之前创建myCustomPinAnnotation在内部自行执行。当我将地图移动到即时视图之外的区域时,我注意到mapView中的viewForAnnotation会根据需要被调用我看到我的开关相应地执行,但引脚的颜色并不总是正确的。初始显示图中的所有引脚每次都是正确的这是这些外部区域的我卡住了,目前为什么他们关闭。

首先,代码应该而不是显式调用viewForAnnotation
删除addAnnotation行后对viewForAnnotation的显式调用

viewForAnnotation是一个委托方法,当地图视图需要显示注释时,将自动调用。如果它没有被自动调用,请确保地图视图的delegate属性被设置(例如为self)。


第二个(也是真正的问题)是,代码假设viewForAnnotation委托方法只在添加每个注释后立即被调用一次。

并非如此,也不能保证。每当需要显示注释时,地图视图将调用viewForAnnotation,并且可以为相同的注释多次调用,或者在实际添加注释后很长时间内调用(例如:在用户平移或缩放地图后,注释进入视图)。

看MKAnnotationView缓冲它的输入队列吗?更多细节和其他答案的相关链接,包括示例代码。

基本上,您必须将影响注释视图的属性存储在注释对象本身中,并从传递给viewForAnnotationannotation参数中检索这些属性。


对于你的情况,我的建议是:

我假设您正在使用内置注释类MKPointAnnotation。而不是使用MKPointAnnotation,它不允许您将自定义status属性与注释对象本身一起存储:

  • 创建一个自定义类,实现MKAnnotation协议,但也具有status属性。在创建注释时设置此属性,并从传递给viewForAnnotationannotation参数中提取其值,并相应地设置pinColor。参考链接答案中的示例代码

  • 使MySupplierData 中的对象本身对象实现MKAnnotation协议。因此,如果MySupplierData中的对象是某个命名为Supplier的类的实例,例如,使Supplier类符合MKAnnotation协议,然后您可以在调用addAnnotation时将MySupplierData对象本身添加到地图视图中。

相关内容

  • 没有找到相关文章

最新更新