iOS 11中MKAnnotationView标注气泡附属视图无法显示求助
嘿,我之前也踩过iOS 11之后地图标注气泡附属视图不显示的坑,给你几个实用的排查和解决方向,应该能帮你搞定:
必须开启气泡显示权限
iOS 11之后,MKAnnotationView默认不会自动触发气泡显示,所以你一定要给标注视图设置canShowCallout = true,这是气泡和附属视图能显示的基础。代码示例:let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "YourReuseID") annotationView.canShowCallout = true // 这行绝对不能少!正确创建并添加.detailedDisclosure样式的附属视图
要显示.detailDisclosure样式的按钮,得用UIButton(type: .detailDisclosure)来初始化按钮,再把它赋值给标注视图的leftCalloutAccessoryView或rightCalloutAccessoryView。别直接用普通按钮改样式,那样大概率不生效:let detailButton = UIButton(type: .detailDisclosure) annotationView.rightCalloutAccessoryView = detailButton确认自定义Annotation的title/subtitle有效
虽然你提到已经设置了标题和副标题,但要确保你的自定义Annotation类(比如你代码里的CalloutP...)正确实现了MKAnnotation协议的title和subtitle属性,且返回值不是nil——如果title为nil,气泡根本不会显示,附属视图自然也看不到。比如:class CustomAnnotation: NSObject, MKAnnotation { var coordinate: CLLocationCoordinate2D var title: String? var subtitle: String? init(coordinate: CLLocationCoordinate2D, title: String?, subtitle: String?) { self.coordinate = coordinate self.title = title self.subtitle = subtitle super.init() } }检查标注视图复用的逻辑
如果你用了dequeueReusableAnnotationView(withIdentifier:)来复用视图,要注意在复用的时候要么重新配置附属视图,要么确保复用的视图已经正确设置了属性,同时别忘了更新复用视图的annotation属性:let reuseID = "AnnotationReuseID" var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseID) as? MKPinAnnotationView if annotationView == nil { // 初始化新视图时配置气泡和附属视图 annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseID) annotationView?.canShowCallout = true let detailButton = UIButton(type: .detailDisclosure) annotationView?.rightCalloutAccessoryView = detailButton } else { // 复用视图时更新关联的annotation annotationView?.annotation = annotation } return annotationView(可选)确保代理方法正确实现(如果需要交互)
要是你需要响应附属按钮的点击事件,别忘了实现calloutAccessoryControlTapped代理方法,不过这一步不影响视图的显示:func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { if control == view.rightCalloutAccessoryView { // 在这里处理按钮点击逻辑 } }
最常见的问题就是漏掉了canShowCallout = true这行代码,你可以先检查这一点,大概率能解决问题。
内容的提问来源于stack exchange,提问作者Finn Wolff

