SwiftUIでMapKitを使用してMapViewを作る【Part2】
はじめに
前回の記事では、SwiftUIでMapを表示することに成功しました。
また、表示するだけでなく、指定した位置をマップの初期中心に持ってきてピン(ポイントアノテーション)を打つことにも成功していました。
今回は、Map上をロングタップすることでピンを打てるようにします。
Coordinator を作成する
前回ピンを作成するために記述した部分は、必要がないので削除しておきます。
MapViewのなかにcoordinatorクラスを作成しましょう。
すると、メソッドを定義するようにXCodeが言ってくれるので
追加して、ついでに、delegateもCoordinatorに設定しましょう。
struct MapView: UIViewRepresentable { func makeUIView(context: Context) -> MKMapView { let map = MKMapView() map.delegate = context.coordinator return map } func makeCoordinator() -> Coordinator { Coordinator(self) } // ビューの更新時に呼ばれる func updateUIView(_ mapView: MKMapView, context: Context) { } class Coordinator: NSObject, MKMapViewDelegate { var parent: MapView init(_ parent: MapView) { self.parent = parent } } }
Coordinatorに、ロングタップを検知するためのUILongPressGestureRecognizerの変数を追加しておきましょう。
そしてその変数にaddTargetするためのメソッドも定義して、addTargetに追加しておきましょう。
class Coordinator: NSObject, MKMapViewDelegate { var parent: MapView let myLongPress: UILongPressGestureRecognizer = UILongPressGestureRecognizer() init(_ parent: MapView) { self.parent = parent super.init() self.myLongPress.addTarget(self, action: #selector(recognizeLongPress)) } @objc func recognizeLongPress(sender: UILongPressGestureRecognizer) { if sender.state == .began { print("In") } else if sender.state == .ended { print("Out") } } }
ロングタップされた時の処理をMKMapViewに認識させるために
mkmapviewに追加でジェスチャーを認識させ(?)ましょう。
func makeUIView(context: Context) -> MKMapView { let map = MKMapView() map.delegate = context.coordinator map.addGestureRecognizer(context.coordinator.myLongPress) // 追加 return map }
ここでいったん実行してみましょう。
ロングタップし始めた時に 'In' 話した時に 'Out' がデバッグコンソールに出てくると思います。
出てきましたね。では、前回と同じようにピンを追加する処理を追加してあげましょう。
今回は、簡単にsender.stateが.endedの時にピンを置くようにしたいと思います。
@objc func recognizeLongPress(sender: UILongPressGestureRecognizer) { if sender.state == .ended { if let mapView = sender.view as? MKMapView { // タップした位置を取得 let point = sender.location(in: mapView) // mapView上での位置に変換 let coordinate = mapView.convert(point, toCoordinateFrom: mapView) // ピンの作成 let annotation = MKPointAnnotation() annotation.coordinate = coordinate mapView.addAnnotation(annotation) } } } }
おわりに
ロングタップでピンを置くことに成功しました。
ただ、ロングタップをした分だけピンが打たれてしまいます。
そこらへんの話はまた次回.
今回の記事のプロジェクトをGitHubに上げていますので是非ご覧ください。
間違いございましたら、是非教えていただきたいのでコメントお願いします。
それぞれの記事ごとにブランチを分けています。 github.com
今までの記事
前回までの記事は、以下から読めます。