【SwiftUI】Mapkitを使った位置情報の取得と逆ジオコーデイング

# はじめに
SwiftUIでMapkitとFirebaseを使用し、位置情報をデータベースに保存することを目的とする。
今回はSwiftUIで取得した現在地から逆ジオコーディングし、都道府県名と市区町村名を取得するところまでを記載。
Mapkitを使って現在置を取得する方法は前回記事を参考にしてください。

**参考記事**
[【SwiftUI】Mapkitを使った位置情報の取得とピンの表示](https://qiita.com/m37335/items/4592f4fc40a1d2b7da05)

# 開発環境
OSX 10.15.7 (Catalina) 
Xcode 12.0.1
CocoaPods 1.10.0

# 取得した現在地から逆ジオコーディングを実行する

追加するのは```makeCoordinator```の下部に```title```と```subtitle```を定義します。

```swift:ContentView.swift
func makeCoordinator() -> mapView.Coordinator {
        
        return mapView.Coordinator(parent1: self)
    }
    
    // ここから追加
    // 都道府県名
    @Binding var title : String
    // 市区町村名
    @Binding var subtitle : String
    
    func  makeUIView(context: UIViewRepresentableContext<mapView>) -> MKMapView {
        // Tokyo 35.6804° N, 139.7690° E
```

次に```Coordinator```クラス内の```locationManager```ファンクション内に```title```と```subtitle```を追加します。
今回は都道府県名と市区町村名を取得できればよいため、```administrativeArea```と```locality```を設定しました。
他の地名や郵便番号など取得したい場合はこの箇所を変更、または追加していきます。

その場合は以下の記事が参考になりました。
[[Swift] MapKitを使って”ジオコーディング・逆ジオコーディング”をやってみる](https://dev.classmethod.jp/articles/geocoding-use-mapkit/)



```swift:ContentView.swift
class Coordinator: NSObject, CLLocationManagerDelegate {
        
        var parent : mapView
        
        init(parent1 : mapView) {
            
            parent = parent1
        }
        
        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
            
            if status == .denied{
                
                parent.alert.toggle()
                print("denied")
            }
        }
        
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            
            let location = locations.last

            let point = MKPointAnnotation()
            
            let georeader = CLGeocoder()
            georeader.reverseGeocodeLocation(location!) { (places, err) in
                
                if err != nil {
                    
                    print((err?.localizedDescription)!)
                    return
                }
                
                // ここから追加
                // 都道府県名
                self.parent.title = (places?.first?.administrativeArea)!
                // 市町村名
                self.parent.subtitle = (places?.first?.locality)!
                
                // 前回記事から一部変更。ピンの選択時に都道府県名と市区町村名を表示できるように設定。

                let place = places?.first?.administrativeArea
                let subPlace = places?.first?.locality
                print(place as Any)
                point.title = place
                point.subtitle = subPlace
                
                point.coordinate = location!.coordinate
                self.parent.map.removeAnnotations(self.parent.map.annotations)
                self.parent.map.addAnnotation(point)
                
                let region = MKCoordinateRegion(center: location!.coordinate, latitudinalMeters: 10000, longitudinalMeters: 100000)
                print(region)
                self.parent.map.region = region
                
            }
        }
    }
```

今後、ここで取得した緯度経度と都道府県名、市区町村名はFirebaseに保存できるようにします。

# 都道府県名と市区町村名を表示する


```swift:ContentView.swift
struct ContentView: View {
    
    // ここから追加
    @State var title = ""
    @State var subtitle = ""
    
    @State var manager = CLLocationManager()
    @State var alert = false
    
    var body: some View {
        // 以下の行を追加
        // ContentViewに地図を表示
        ZStack(alignment: .bottom, content: {
            mapView(manager: $manager, alert: $alert, title: $title, subtitle: $subtitle).alert(isPresented: $alert) {
                
                Alert(title: Text("Please Enable Location Access In Setting Panel!!!"))
            }
            
            // 以下を追加
            // 地名を取得した場合に表示
            if self.title != "" {
                HStack(spacing: 12) {
                    Image(systemName: "info.circle.fill").font(.largeTitle).foregroundColor(.black)
                    VStack(alignment: .leading, spacing: 5){
                        Text(self.title).font(.body).foregroundColor(.black)
                        Text(self.subtitle).font(.caption).foregroundColor(.gray)
                    }
                Spacer()
                }
                .padding()
                // "Color"はAssets.xcassetsで設定
                .background(Color("Color"))
                .cornerRadius(15)
                .offset(y: -30)
            .padding()
            }
        })
    }
}
```

"Color"はAssets.xcassetsで設定しました。[+]から、[Color set]を選択し、色を作成しました。
![Assets_xcassets.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867981/929b13a2-9643-80f1-c917-fdc647fb057b.png)



# Simulatorで地図の表示と確認
![iPhone_11_–_14_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867981/caf161da-eec3-1567-b7f1-d2884280d588.png)

以上です。