iOS MapKit 地圖與定位整合教學
MapKit 讓我們能輕鬆在 App 中嵌入 Apple Maps。在 SwiftUI 中,新的 Map API (iOS 17+) 變得非常直觀。
顯示地圖與控制視角
使用 MapCameraPosition 來控制地圖的顯示區域。
import MapKit
struct ContentView: View {
// 預設位置:台北 101
@State private var position: MapCameraPosition = .region(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 25.0339, longitude: 121.5644),
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
)
var body: some View {
Map(position: $position) {
// 加入標記
Marker("台北 101", coordinate: CLLocationCoordinate2D(latitude: 25.0339, longitude: 121.5644))
}
.mapStyle(.hybrid(elevation: .realistic)) // 3D 混合衛星地圖
.mapControls {
MapUserLocationButton() // 顯示「回到目前位置」按鈕
MapCompass() // 指南針
MapScaleView() // 比例尺
}
}
}
獲取使用者位置 (Core Location)
要獲取定位,需要使用 CLLocationManager。
步驟 1: 新增 Info.plist 權限
請在 Info.plist 新增以下 Key:
Privacy - Location When In Use Usage Description: 告訴使用者為什麼你需要定位。
步驟 2: 建立 Manager
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
let manager = CLLocationManager()
@Published var location: CLLocation?
@Published var authorizationStatus: CLAuthorizationStatus = .notDetermined
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
}
// 請求權限
func requestPermission() {
manager.requestWhenInUseAuthorization()
}
// Delegate: 權限狀態改變
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
authorizationStatus = manager.authorizationStatus
if authorizationStatus == .authorizedWhenInUse || authorizationStatus == .authorizedAlways {
manager.startUpdatingLocation()
}
}
// Delegate: 位置更新
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
location = locations.first
}
}
步驟 3: 在 Map 中顯示
Map {
UserAnnotation() // 顯示藍色小圓點
}
繪製路徑 (Polyline)
如果要在地圖上畫出跑步路徑或導航路線,可以使用 MapPolyline。
let locations = [
CLLocationCoordinate2D(latitude: 25.0339, longitude: 121.5644), // 起點
CLLocationCoordinate2D(latitude: 25.0380, longitude: 121.5644), // 中點
CLLocationCoordinate2D(latitude: 25.0400, longitude: 121.5700) // 終點
]
Map {
MapPolyline(coordinates: locations)
.stroke(.blue, lineWidth: 5)
}
搜尋地點 (MKLocalSearch)
MapKit 內建了搜尋興趣點 (POI) 的功能。
func searchPlaces(query: String) async -> [MKMapItem] {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = query
request.resultTypes = .pointOfInterest
guard let response = try? await MKLocalSearch(request: request).start() else {
return []
}
return response.mapItems
}
地圖與定位是 LBS (Location Based Service) 應用的核心,結合兩者可以開發出導航、周邊搜尋等強大功能。