[英]How do I propertly subscribe to location updates when a View is visible?
我创建了一个实现CLLocationDelegate
和ObservableObject
的 class ,以便它可以让视图使用@StateObject
和@EnvironmentObject
订阅位置更新。 这很好用,但是因为只有某些视图需要访问该位置,所以我想在这些视图出现或消失时调用startUpdatingLocation
和stopUpdatingLocation
。
假设我的视图可以访问委托及其位置管理器,我应该将startUpdatingLocation
和stopUpdatingLocation
调用放在哪里?
我的第一个倾向是像这样使用onAppear
和onDisappear
。
struct ViewThatNeedsLocation : View {
@EnvironmentObject var locationDelegate: MyLocationDelegate
var body: some View {
Text("")
.onAppear {
locationDelegate.manager.startUpdatingLocation()
}.onDisappear {
locationDelegate.manager.stopUpdatingLocation()
}
}
}
但这有几个问题:
onAppear
和onDisappear
可以由于父级更改而被多次调用,即使用户从未看到视图明显更改。onDisappear
调用之前调用onAppear
。这意味着我可以获得以下事件顺序
onAppear
startUpdatingLocation (good)
onAppear (again)
startUpdatingLocation (redundant)
onDisappear (?)
stopUpdatingLocation (bad)
我的猜测是ViewThatNeedsLocation
被多次创建和销毁,而渲染的内容没有被更改。 如果SwiftUI
提供了某种关于生命周期修饰符的顺序的保证,这会很好,但事实并非如此。
这样做的正确方法是什么? 当视图可靠地出现和消失时,是否有一种简单的方法来触发设置和拆卸功能?
class LocationManager: NSObject, ObservableObject {
private let locationManager = CLLocationManager()
@Published var authorizationStatus: CLAuthorizationStatus = .notDetermined
@Published var location: CLLocation?
@Published var region: CLRegion?
override init() {
super.init()
self.locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
}
extension LocationManager: CLLocationManagerDelegate {
func requestLocation() {
locationManager.requestLocation()
}
func updateLocation() {
locationManager.startUpdatingLocation()
}
func stopUpdatingLocation() {
locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
self.authorizationStatus = status
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
self.location = location
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("error getting location \(error.localizedDescription)")
}
}
在视图结构中:
@ObservedObject var locationManager = LocationManager()
@State private var location: CLLocation?
.onReceive(locationManager.$location, perform: userLocation)
.onReceive(locationManager.$authorizationStatus, perform: { status in
switch status {
case .authorizedAlways:
locationManager.updateLocation()
case .authorizedWhenInUse:
locationManager.updateLocation()
default:
break
}
})
我只需要第一个位置,所以我在 userLocation function 的视图中调用 locationManager.stopUpdatingLocation(),但您可以在 onDisapear 中执行此操作。 在这里你有一些演示
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.