概要
アプリのMap上でMkMarkerAnnotationViewをドラッグさせる実装についてです。
ドラッグ可能なMKPinAnnotationViewを実装する方法はたくさん出てくるのですが、MkMarkerAnnotationViewのままドラッグさせる方法が見つからなかったので、今回記事にしました。
実行環境
【Xcode】 11.0(Xcode11 GM Seed)
【Swift】 5
【iOS】 13.0
実装
実装は以下の通りです。
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// annotationをmapに設定
let annotation = MKPointAnnotation()
annotation.coordinate = point
mapView.addAnnotation(annotation)
}
/// annotation生成時に行うannotationの設定
/// - Parameter mapView: annotationが生成されたmapView
/// - Parameter annotation: 生成されたannotation
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let markerAnnotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "myPin")
markerAnnotationView.isDraggable = true
return markerAnnotationView
}
}
今回の肝はannotation生成時のdelegateメソッドであるfunc mapView(MKMapView, viewFor: MKAnnotation) -> MKAnnotationView?
の一行目です。
MKMarkerAnnotationView
のオブジェクトを生成し、isDraggable
をtrue
に設定することで、そのままドラッグすることができるようになります。
自分は最初MKMarkerAnnotationView
の存在がわからず悩んでいたんですが、簡単に実装できましたね。
おまけ
上記だけだと物足りないので、
- MKMarkerAnnotationViewをタップして吹き出しを表示する
- ドラッグすると吹き出しが消える
- ドラッグし終わると吹き出しが再表示する
以上の機能を実装してみます。
@IBOutlet weak var mapView: MKMapView!
let annotation = MKPointAnnotation()
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// mapの縮尺設定
let point = CLLocationCoordinate2D(latitude: 35.681_236, longitude: 139.767_125)
let region = MKCoordinateRegion(center: point, latitudinalMeters: 1000, longitudinalMeters: 1000)
mapView.setRegion(region, animated: true)
// annotationをmapに設定
annotation.coordinate = point
annotation.title = "東京駅"
annotation.subtitle = "東京都千代田区丸の内1丁目"
mapView.addAnnotation(annotation)
}
/// annotation生成時に行うannotationの設定
/// - Parameter mapView: annotationが生成されたmapView
/// - Parameter annotation: 生成されたannotation
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let markerAnnotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "myPin")
markerAnnotationView.isDraggable = true
markerAnnotationView.canShowCallout = true
markerAnnotationView.rightCalloutAccessoryView = UIButton(type: UIButton.ButtonType.detailDisclosure)
return markerAnnotationView
}
/// annotationドラッグ時に行う処理
/// - Parameter mapView:annotationが生成されてたmapView
/// - Parameter view: annotation
/// - Parameter newState: 次の状態
/// - Parameter oldState: 前の状態
public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationView.DragState, fromOldState oldState: MKAnnotationView.DragState) {
if newState == .starting {
mapView.deselectAnnotation(annotation, animated: true)
}
}