【Swift】MkMarkerAnnotationViewをドラッグ可能にする

# 概要
アプリのMap上でMkMarkerAnnotationViewをドラッグさせる実装についてです。
ドラッグ可能なMKPinAnnotationViewを実装する方法はたくさん出てくるのですが、MkMarkerAnnotationViewのままドラッグさせる方法が見つからなかったので、今回記事にしました。

イメージは下記の通りです。
![qiita_20190917_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347128/a71a2260-32e2-d563-b700-fae8381b9d54.gif)

# 実行環境
【Xcode】 11.0（Xcode11 GM Seed）
【Swift】 5
【iOS】   13.0

# 実装
実装は以下の通りです。

```swift
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`の存在がわからず悩んでいたんですが、簡単に実装できましたね。

## おまけ
上記だけだと物足りないので、

1. MKMarkerAnnotationViewをタップして吹き出しを表示する
2. ドラッグすると吹き出しが消える
3. ドラッグし終わると吹き出しが再表示する

以上の機能を実装してみます。

![qiita_20190917_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347128/f9117976-7528-14b0-d15c-dbc29c1c3bc1.gif)


```swift
    @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 = "東京都千代田区丸の内１丁目"
        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)
        }
    }
```