前语
SwiftUI 与 MapKit 的集成在本年发生了严重变化。在之前的 SwiftUI 版别中,咱们将 MKMapView 的基本功能封装到名为 Map 的 SwiftUI 视图中。走运的是,事情发生了变化,SwiftUI 引入了与 MapKit 集成的新 API。本篇文章咱们将学习如安在 SwiftUI 的最新版别中运用可用的新功能丰厚的 API 与 MapKit 集成。
正如我之前所说,在 SwiftUI 框架的前期版别中,咱们有一个 Map 视图,为咱们供给了 MapKit 的基本功能,该功能现在已被弃用。在面向较早 Apple 渠道版别的情况下,依然运用已弃用的 Map 视图是有意义的。
新 MapKit API 的引入
新的 MapKit API 引入了 MapContentBuilder 成果构建器,它看起来类似于 ViewBuilder,但是运用符合 MapContent 协议的类型。让咱们从运用 SwiftUI 中最新迭代中供给的新 MapKit API 集成的基本示例开始。
import MapKit
import SwiftUI
extension CLLocationCoordinate2D {
static let newYork: Self = .init(
latitude: 40.730610,
longitude: -73.935242
)
static let seattle: Self = .init(
latitude: 47.608013,
longitude: -122.335167
)
static let sanFrancisco: Self = .init(
latitude: 37.733795,
longitude: -122.446747
)
}
struct ContentView: View {
var body: some View {
Map {
Annotation("Seattle", coordinate: .seattle) {
Image(systemName: "mappin")
.foregroundStyle(.black)
.padding()
.background(.red)
.clipShape(Circle())
}
Marker(coordinate: .newYork) {
Label("New York", systemImage: "mappin")
}
Marker("San Francisco", monogram: Text("SF"), coordinate: .sanFrancisco)
}
}
}
正如你在上面的示例中看到的,咱们经过运用 MapContentBuilder 闭包界说地图,并在其上放置内容。MapContentBuilder 类型与符合 MapContent 协议的任何类型一同运用。
在咱们的示例中,咱们运用了 Marker 和 Annotation 类型。Marker 是一个基本项,答应咱们在地图上放置预界说的标记。Annotation 类型更先进,将使咱们能够运用纬度和经度在地图上放置 SwiftUI 视图。
SwiftUI 为咱们供给了许多符合 MapContent 协议的类型。咱们已经运用了其间的两个:Marker 和 Annotation。其间许多包含 MapCircle、MapPolygon、MapPolyline、UserAnnotation 等。
struct ContentView: View {
var body: some View {
Map {
Annotation("Seattle", coordinate: .seattle) {
Image(systemName: "mappin")
.foregroundStyle(.black)
.padding()
.background(.red)
.clipShape(Circle())
}
Marker(coordinate: .newYork) {
Label("New York", systemImage: "mappin")
}
UserAnnotation()
}
}
}
操控初始地图方位
你能够经过运用 Map 初始化器的另一个重载来操控地图的初始方位,该初始化器供给 initialPosition 参数。
struct ContentView: View {
let initialPosition: MapCameraPosition = .userLocation(
fallback: .camera(
MapCamera(centerCoordinate: .newYork, distance: 0)
)
)
var body: some View {
Map(initialPosition: initialPosition) {
Annotation("Seattle", coordinate: .seattle) {
Image(systemName: "mappin")
.foregroundStyle(.black)
.padding()
.background(.red)
.clipShape(Circle())
}
Marker(coordinate: .newYork) {
Label("New York", systemImage: "mappin")
}
Marker("San Francisco", monogram: Text("SF"), coordinate: .sanFrancisco)
}
}
}
initialPosition 参数接受 MapCameraPosition 类型的实例。MapCameraPosition 答应咱们以几种方法界说地图方位。它能够是咱们在示例中运用的用户方位,或许你能够运用 camera、region、rect 或 item 等静态函数将其指向地图上的任何区域。默认情况下,它运用 MapCameraPosition 类型的主动实例,该类型合适地图内容。
相机方位的双向绑定
每逢你需要对相机方位有稳定的操控时,你能够运用 Map 初始化器的另一个重载,答应你供给与地图相机方位的双向绑定。
struct ContentView: View {
@State private var position: MapCameraPosition = .userLocation(
fallback: .camera(
MapCamera(centerCoordinate: .newYork, distance: 0)
)
)
var body: some View {
Map(position: $position) {
// ...
}
}
}
SwiftUI 在用户拖动地图时更新方位绑定。它还在你以编程方法更新 position 特点时立即更新地图相机方位。
struct ContentView: View {
@State private var position: MapCameraPosition = .userLocation(
fallback: .camera(
MapCamera(centerCoordinate: .newYork, distance: 0)
)
)
var body: some View {
Map(position: $position, interactionModes: .pitch) {
// ...
}
}
}
经过运用 interactionModes 参数,你能够操控与地图答应的交互类型。MapInteractionModes 类型界说了一组交互,如平移、俯仰、旋转和缩放。默认情况下,它启用所有可用的交互类型。
总结
今天,咱们学习了在 SwiftUI 中集成 MapKit 的基础知识。在接下来的几周里,咱们将持续评论相机操作、地图控件和其他高档主题。希望你喜欢这篇文章。