SwiftUIでMapKitを使いたい!
対象者
SwiftUIでMapKitを使って地図を表示する機能を作るのをやってみたい人が対象です。筆者もやってみたい初心者です笑
やること/やらないこと
やること:
SwiftUIの標準のAPIを使う
やらないこと:
MapKitについて深掘りしません。内部のコード見たり調べてみたのですが、公式と書方が違う?
なんかパラメーター渡すとか、プロトコルに準拠してないからとエラーが出ました💦
プロジェクトの説明
まずは、x-codeで新規プロジェクトを作成して、ContentView
に以下のコードを書いてください!
import SwiftUI
import MapKit
struct Location: Identifiable {
let id = UUID()
let coordinate: CLLocationCoordinate2D
}
struct ContentView: View {
let cityHallLocation = Location(coordinate: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194))
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
)
var body: some View {
Map(coordinateRegion: $region, annotationItems: [cityHallLocation]) { location in
MapMarker(coordinate: location.coordinate)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
このように書かないとMapが表示できなかった???
公式やネットのコードが古いのかiOSのバージョンのせいかMap()
だけでは使えない?
コードの解説とハマったこと!
MapビューのannotationItemsパラメータは、Identifiableプロトコルに準拠する必要があります。しかし、CLLocationCoordinate2Dはその要件を満たしていません。そのため、Identifiableプロトコルに準拠する新しい型を作成し、その型のインスタンスをannotationItemsに渡す必要があります。
import SwiftUI
import MapKit
struct Location: Identifiable {
let id = UUID()
let coordinate: CLLocationCoordinate2D
}
struct ContentView: View {
let cityHallLocation = Location(coordinate: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194))
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
)
var body: some View {
Map(coordinateRegion: $region, annotationItems: [cityHallLocation]) { location in
MapMarker(coordinate: location.coordinate)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
このコードでは、Locationという新しい型を作成し、それがIdentifiableプロトコルに準拠するようにしています。そして、LocationのインスタンスをannotationItemsに渡しています。
これでもエラが出た!
Location構造体はIdentifiableプロトコルに準拠していますが、それを使用していないようで、cityHallLocationをCLLocationCoordinate2DからLocationに変更する必要がありました。
struct ContentView: View {
let cityHallLocation = Location(coordinate: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194))
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
)
var body: some View {
Map(coordinateRegion: $region, annotationItems: [cityHallLocation]) { location in
MapMarker(coordinate: location.coordinate)
}
}
}
この修正により、annotationItemsパラメータにIdentifiableプロトコルに準拠したLocation型のオブジェクトを渡すことができます。
Previewで表示できた💦
感想
MapKitの公式を見てみたが、私の環境ではなぜか使えない???
チュートリアルの動画も見てみたが、Map
のところの括弧の書方が違う気がした???
x-codeのバージョンは、14.3.1を使用しております。
追加情報
東京都渋谷の情報を表示するには、このように書けばできます。
Mapの中に、以下のようなパラメーターを渡す必要がある。
import SwiftUI
import MapKit
struct ContentView: View {
// 東京渋谷の座標
let shibuyaCoordinate = CLLocationCoordinate2D(latitude: 35.658035, longitude: 139.701636)
var body: some View {
Map(coordinateRegion: .constant(MKCoordinateRegion(
center: shibuyaCoordinate,
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)))
.edgesIgnoringSafeArea(.all)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Discussion