【问题标题】:MKMarkerAnnotationView Error, Terminating app due to uncaught exceptionMKMarkerAnnotationView 错误,由于未捕获的异常而终止应用程序
【发布时间】:2020-06-27 05:33:31
【问题描述】:

enter image description here

注解在地图上显示时,可以构建并执行,但执行过程中出错并停止。 MKMarkerAnnotationView 显示聚类和字形图像。 大约有 100 个注解,在加载 View 时从 Firestore 获取并存储在一个数组中。 地图放大或移动时发生错误。 斯威夫特版本:斯威夫特5 我也检查了插座连接,但看起来没有问题。

找不到解决方案,您能告诉我出了什么问题吗? 我写了Map等的设置方法,但如果根本错误,请教我。

错误 [XXX.CustomPinAnnotation memberAnnotations]:无法识别的选择器发送到实例 0x2835e16c0

  • 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[XXX.CustomPinAnnotation memberAnnotations]:无法识别的选择器发送到实例 0x2835e16c0”* 第一次抛出调用堆栈:

CustomPinAnnotation.swift


import UIKit
import MapKit

class CustomPinAnnotation: NSObject, MKAnnotation {

    let clusteringIdentifier : String
    let title: String?
    let subtitle: String?
    let coordinate: CLLocationCoordinate2D
    //let glyphText: String
    let glyphImage: UIImage
    let glyphTintColor: UIColor
    let markerTintColor: UIColor
    let objectid: Int

    init(_ clusteringIdentifier: String, title: String, subtitle: String, coordinate: CLLocationCoordinate2D, glyphImage: UIImage, glyphTintColor: UIColor, markerTintColor: UIColor, objectid: Int) {
        self.clusteringIdentifier = clusteringIdentifier
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate
//        self.glyphText = glyphText
        self.glyphImage = glyphImage
        self.glyphTintColor = glyphTintColor
        self.markerTintColor = markerTintColor
        self.objectid = objectid
    }
}

ViewController.swift

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {

    var locationManager = CLLocationManager()
    var userCoordinate = CLLocationCoordinate2D()

    //object array
    var objectAll = [objectData]()        

    //Map view
    @IBOutlet weak var mapView: MKMapView!

    func displayAllMountains() {
        for mountain in objectAll {
            let pinImage = UIImage.init(named: "XXXXX")!
            let subtitletext = String(object.height) + "m"
            let annotation = CustomPinAnnotation("clusterid", title:object.name, subtitle: subtitletext, coordinate: object.geopoint, glyphImage: pinImage, glyphTintColor: .white, markerTintColor: .darkGray, objectid: object.objectid)                        
            self.mapView.addAnnotation(annotation)
        }
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {   
        if annotation === mapView.userLocation {
            return nil
        } else {
            let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation)

            guard let markerAnnotationView = annotationView as? MKMarkerAnnotationView,
                let annotation = annotation as? CustomPinAnnotation else {
                     return annotationView
            }

            markerAnnotationView.clusteringIdentifier = annotation.clusteringIdentifier
//            markerAnnotationView.glyphText = annotation.glyphText
            markerAnnotationView.glyphImage = annotation.glyphImage
            markerAnnotationView.glyphTintColor = annotation.glyphTintColor
            markerAnnotationView.markerTintColor = annotation.markerTintColor
            return markerAnnotationView
        }
    }
}

【问题讨论】:

    标签: ios swift mkannotation


    【解决方案1】:

    你说它是在报道:

    错误 [XXX.CustomPinAnnotation memberAnnotations]:无法识别的选择器发送到实例 0x2835e16c0

    memberAnnotations 是一个MKClusterAnnotation 方法。但它试图在您的 CustomPinAnnotation 对象上调用该方法。在某个地方,它试图在预期 MKClusterAnnotation 的上下文中使用 CustomPinAnnotation

    我在表达您的问题时遇到了麻烦,我不确定您分享的内容是否足以让我们重现它。但我可以很容易地看出它是如何被混淆的。有三种注解类型,不仅有MKUserLocationCustomPinAnnotation,还有MKClusterAnnotation。您的 mapView(_:viewFor:) 只考虑前两种类型的存在。如果你愿意,你也可以让它处理MKClusterAnnotation

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation {
            return nil
        } else if annotation is MKClusterAnnotation {
            return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier, for: annotation)
        }
    
        let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation)
    
        guard
            let markerAnnotationView = annotationView as? MKMarkerAnnotationView,
            let annotation = annotation as? CustomPinAnnotation
        else {
            return annotationView
        }
    
        markerAnnotationView.clusteringIdentifier = annotation.clusteringIdentifier
        markerAnnotationView.displayPriority = .required
        // markerAnnotationView.glyphText = annotation.glyphText
        markerAnnotationView.glyphImage = annotation.glyphImage
        markerAnnotationView.glyphTintColor = annotation.glyphTintColor
        markerAnnotationView.markerTintColor = annotation.markerTintColor
        return markerAnnotationView
    }
    

    不过,我个人建议完全删除mapView(_:viewFor:),而是定义您自己的注释视图类来执行此配置:

    class CustomAnnotationView: MKMarkerAnnotationView {
        override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
            super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
            update(for: annotation)
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override var annotation: MKAnnotation? { didSet { update(for: annotation) } }
        
        func update(for annotation: MKAnnotation?) {
            displayPriority = .required
    
            guard let annotation = annotation as? CustomPinAnnotation else { return }
            
            clusteringIdentifier = annotation.clusteringIdentifier
            // markerAnnotationView.glyphText = annotation.glyphText
            glyphImage = annotation.glyphImage
            glyphTintColor = annotation.glyphTintColor
            markerTintColor = annotation.markerTintColor
        }
    }
    

    当然,请确保注册它(以及您的集群注释视图):

    mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
    mapView.register(MKMarkerAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)
    

    但关键是mapView(_:viewFor:)的默认实现会自动处理所有三种类型的注解视图。通过这种方式,我们将“我如何渲染这个注释视图”的代码从视图控制器(或任何MKMapViewDelegate)中取出,并进入它所属的注释视图类。

    【讨论】:

    • 嗨,罗布。谢谢您的回答。我无法正确处理 MKClusterAnnotation,因为我不太了解 ClusterAnnotation 和 MarkerAnnotation 之间的关系。感谢您的建议,它有效!也感谢您对如何进行第二次“删除 mapView(_:viewFor:)”的任何建议。我想进一步了解Annotation的显示。感谢您提供非常有用的建议!
    猜你喜欢
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 2020-01-26
    相关资源
    最近更新 更多