简体   繁体   English

当视图可见时,如何正确订阅位置更新?

[英]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 .我创建了一个实现CLLocationDelegateObservableObject的 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.这很好用,但是因为只有某些视图需要访问该位置,所以我想在这些视图出现或消失时调用startUpdatingLocationstopUpdatingLocation

Assuming my view has access to the delegate and its location manager, where do I put the startUpdatingLocation and stopUpdatingLocation calls?假设我的视图可以访问委托及其位置管理器,我应该将startUpdatingLocationstopUpdatingLocation调用放在哪里?

My first inclination was to use onAppear and onDisappear like so.我的第一个倾向是像这样使用onAppearonDisappear

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. onAppearonDisappear可以由于父级更改而被多次调用,即使用户从未看到视图明显更改。
  • 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.

相关问题 我如何知道视图是否可见? - How do I know if a view is visible or not? 双击集合视图单元格时如何使图像可见? - How do I make image visible when collection view cell is double tapped? 如何处理自定义结果视图的NSFetchedResultsControllerDelegate更新 - How do I Handle NSFetchedResultsControllerDelegate updates for custom results view 如何从视图控制器或类检查特定的视图控制器在屏幕上是否可见? 或如何检查可见的视图控制器? - How do I check from a view controller or class if a specific view controller is visible on screen? Or how do I check visible view controller? 如何检查另一个视图控制器是否可见? - How do i check if another view controller is visible? 如何停止其他班级/视图的位置更新? - How to stop location updates from another class/view? 我如何订阅事件循环的结尾 - How do I subscribe to the end of the event loop 推送到另一个视图后,如何使此ios按钮在提要视图中保持可见? - How do i get this ios button to stay visible in the feed view after pushing to another view? 如何在不保持图标的情况下进行每小时位置更新? - How to do hourly location updates without keeping the icon on? iOS:用户可见视图后需要执行某些操作时要覆盖哪个函数? - iOS: Which function to override when I need to do something after the view is visible to the user?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM