如何将点击监听器添加到选定的 mkannotationview?
How to add click listener to selected mkannotationview?
我需要点击地图上的注释。我可以像这样看到选定的注释视图
我想在这个选定的注释视图上添加点击侦听器,以打开另一个带有注释详细信息的视图控制器。我该怎么做?
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if let selected = (view.annotation as? CustomAnnotation) {
self.selectedAnnotation = selected
}
}
已编辑
通常你会添加,例如,rightCalloutAccessoryView
,然后实现 calloutAccessoryControlTapped
,如
所示
但是你说:
I need to make the whole callout clickable
MapKit 没有委托方法来捕获标注本身的点击,只有在辅助视图上。但是您可以添加自己的委托来为您执行此操作。
protocol CustomAnnotationViewDelegate: class {
func didTapCallout(for annotation: MKAnnotation)
}
class CustomAnnotationView: MKPinAnnotationView {
static let preferredReuseIdentifier = Bundle.main.bundleIdentifier! + ".customAnnotationView"
weak var delegate: CustomAnnotationViewDelegate?
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
canShowCallout = true
let tap = UITapGestureRecognizer(target: self, action: #selector(didTapAnnotationView(_:)))
self.addGestureRecognizer(tap)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didTapAnnotationView(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: self)
// ignore taps on the annotation view, itself
if bounds.contains(location) { return }
// if we got here, we must have tapped on the callout
delegate?.didTapCallout(for: annotation!)
}
}
那么在iOS11及以后的版本中,可以注册这个reuseIdentifier:
override func viewDidLoad() {
super.viewDidLoad()
mapView.register(CustomAnnotationView.self,
forAnnotationViewWithReuseIdentifier: CustomAnnotationView.preferredReuseIdentifier)
}
而您的 viewFor
可以指定委托人:
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation) as! CustomAnnotationView
annotationView.delegate = self
return annotationView
}
}
或者,如果您需要支持 11 之前的 iOS 版本,您将不会注册重用标识符,但如果未成功出队,则必须自己手动实例化 CustomAnnotationView
:
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: CustomAnnotationView.preferredReuseIdentifier) as? CustomAnnotationView
if annotationView == nil {
annotationView = CustomAnnotationView(annotation: annotation, reuseIdentifier: CustomAnnotationView.preferredReuseIdentifier)
annotationView?.delegate = self
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}
无论哪种方式,您现在都可以让您的视图控制器符合新的 CustomAnnotationViewDelegate
:
extension ViewController: CustomAnnotationViewDelegate {
func didTapCallout(for annotation: MKAnnotation) {
print("tapped callout for \(annotation)")
}
}
但请注意,在上面,我在 CustomAnnotationView
init
方法中添加了点击手势识别器,以确保点击手势仅创建一次,当注释首次创建视图。
我需要点击地图上的注释。我可以像这样看到选定的注释视图
我想在这个选定的注释视图上添加点击侦听器,以打开另一个带有注释详细信息的视图控制器。我该怎么做?
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if let selected = (view.annotation as? CustomAnnotation) {
self.selectedAnnotation = selected
}
}
已编辑
通常你会添加,例如,rightCalloutAccessoryView
,然后实现 calloutAccessoryControlTapped
,如
但是你说:
I need to make the whole callout clickable
MapKit 没有委托方法来捕获标注本身的点击,只有在辅助视图上。但是您可以添加自己的委托来为您执行此操作。
protocol CustomAnnotationViewDelegate: class {
func didTapCallout(for annotation: MKAnnotation)
}
class CustomAnnotationView: MKPinAnnotationView {
static let preferredReuseIdentifier = Bundle.main.bundleIdentifier! + ".customAnnotationView"
weak var delegate: CustomAnnotationViewDelegate?
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
canShowCallout = true
let tap = UITapGestureRecognizer(target: self, action: #selector(didTapAnnotationView(_:)))
self.addGestureRecognizer(tap)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didTapAnnotationView(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: self)
// ignore taps on the annotation view, itself
if bounds.contains(location) { return }
// if we got here, we must have tapped on the callout
delegate?.didTapCallout(for: annotation!)
}
}
那么在iOS11及以后的版本中,可以注册这个reuseIdentifier:
override func viewDidLoad() {
super.viewDidLoad()
mapView.register(CustomAnnotationView.self,
forAnnotationViewWithReuseIdentifier: CustomAnnotationView.preferredReuseIdentifier)
}
而您的 viewFor
可以指定委托人:
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation) as! CustomAnnotationView
annotationView.delegate = self
return annotationView
}
}
或者,如果您需要支持 11 之前的 iOS 版本,您将不会注册重用标识符,但如果未成功出队,则必须自己手动实例化 CustomAnnotationView
:
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation { return nil }
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: CustomAnnotationView.preferredReuseIdentifier) as? CustomAnnotationView
if annotationView == nil {
annotationView = CustomAnnotationView(annotation: annotation, reuseIdentifier: CustomAnnotationView.preferredReuseIdentifier)
annotationView?.delegate = self
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}
无论哪种方式,您现在都可以让您的视图控制器符合新的 CustomAnnotationViewDelegate
:
extension ViewController: CustomAnnotationViewDelegate {
func didTapCallout(for annotation: MKAnnotation) {
print("tapped callout for \(annotation)")
}
}
但请注意,在上面,我在 CustomAnnotationView
init
方法中添加了点击手势识别器,以确保点击手势仅创建一次,当注释首次创建视图。