MKMapViewのMKAnnotationViewのタップを連続で検知する方法を知りたかったので調べました。
環境
- Xcode 12.2
サンプル
検証用として、東京駅にMKPointAnnotation
を追加するサンプルコードです。
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup() {
// 中心座標 東京駅
let centerCoordinate = CLLocationCoordinate2D(latitude: 35.68141918995943,
longitude: 139.7673930186306)
let span = MKCoordinateSpan(latitudeDelta: 0.01,
longitudeDelta: 0.01)
let region = MKCoordinateRegion(center: centerCoordinate,
span: span)
// 東京駅周辺を表示
mapView.setRegion(region, animated: true)
mapView.delegate = self
// Annotationを東京駅に追加
let annotation = MKPointAnnotation()
annotation.coordinate = centerCoordinate
mapView.addAnnotation(annotation)
}
}
// MARK: - MKMapViewDelegate
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, didSelect annotation: MKAnnotation) {
print("didSelect")
}
}
このコードだとマップ上のMKPointAnnotation
をタップすると、一度mapView(_ , didSelect)
内の処理が呼び出されるが、一度MKPointAnnotation
外をタップしてMKPointAnnotation
の選択状態を解除しなければ、mapView(_ , didSelect)
内の処理を再度呼び出すことが出来なかった。
原因
func mapView(_ mapView: MKMapView, didSelect annotation: MKAnnotation)
ではなく、MKAnnotationView
のfunc mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView)
のドキュメントには下記の記述がありました。
You can use this method to track changes in the selection state of annotation views.
このメソッドを使用して、アノテーションViewの選択状態の変更を追跡出来ます
引用: Apple Developer - mapView(_:didSelect:)
選択状態の変更を追跡ということから、一度選択すると選択状態になっている為、連続でタップしても選択状態からは変更になっていないのでdidSelect
が呼ばれていないように思いました。
解決策
didSelect
内でMKAnnotation
の選択状態を解除することで、また次の選択状態の変更も検知できるようになりました。
// MARK: - MKMapViewDelegate
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, didSelect annotation: MKAnnotation) {
print("didSelect")
mapView.deselectAnnotation(annotation, animated: false)
}
}
おわりに
今回の解決策だと、MKPointAnnotation
が選択された時の大きく強調されるようなアニメーションを使用できない為、アニメーションを表示させたい場合には選択状態を解除するまでに遅延をかけたりと一工夫が必要そうです。
無事にマップ上のお気に入りの場所を何度も選択できるようになりました。ありがとうございました。