iOS17から用意されたSwiftUIのMapkitを試してみた

## 概要
- 2023年6月 WWDC2023にて、「地図アプリを簡単に作成できる」とAppleは公言しています。
- そんな簡単に地図アプリができるわけないやろ？と思った人もいるはず。
- iOS17の新機能でお手軽に遊びたい人向けの記事です。

WWDCの記事はこちら↓
https://developer.apple.com/videos/play/wwdc2023/10043/

Appleデベロッパ向けの[サイト](https://developer.apple.com/jp/whats-new/)
(2023/09/21付)でも簡単にできると書いてあるので、疑い半分で実際に試してみます。

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/2d2b6401-b0c2-cc2b-a5c5-8058caf1cf77.png">

## Mapを出してみたい

プロジェクトを新規作成してContentView.swiftの中で噂のMapKitをimportしてみます。
そして、Map()だけ書いてみます。
すると・・・？

```swift
import SwiftUI
import MapKit // ←これ

struct ContentView: View {
    var body: some View {
        Map() // ←これ
    }
}
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/0796f5f5-7832-a034-4107-95169fff30b2.jpeg">


**なんか日本のマップ出てきた！すごい！**
"Hello World"よりも短いコードで書けるので、確かに**簡単に**書けてしまいます。

そして、一行追加するだけで、mapの形式を変えられてしまいます。

```swift
        Map()
            .mapStyle(.imagery(elevation: .realistic))
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/40a12b16-03b7-8c28-b08a-0801329baf26.jpeg">

Japan is Beautiful!!!リアルな地図に切り替えるのも簡単です。

## アノテーションをつけてみたい

まずはピンを建てたい座標（緯度・経度）を調べます。
⚠️: 緯度経度にはdegree形式とdms形式という二種類があり数値が異なるので注意してください。
degree形式がiOS開発環境の場合はデフォルトのようです。

打つ文字数が少ないってこともあり、三重県の「津駅」を今回は使います。

[CLLocationCoordinate2D](https://developer.apple.com/documentation/corelocation/cllocationcoordinate2d)を使って座標を定義して、
新機能の[Marker](https://developer.apple.com/documentation/mapkit/marker)を使います。

```swift
extension CLLocationCoordinate2D {
    static let tsu_station = CLLocationCoordinate2D(latitude: 34.7345036, longitude: 136.5101973)
}

struct ContentView: View {
    var body: some View {
        Map {
            Marker("Tsu-Station", systemImage: "train.side.front.car", coordinate: .tsu_station)
                .tint(.blue)
        }
    }
}
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/2d856235-0cf4-dfc1-e3f2-2d2ec31a01e8.png">


systemImageは[SF Symbols](https://developer.apple.com/jp/sf-symbols/)から画像を探します。

Marker部分を消して、[Anotation](https://developer.apple.com/documentation/mapkit/annotation)に変えてみると・・・

```swift
            Annotation("Tsu-Station",
                       coordinate: .tsu_station, anchor: .bottom) {
                VStack {
                    Text("Mie is Tokai")
                    Image(systemName: "flag.2.crossed")
                }
                .foregroundColor(.blue)
                .padding()
                .background(in: .capsule)
            }

```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/b11c3b98-2dad-910c-05fd-9046885948e2.png">


津駅「三重 is 都会」・・・なんて遊びもできます。


## 中心地(現在地)に戻る機能

現在地を取得する ~~には権限の関係でInfo.plist の設定とかもあって、めんd・・・~~ 機能はiOS17以前と変わらないので別途調べてください。

地図アプリ使用中に特定の位置、つまりUserLocationに戻りたい場合があると思います。
その場合は[MapCameraPosition](https://developer.apple.com/documentation/mapkit/mapcameraposition)を使います。

中心地に戻るボタン(LocationButton.swift)を追加した例です。

**ContextView.swift**
```swift
struct ContentView: View {
    
    @State var position: MapCameraPosition = .automatic // ←ここ追加
    
    var body: some View {
        Map(position: $position)  {
            
            UserAnnotation(anchor: .center) // ←ここ追加
            
            Annotation("Tsu-Station",
                       coordinate: .tsu_station, anchor: .bottom) {
                VStack {
                    Text("Mie is Tokai")
                    Image(systemName: "flag.2.crossed")
                    LocationButton(position: $position) // ←ここ追加
                }
                .foregroundColor(.blue)
                .padding()
                .background(in: .capsule)
            }
        }
    }
}

```
**LocattionButton.swift(新規作成)**

```swift
import SwiftUI
import MapKit

struct LocationButton: View {
    
    @Binding var position: MapCameraPosition

    var body: some View {
        
        Button {
            position = .userLocation(fallback: .automatic)
        } label: {
            Label("ふるさと",systemImage: "location.circle")
        }
    }
}
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/dd1b993f-e0a6-9c81-e00f-7b7622165a58.png">

上記のソースを実行し、"ふるさと"をタップすると津駅が中央になります。
これはもう**津駅は都会**と言っても過言ではないですね。

## 方角やら3Dやら

地図アプリの右上ら辺にある諸々を出したいときは、[mapControls](zhttps://developer.apple.com/documentation/mapkit/map/4231681-mapcontrols)を使います。

**例**
```swift
        Map()
        .mapControls {
            MapUserLocationButton()
```

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/66038a15-3b48-832f-588f-95636ceabbe6.jpeg">

## 時間があればやってみたいこと

WWDC2023のサンプルでは検索アプリのようなものを作っていましたが、緯度経度を取得するAPIを使ってみると面白いかもしれません。

個人的に興味があったのは「湧き水API」というものがあり、それを使って、湧き水の位置アプリを作ると面白そうです。（思ったより日本中に湧き水ってあるんですね。）
https://springwaterapi.docs.apiary.io/#introduction

**例**
```Json
  "result": [
    {
      "access": "◎",
      "activity": "市民モニターによる実態調査",
      "address": "愛知県名古屋市千種区天白町大字植田植田山",
      "createCd": "admin",
      "createDate": 1672239600000,
      "furigana": "きんめいすい",
      "id": 1830,
      "latitude": 35.1507491,
      "link": "<ahref="map/23100-1.jpg"<=""a="">写真・地図</a>",
      "longitude": 136.9848604,
      "name": "金明水",
      "oldAddress": "名古屋市千種区天白町",
      "overview": "東山動植物園の東南の斜面から湧出しており、近傍には小さな祠が作られています。",
      "updateCd": "admin",
      "updateDate": 1672239600000
    },
```

水のアイコン&Anotationでコメント出したりするとか？災害時に使えたり？
興味を持たれた方はぜひアプリ作ってみてはいかがでしょうか。

## まとめ

- 数行で簡単に作れた
- SwiftUIの進化を改めて感じる。
- 画像やピン留めなどが簡単にできるので位置情報使った簡単なゲームも作れる気がする。
- iOS17最高かよ・・・