在 SwiftUI 中为 MKMapView 添加"show user location"按钮的正确方法是什么?



我正在尝试创建一个带有MKMapView的SwiftUI视图和一个导航到用户位置的按钮。下面是我的全部代码。我创建了一个名为MapView的视图,它符合UIViewRepresentable来保存我的MKMapView。我有一个位置按钮,点击时,shouldNavigateToUserLocation设置为 true。这会导致 UI 重新加载,如果shouldNavigateToUserLocation为 true,我的MapView将导航到用户位置。然后,它将shouldNavigateToUserLocation设置为 false,以便 MapView 不会在每次状态更改时不断移动到用户位置。

这种方法在实际设备上运行时似乎有效,但我在第 87 行收到警告"在视图更新期间修改状态,这将导致未定义的行为",这是shouldNavigateToUserLocation = false.这是可以理解的,但我的问题是,我怎样才能避免这种情况?我似乎找不到重组代码的方法,所以我没有违反在视图更新期间不修改状态的规则,同时仍然让地图在用户按下按钮时导航到用户位置。

我尝试了几种不同的方法,但我主要遇到了我的 MapView 和我的控制器类实际上都无法直接访问 MKMapView 的问题。我理解为什么在 SwiftUI 中会这样,但它确实限制了我能做的事情。

这是我的全部代码:

import SwiftUI
import MapKit
struct ContentView: View {
@State var currentlyDisplayingLocationAuthorizationRequest = false
@State var shouldNavigateToUserLocation = false
let locationManager = CLLocationManager()
var body: some View {
ZStack {
MapView(currentlyDisplayingLocationAuthorizationRequest: $currentlyDisplayingLocationAuthorizationRequest,
shouldNavigateToUserLocation: $shouldNavigateToUserLocation)
HStack {
Spacer()
VStack {
Spacer()
Button(action: {
self.checkForLocationAuthorizationAndNavigateToUserLocation()
}) {
Image(systemName: "location")
.imageScale(.large)
.accessibility(label: Text("Locate Me"))
.padding()
}
.background(Color.gray)
.cornerRadius(10)
.padding()
}
}
}
.onAppear {
self.shouldNavigateToUserLocation = true
}
}
func checkForLocationAuthorizationAndNavigateToUserLocation() {
currentlyDisplayingLocationAuthorizationRequest = false
if CLLocationManager.authorizationStatus() == .notDetermined {
print("location authorization not determined")
currentlyDisplayingLocationAuthorizationRequest = true
locationManager.requestWhenInUseAuthorization()
return
}
shouldNavigateToUserLocation = true
}
}
struct MapView: UIViewRepresentable {
@Binding var currentlyDisplayingLocationAuthorizationRequest: Bool
@Binding var shouldNavigateToUserLocation: Bool
let locationManager = CLLocationManager()
func makeUIView(context: Context) -> MKMapView {
let map = MKMapView()
map.delegate = context.coordinator
map.showsUserLocation = true
return map
}
func updateUIView(_ uiView: MKMapView, context: Context) {
if !currentlyDisplayingLocationAuthorizationRequest && shouldNavigateToUserLocation {
moveToUserLocation(map: uiView)
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
// MARK: Location -
private func moveToUserLocation(map: MKMapView) {
guard let location = locationManager.location else { return }
let region = MKCoordinateRegion(center: location.coordinate,
span: MKCoordinateSpan(latitudeDelta: 0.02,
longitudeDelta: 0.02))
map.setRegion(region, animated: true)
shouldNavigateToUserLocation = false
}
// MARK: Coordinator -
final class Coordinator: NSObject, MKMapViewDelegate {
var control: MapView
init(_ control: MapView) {
self.control = control
}
}
}

这不是您要搜索的内容,但您应该看看我最近对另一个相关问题的回答(如何在 swiftUI 中添加移回用户位置按钮?我认为它可以帮助你,或者其他人,如果他们面临同样的问题。

相关内容

最新更新