Mapkitについてまとめてみた


# はじめに
個人開発中のアプリでMapkitが必要になったんですが、かなり苦戦したため書こうと思いました。
Mapkitに苦しんでる人は、この記事を読みながら手を動かして一緒にやりましょう！

## 目次
1. Mapkitの基礎
2. アノテーション(ピン)の付け方
3. 現在地の取得の仕方
6. 参考文献 

### Mapkitの基礎
**まずMapkitとは**
「Display map or satellite imagery within your app, call out points of interest, and determine placemark information for map coordinates.」
だそうです(公式)
直訳すると「アプリ内で地図や衛星画像を表示し、興味のある場所を示し、地図の座標に対する地名情報を取得します。」です
ようするに地図を表示するためのフレームワークみたいなもんです。

**一番簡単な例**
```swift
import SwiftUI
//  Mapkitのimport
import MapKit

struct ContentView: View {
  var body: some View {
    //  Mapを表示
    Map()
  }
}

#Preview {
  ContentView()
}

```
直感的にもわかりやすいですね。
`import Mapkit`でフレームワークを導入して、`Map()`で呼び出してます。

![スクリーンショット 2024-09-08 22.42.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763749/23c5a795-1228-f1d4-9a47-c366ad86e648.png)

こんな感じで表示されたらOKです。

### アノテーション(ピン)の付け方
アノテーションはピンみたいなものです。
```swift
import SwiftUI
import MapKit

//  これを追記
extension CLLocationCoordinate2D {
  static let tokyo = CLLocationCoordinate2D(
    latitude: 35.681236,
    longitude: 139.767125
  )
}

struct ContentView: View {
  var body: some View {
    //  ちょっと変形
    Map {
      Marker(
        "Tokyo",
        systemImage: "train.side.front.car",
        coordinate: .tokyo
      )
    }
  }
}

#Preview {
  ContentView()
}

```
ここから初めてMapkitを使う人にとっては訳がわからなくなってきます。
**解説**
```swift
extension CLLocationCoordinate2D {
  static let tokyo = CLLocationCoordinate2D(
    latitude: 35.681236,
    longitude: 139.767125
  )
}
```
- 緯度と経度を`CLLocationCoordinate2D`で指定したらその場所を特定してくれます。
- `extension`はここでは`CLLocationCoordinate2D`に緯度と経度を追加するために使ってるものと考えてください。

```swift
Map {
      Marker(
        "Tokyo",
        systemImage: "train.side.front.car",
        coordinate: .tokyo
      )
}
```
 `Maker()`の
- **第一引数**には表示する文字
- **第二引数**にはピンの見た目
- **第三引数**には表示する緯度経度
を指定してます。

![スクリーンショット 2024-09-08 22.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763749/0c87bd7a-4535-daf0-b28f-4c86172bdfd9.png)

こんな感じになればOKです！

### 現在地の取得の仕方
ここからかなり難しくなると思います
というより覚えることが増える

手順を書きます
1. `LocationManager`クラスを定義する
2. `info.plist`の作成
3. 位置情報を取得するための記述を書く
4. Viewで使う

**結論(コメントアウトに解説)**
```swift
import Foundation
import MapKit
                       
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
  // CLLocationManager()で位置情報を取得
  let manager = CLLocationManager()
  // MKCoordinateRegion()は範囲を指定する
  @Published var region = MKCoordinateRegion()
  
  override init() {
    // NSObjectを初期化
    super.init()
    // 位置が変わった時その情報を自分で受け取る
    manager.delegate = self
    // 位置情報を取得するための許可
    manager.requestWhenInUseAuthorization()
    // 正確な位置を取得
    manager.desiredAccuracy = kCLLocationAccuracyBest
    // 2メートルごとに位置を更新
    manager.distanceFilter = 2
    // 位置情報が変わるたびに情報をうけとれるように
    manager.startUpdatingLocation()
  }
  
  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    locations.last.map {
      let center = CLLocationCoordinate2D(
        latitude: $0.coordinate.latitude, longitude: $0.coordinate.longitude
      )
      
      region = MKCoordinateRegion(
        center: center,
        latitudinalMeters: 100.0,
        longitudinalMeters: 100.0
      )
    }
  }
}
```

```swift
import SwiftUI
import MapKit

struct ContentView: View {
  @ObservedObject var manager = LocationManager()
  
  @State var trackingMode = MapUserTrackingMode.follow
  var body: some View {
    Map (
         // 場所の範囲を決める
         coordinateRegion: $manager.region,
         // 自分のいる場所を地図に表示するか
         showsUserLocation: true,
         // 歩いてる時地図の中心を変えるか
         userTrackingMode: $trackingMode
    )
  }
}

#Preview {
  ContentView()
}

```


`LocationManager`クラスを定義する
新しいファイルを作成し、上のように書いてください
以下細かい説明(いらないよって方はすっ飛ばしてください)
```swift
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { 略}
```
LocationManagerをNSObject, ObservableObject, CLLocationManagerDelegateに準拠させます
- `NSObject`はhttps://qiita.com/Ryuto_Yuz/items/ce7f2091fea17a9408e8
を参考にしてください(あんま理解してなくてもいいです)
- `ObservableObject`にすることで位置情報の更新があっても大丈夫にできる(語彙力)
- `CLLocationManagerDelegate`を使うことによって位置が変わったときにその情報を教えてくれる役割(ObservableObjectはビューに知らせる役目だけどCLLocationManagerDelegateはCLLocationManagerに知らせる役目)
てな感じです

あとはコメントアウトの通り！


 `info.plist`の作成
画像のようにやってってください

 ![3ED18EAB-3FA1-48F8-9A04-D32EBEB62B01.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763749/8c6e1d5b-5968-4ccf-32f1-0db7aa114267.jpeg)

+ボタンを押すだけで画像のようになります！

![スクリーンショット 2024-09-08 23.14.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763749/01ea2b5a-0716-aace-f15c-6c41370b98ba.png)

![スクリーンショット 2024-09-08 23.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763749/cf41ea43-2c48-0b0c-cefa-53980c5388e1.png)

Documen typesは消しましょう

+ボタンを押し、`Privacy - Location When In Use Usage Description`と記述すればOKです!
![スクリーンショット 2024-09-08 23.17.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763749/c191f8fc-73e3-8a1b-cee7-7b98c8ba6312.png)


### 参考文献

https://developer.apple.com/documentation/mapkit/

https://www.amazon.co.jp/%E8%A9%B3%E7%B4%B0%EF%BC%81SwiftUI-iPhone%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA-%E5%85%A5%E9%96%80%E3%83%8E%E3%83%BC%E3%83%88-iOS-Xcode-13%E5%AF%BE%E5%BF%9C-ebook/dp/B09N3HRVV9/ref=sr_1_14?adgrpid=116928476824&dib=eyJ2IjoiMSJ9.rINdE6ZN9EDvWh5c-xD90_IjBwz8AkUQd2tvhtV6PH77oV8-QcvF-U8LyT-eNQv0WgquKO89_t_dBWEKNPUOMe5aHRHuGJMRSBnPKHngyg9yuU3MPTItp3_AO3Q1h1zJFUuYvpwlKFb5xNEJ_s2aIg0cF6mezWcIBwK0nTwM71iHp8r2kDsip0YZ1RVSd-CgoO50f9EOuO8iAgyiBjPbdj2kndo9mxHQM4gOI48lwgDugThEhJ6-jJ3NLPP1rrEDXZLv7ijbNfZzPPi-9QM4bG5D3j3Qvz7Eux9hNhXMLTg.4stdMpLPahY7OrCpKk8BSrsgf-U0RIesY6rqgdX6dl4&dib_tag=se&hvadid=679070296547&hvdev=c&hvlocphy=9198400&hvnetw=g&hvqmt=b&hvrand=12025014491872752933&hvtargid=kwd-993330800324&hydadcr=15819_13711663&jp-ad-ap=0&keywords=swiftui+%E6%9C%AC&qid=1725802653&sr=8-14