[英]How do I propertly subscribe to location updates when a View is visible?
I've created a class that implements CLLocationDelegate
and ObservableObject
so that it can let views subscribe to location updates using @StateObject
and @EnvironmentObject
.我创建了一个实现
CLLocationDelegate
和ObservableObject
的 class ,以便它可以让视图使用@StateObject
和@EnvironmentObject
订阅位置更新。 This works fine, but because only certain views need access to the location, I'd like to call startUpdatingLocation
and stopUpdatingLocation
when those views appear or disappear.这很好用,但是因为只有某些视图需要访问该位置,所以我想在这些视图出现或消失时调用
startUpdatingLocation
和stopUpdatingLocation
。
Assuming my view has access to the delegate and its location manager, where do I put the startUpdatingLocation
and stopUpdatingLocation
calls?假设我的视图可以访问委托及其位置管理器,我应该将
startUpdatingLocation
和stopUpdatingLocation
调用放在哪里?
My first inclination was to use onAppear
and onDisappear
like so.我的第一个倾向是像这样使用
onAppear
和onDisappear
。
struct ViewThatNeedsLocation : View {
@EnvironmentObject var locationDelegate: MyLocationDelegate
var body: some View {
Text("")
.onAppear {
locationDelegate.manager.startUpdatingLocation()
}.onDisappear {
locationDelegate.manager.stopUpdatingLocation()
}
}
}
But this suffers from a couple problems:但这有几个问题:
onAppear
and onDisappear
can be called multiple times due to parent changes, even if the user never sees the view visibly change. onAppear
和onDisappear
可以由于父级更改而被多次调用,即使用户从未看到视图明显更改。onDisappear
is not guaranteed to be called before a subsequent onAppear
call.onDisappear
调用之前调用onAppear
。 This means I can get the following order of events这意味着我可以获得以下事件顺序
onAppear
startUpdatingLocation (good)
onAppear (again)
startUpdatingLocation (redundant)
onDisappear (?)
stopUpdatingLocation (bad)
My guess is that ViewThatNeedsLocation
is being created and destroyed multiple times without the rendered content being changed.我的猜测是
ViewThatNeedsLocation
被多次创建和销毁,而渲染的内容没有被更改。 This would be fine if SwiftUI
provided some sort of guarantee about the order of the lifecycle modifiers, but it doesn't.如果
SwiftUI
提供了某种关于生命周期修饰符的顺序的保证,这会很好,但事实并非如此。
What is the correct way to do this?这样做的正确方法是什么? Is there a simple way to fire setup and teardown functions when a view appears and disappears reliably?
当视图可靠地出现和消失时,是否有一种简单的方法来触发设置和拆卸功能?
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)")
}
}
And in view struct:在视图结构中:
@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
}
})
I just need first location so i am calling locationManager.stopUpdatingLocation() in my view in userLocation function, but you can do that in onDisapear.我只需要第一个位置,所以我在 userLocation function 的视图中调用 locationManager.stopUpdatingLocation(),但您可以在 onDisapear 中执行此操作。 here you have some demo
在这里你有一些演示
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.