SwiftUIでMapKitを使用してMapViewを作る【Part2】
2020/07/30
はじめに
前回の記事では、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)
let coordinate = mapView.convert(point, toCoordinateFrom: mapView)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
}
}
}
おわりに
ロングタップでピンを置くことに成功しました。
ただ、ロングタップをした分だけピンが打たれてしまいます。
そこらへんの話はまた次回.
今回の記事のプロジェクトをGitHubに上げていますので是非ご覧ください。
間違いございましたら、是非教えていただきたいのでコメントお願いします。
それぞれの記事ごとにブランチを分けています。
tukuyo/SwiftUI_Map
今までの記事
前回までの記事は、以下から読めます。
SwiftUIでMapKitを使用してMapViewを作る - tukuyo's blog