iOS 中 annotationView 中的自定义 pin 图像

Posted

技术标签:

【中文标题】iOS 中 annotationView 中的自定义 pin 图像【英文标题】:Custom pin image in annotationView in iOS 【发布时间】:2015-12-26 16:44:15 【问题描述】:

我正在尝试从 Swift 1.2 更改为 Swift 2.0,并且我已完成更改。目前我正在对 MapViewController 进行更改,没有任何错误或警告,但我的 pin (annotationView) 的自定义图像未分配给 pin,它显示的是默认图像(红点)。

这是我的代码,我希望你能给我一些提示,因为我认为一切都很好,但它仍然无法正常工作:

func parseJsonData(data: NSData) -> [Farmacia] 

    let farmacias = [Farmacia]()

    do
    
        let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary

        // Parse JSON data
        let jsonProductos = jsonResult?["farmacias"] as! [AnyObject]

        for jsonProducto in jsonProductos 

            let farmacia = Farmacia()
            farmacia.id = jsonProducto["id"] as! String
            farmacia.nombre = jsonProducto["nombre"] as! String
            farmacia.location = jsonProducto["location"] as! String

            let geoCoder = CLGeocoder()
            geoCoder.geocodeAddressString(farmacia.location, completionHandler:  placemarks, error in

                if error != nil 
                    print(error)
                    return
                

                if placemarks != nil && placemarks!.count > 0 

                    let placemark = placemarks?[0]

                    // Add Annotation
                    let annotation = MKPointAnnotation()
                    annotation.title = farmacia.nombre
                    annotation.subtitle = farmacia.id
                    annotation.coordinate = placemark!.location!.coordinate

                    self.mapView.addAnnotation(annotation)
                

            )
        
    
    catch let parseError 
        print(parseError)
    

    return farmacias


func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? 

    let identifier = "MyPin"

    if annotation.isKindOfClass(MKUserLocation) 
        return nil
    

    // Reuse the annotation if possible
    var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)

    if annotationView == nil
    
        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView!.canShowCallout = true
    

    annotationView!.image = UIImage(named: "custom_pin.png")

    let detailButton: UIButton = UIButton(type: UIButtonType.DetailDisclosure)
    annotationView!.rightCalloutAccessoryView = detailButton

    print(annotationView!.image)

    return annotationView

提前致谢,

问候。

【问题讨论】:

【参考方案1】:

接受的答案不起作用,因为它在 else 块中未初始化 annotationView

这里有一个更好的解决方案。如果可能,它会使注释视图出队,否则会创建一个新视图:

// https://***.com/a/38159048/1321917
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? 
    // Don't want to show a custom image if the annotation is the user's location.
    guard !(annotation is MKUserLocation) else 
        return nil
    

    // Better to make this class property
    let annotationIdentifier = "AnnotationIdentifier"

    var annotationView: MKAnnotationView?
    if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) 
        annotationView = dequeuedAnnotationView
        annotationView?.annotation = annotation
    
    else 
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
        annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
    

    if let annotationView = annotationView 
        // Configure your annotation view here
        annotationView.canShowCallout = true
        annotationView.image = UIImage(named: "yourImage")
    

    return annotationView

【讨论】:

这对我的帮助远远超过接受的答案,非常感谢@Andrey Gordeev 哇!这严重救了我!!!我遇到了一些严重的性能问题,但是看到这个关于如何正确使用标识符的示例确实很有帮助。我以为我一开始也正确使用它。这应该是公认的答案! 太棒了!谢谢。 如果在声明“annotationView”时出列,实际上可以使这更简单。看我的回答。【参考方案2】:

答案如下:

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? 

    let identifier = "MyPin"

    if annotation.isKindOfClass(MKUserLocation) 
        return nil
    

    let detailButton: UIButton = UIButton(type: UIButtonType.DetailDisclosure)

    if let annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) 
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
        annotationView.canShowCallout = true
        annotationView.image = UIImage(named: "custom_pin.png")
        annotationView.rightCalloutAccessoryView = detailButton
    
    else 
        annotationView.annotation = annotation
    

    return annotationView

问候

【讨论】:

感谢您分享您的解决方案。它也帮助了我 投了反对票。 1)“annotationView”实例是在 if-let 范围内创建的,并且在 else-范围内不存在。 2)如果您成功地可以使注释视图出队,那么您应该使用它而不是创建一个新实例。新实例应在 else 范围内创建,其中不能将可重用对象出列。 我认为需要 MKPinAnnotation 作为 MKAnnotation 的子级【参考方案3】:

SWIFT 3,4

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? 

    if annotation.isKind(of: MKUserLocation.self) 
        return nil
    

    let annotationIdentifier = "AnnotationIdentifier"

    var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier)
    if (pinView == nil) 
        pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
    

    pinView?.canShowCallout = false

    return pinView

【讨论】:

以上是关于iOS 中 annotationView 中的自定义 pin 图像的主要内容,如果未能解决你的问题,请参考以下文章

缩放地图视图时动画AnnotationView消失?

mkmapview MKUserLocation AnnotationView

点击相应的annotationview后如何在mkannotationview中实现字幕的更新

swift ios中的自定义谷歌地图标记图标图像

Xamarin 表单中的自定义通用 OnPlatform 问题

iOS中的自定大小集合视图单元格