🙆♀️
SwiftUI MapKit 基礎
MapKitを追加する方法
以下のようなコードを書くとマップが登場します
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
Map()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
アノテーションをつける
まずは自分の建てたいピンの位置の緯度と軽度の座標を調べる
*Swiftではdegree形式がデフォルト
CLLocationCordinate2Dを使い座標を指定する
import SwiftUI
import MapKit
extension CLLocationCoordinate2D {
static let kamikitazawa_sta = CLLocationCoordinate2D(latitude: 35.6689, longitude: 139.6234)
}
struct ContentView: View {
var body: some View {
Map {
Annotation("Kamikitazawa-Station",
coordinate: .kamikitazawa_sta, anchor: .bottom) {
VStack {
Text("Kamikitazawa Sta")
Image(systemName: "flag.2.crossed")
}
.foregroundColor(.blue)
.padding()
.background(in: .capsule)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
地図のスタイルの変更
3Dにするためには.mapStyle(.standard)から .mapStyle(.standard(elevation: .realistic))にする
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
Map()
.mapStyle(.standard(elevation: .realistic))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
現実的にするには.mapStyle(.standard)から.mapStyle(.imagery)に変える
import SwiftUI
import MapKit
struct ContentView: View {
var body: some View {
Map()
.mapStyle(.imagery(elevation: .realistic))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
現在位置を表示する
プロジェクトナビゲーターで、プロジェクトの「Info.plist」ファイルを探し、選択します
「Information Property List」セクションで、右上の「+」ボタンをクリックし、新しいキーを追加します
表示されるウィンドウで「Privacy - Location Always and When In Use Usage Description」キーを選択します
キーの横にある値の欄に、ユーザに向けた位置情報使用の理由を説明する文字列を入力します (例: "現在地を表示させるために必要です")
import SwiftUI
import MapKit
import CoreLocation
import Combine
struct ContentView: View {
@StateObject private var locationManager = LocationManager()
var body: some View {
Map(coordinateRegion: $locationManager.region, showsUserLocation: true, annotationItems: locationManager.annotations) { annotation in
MapMarker(coordinate: annotation.coordinate)
}
.edgesIgnoringSafeArea(.all)
.onAppear {
locationManager.requestLocation()
}
}
}
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let manager = CLLocationManager()
@Published private(set) var annotations: [LocationAnnotation] = []
@Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 35.6895, longitude: 139.6917), span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
}
func requestLocation() {
manager.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
let annotation = LocationAnnotation(coordinate: location.coordinate)
annotations = [annotation]
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
region = MKCoordinateRegion(center: center, span: span)
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
struct LocationAnnotation: Identifiable {
let id = UUID()
let coordinate: CLLocationCoordinate2D
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
MapKitのcontrols
import SwiftUI
import MapKit
struct ContentView: View {
@Namespace var mapScope
var body: some View {
Map (scope: mapScope)
.overlay(alignment: .bottomTrailing) {
VStack {
MapUserLocationButton(scope: mapScope)
MapPitchButton(scope: mapScope)
MapCompass(scope: mapScope)
.mapControlVisibility(.visible)
}
.padding(.trailing, 10)
.buttonBorderShape(.circle)
}
.mapScope(mapScope)
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
}
参考資料
Discussion