【UIKit】MKMapViewのMKAnnotationのタップを連続で検知する方法

2023.01.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

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")
    }
}

mapkit_annotation_sample

このコードだとマップ上のMKPointAnnotationをタップすると、一度mapView(_ , didSelect)内の処理が呼び出されるが、一度MKPointAnnotation外をタップしてMKPointAnnotationの選択状態を解除しなければ、mapView(_ , didSelect)内の処理を再度呼び出すことが出来なかった。

原因

func mapView(_ mapView: MKMapView, didSelect annotation: MKAnnotation)ではなく、MKAnnotationViewfunc 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が選択された時の大きく強調されるようなアニメーションを使用できない為、アニメーションを表示させたい場合には選択状態を解除するまでに遅延をかけたりと一工夫が必要そうです。

無事にマップ上のお気に入りの場所を何度も選択できるようになりました。ありがとうございました。

参考