はじめに
個人開発中のアプリでMapkitが必要になったんですが、かなり苦戦したため書こうと思いました。
Mapkitに苦しんでる人は、この記事を読みながら手を動かして一緒にやりましょう!
目次
- Mapkitの基礎
- アノテーション(ピン)の付け方
- 現在地の取得の仕方
- 参考文献
Mapkitの基礎
まずMapkitとは
「Display map or satellite imagery within your app, call out points of interest, and determine placemark information for map coordinates.」
だそうです(公式)
直訳すると「アプリ内で地図や衛星画像を表示し、興味のある場所を示し、地図の座標に対する地名情報を取得します。」です
ようするに地図を表示するためのフレームワークみたいなもんです。
一番簡単な例
import SwiftUI
// Mapkitのimport
import MapKit
struct ContentView: View {
var body: some View {
// Mapを表示
Map()
}
}
#Preview {
ContentView()
}
直感的にもわかりやすいですね。
import Mapkit
でフレームワークを導入して、Map()
で呼び出してます。
こんな感じで表示されたらOKです。
アノテーション(ピン)の付け方
アノテーションはピンみたいなものです。
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を使う人にとっては訳がわからなくなってきます。
解説
extension CLLocationCoordinate2D {
static let tokyo = CLLocationCoordinate2D(
latitude: 35.681236,
longitude: 139.767125
)
}
- 緯度と経度を
CLLocationCoordinate2D
で指定したらその場所を特定してくれます。 -
extension
はここではCLLocationCoordinate2D
に緯度と経度を追加するために使ってるものと考えてください。
Map {
Marker(
"Tokyo",
systemImage: "train.side.front.car",
coordinate: .tokyo
)
}
Maker()
の
- 第一引数には表示する文字
- 第二引数にはピンの見た目
-
第三引数には表示する緯度経度
を指定してます。
こんな感じになればOKです!
現在地の取得の仕方
ここからかなり難しくなると思います
というより覚えることが増える
手順を書きます
-
LocationManager
クラスを定義する -
info.plist
の作成 - 位置情報を取得するための記述を書く
- Viewで使う
結論(コメントアウトに解説)
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
)
}
}
}
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
クラスを定義する
新しいファイルを作成し、上のように書いてください
以下細かい説明(いらないよって方はすっ飛ばしてください)
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { 略}
LocationManagerをNSObject, ObservableObject, CLLocationManagerDelegateに準拠させます
-
NSObject
はhttps://qiita.com/Ryuto_Yuz/items/ce7f2091fea17a9408e8
を参考にしてください(あんま理解してなくてもいいです) -
ObservableObject
にすることで位置情報の更新があっても大丈夫にできる(語彙力) -
CLLocationManagerDelegate
を使うことによって位置が変わったときにその情報を教えてくれる役割(ObservableObjectはビューに知らせる役目だけどCLLocationManagerDelegateはCLLocationManagerに知らせる役目)
てな感じです
あとはコメントアウトの通り!
info.plist
の作成
画像のようにやってってください
+ボタンを押すだけで画像のようになります!
Documen typesは消しましょう
+ボタンを押し、Privacy - Location When In Use Usage Description
と記述すればOKです!
参考文献