如何使用 SwiftUI 中新地圖框架 MapKit
前言
了解 iOS 17 中的 MapKit 后,我們會發(fā)現(xiàn) Apple 引入了更適合 SwiftUI 的 API。
MapKit 棄用項
一旦將你的 App 目標(biāo)更新到 iOS 17,Xcode 會將任何使用舊的 Map 初始化器的用法標(biāo)記為已棄用:
會有警告提示:init coordinate region 已在 iOS 17 中棄用。請改用帶有 MapContentBuilder 參數(shù)的地圖初始化器。
在 iOS 17 中,MapKit 為 SwiftUI 引入了需要 MapContentBuilder 參數(shù)的地圖初始化器。下面為大家介紹一下MapKit 相關(guān)的基礎(chǔ)知識。
MapContentBuilder(iOS 17)
在 iOS 17 中,用于地圖視圖的各種初始化器都需要一個名為 MapContentBuilder 的 content 參數(shù)。MapContentBuilder 是一個結(jié)果構(gòu)建器,允許在閉包中添加地圖內(nèi)容,例如標(biāo)記、注釋和自定義內(nèi)容。
下面讓我們看看是如何使用的,這里是一些倫敦地標(biāo)的坐標(biāo):
extension CLLocationCoordinate2D {
static let towerBridge = CLLocationCoordinate2D(latitude: 51.5055, longitude: -0.075406)
static let boe = CLLocationCoordinate2D(latitude: 51.5142, longitude: -0.0885)
static let hydepark = CLLocationCoordinate2D(latitude: 51.508611, longitude: -0.163611)
static let kingsCross = CLLocationCoordinate2D(latitude: 51.5309, longitude: -0.1233)
}
要創(chuàng)建一個帶有標(biāo)記和注釋的地圖視圖,詳細(xì)代碼如下:
struct ContentView: View {
var body: some View {
Map {
Marker("Tower Bridge", coordinate: .towerBridge)
Marker("Hyde Park", coordinate: .hydepark)
Marker("Bank of England",
systemImage: "sterlingsign", coordinate: .boe)
.tint(.green)
Annotation("Kings Cross",
coordinate: .kingsCross, anchor: .bottom) {
VStack {
Text("在此搭乘火車!")
Image(systemName: "train.side.front.car")
}
.foregroundColor(.blue)
.padding()
.background(in: .capsule)
}
}
}
}
在沒有其他選項的情況下,地圖視圖的邊界將包圍地圖內(nèi)容。
地圖交互
為了控制用戶與地圖的交互方式,可以傳遞一組允許的模式。默認(rèn)情況下允許所有模式(平移、縮放、傾斜、旋轉(zhuǎn)),代碼如下:
Map(interactionModes: [.pan,.pitch]) { ... }
地圖樣式
使用 Map Style 視圖修飾符可以在標(biāo)準(zhǔn)、衛(wèi)星或混合樣式之間切換,控制高度、顯示興趣點和顯示交通情況,代碼如下:
Map { ...
}
.mapStyle(.hybrid(elevation: .realistic,
pointsOfInterest: .including([.publicTransport]),
showsTraffic: true))
地圖控件
標(biāo)準(zhǔn)的地圖控件,如指南針、用戶位置、傾斜、比例尺和縮放控件都實現(xiàn)為 SwiftUI 視圖。這意味著可以將它們放置在視圖的任何位置,不過需要定義一個地圖范圍命名空間,以將它們與它們控制的地圖關(guān)聯(lián)起來,代碼如下:
struct ContentView: View {
@Namespace var mapScope
var body: some View {
VStack {
Map(scope: mapScope) { ... }
MapCompass(scope: mapScope)
}
.mapScope(mapScope)
}
}
要將它們放置在標(biāo)準(zhǔn)位置,使用地圖控件視圖修飾符,代碼如下:
Map { ...
}
.mapControls {
MapPitchToggle()
MapUserLocationButton()
MapCompass()
}
地圖相機(jī)位置
地圖相機(jī)位置定義了從地圖表面上方查看地圖的虛擬位置??梢允褂矛F(xiàn)有的地圖項、地圖邊界、區(qū)域或用戶位置來創(chuàng)建地圖相機(jī)位置并設(shè)置初始地圖位置,代碼如下:
Map(initialPosition: position)
將 MapCameraPosition 的綁定傳遞給地圖,使其在用戶在地圖上移動時跟蹤相機(jī)位置,代碼如下:
struct ContentView: View {
@State private var position: MapCameraPosition = .region(.uk)
var body: some View {
Map(position: $position) {
Marker("Tower Bridge", coordinate: .towerBridge)
}
}
}
設(shè)置位置會導(dǎo)致地圖更改其相機(jī)位置以匹配。例如,在用戶移動位置后,要在 toolbar 中添加一個按鈕,以將地圖重置為初始位置,代碼如下:
Map(position: $position) { ...
}
.toolbar {
ToolbarItem {
Button("重置") {
position = .region(.uk)
}
}
}
將位置設(shè)置為 .automatic 可以使地圖框架內(nèi)容。
總結(jié)
這就是在 iOS 17 中使用 SwiftUI 中的 MapKit 所需要了解的內(nèi)容。通過引入 MapContentBuilder 和其他新的初始化器,可以更方便地創(chuàng)建交互式地圖視圖,添加標(biāo)記、注釋和自定義內(nèi)容,并在用戶移動地圖相機(jī)時自動更新位置。
此外,還可以使用 Map Style 修飾符和 Map 控件來自定義地圖的樣式和控件。這些改進(jìn)使得在 SwiftUI 中使用 MapKit 變得更加強(qiáng)大和靈活。