【问题标题】:Using startUpdatingLocation() and stopUpdatingLocation() to activate/deactivate location updates in specific Views使用 startUpdatingLocation() 和 stopUpdatingLocation() 在特定视图中激活/停用位置更新
【发布时间】:2021-05-29 21:59:07
【问题描述】:

基于 stackoverflow 中的一些代码示例,我创建了一个定位服务类。定位服务在应用启动时立即启动,由上方系统栏中的导航符号指示。我的应用程序只需要特定视图中的位置服务,因此我想在特定事件上激活/停用位置服务。这可以减少能源消耗并提高客户的信心,即仅在需要时使用位置服务。

首先我定义了一个LocationViewModel类:

import SwiftUI
import Foundation
import Combine
import CoreLocation
import CoreMotion

class LocationViewModel: NSObject, ObservableObject
{

    @Published var userLatitude: Double = 0
    @Published var userLongitude: Double = 0
        
    private let locationManager = CLLocationManager()

    override init()
    {
        super.init()
        
        self.locationManager.delegate = self
        
        self.locationManager.startUpdatingLocation()
    }
    
    // I tried this to access the startUpdatingLocation() method, but it did not work
    func startUpdatingLocation()
    {
        self.locationManager.startUpdatingLocation()
    }
        
}

extension LocationViewModel: CLLocationManagerDelegate
{
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    {
        guard let location = locations.last else { return }
        
        userLatitude = location.coordinate.latitude
        userLongitude = location.coordinate.longitude
    }
}

接下来,在作为 NavigationView 一部分的特定 LocationView 中,我创建 LocationViewModel 类的实例:

import SwiftUI

struct LocationView : View
{
    // some say, that a @StateObject is preferred over @ObservedObject, see:
    // https://stackoverflow.com/questions/59620573/handle-swiftui-and-corelocation-with-mvvm-pattern
    @ObservedObject var locationViewModel = LocationViewModel()
    
    var body: some View
    {
        VStack
        {
            Text("Latitude: \(locationViewModel.userLatitude)")
            Text("Longitude: \(locationViewModel.userLongitude)")
        }
        .navigationTitle("Location")
        .navigationBarTitleDisplayMode(.inline)
    }
}

问题:

  1. 为什么应用启动时定位服务会启动?覆盖 init() 方法调用 startUpdatingLocation(),但 LocationView(定义为 NavigationView 的一部分)不会在应用启动时显示。这是 NavigationView 的效果吗?

  2. 如何从实例外部访问 self.locationManager 的 startUpdatingLocation() 方法?有什么方法可以直接做到这一点,还是有必要创建一个特定的包装方法(因为我已经尝试过但没有成功)? LocationViewModel 实例不提供任何方法(XCode 表示没有完成)。

  3. 当特定视图变得可见/不可见时,如何开始/停止位置更新(导航符号消失)?我发现的所有代码示例都实现了永久位置更新。

【问题讨论】:

  • 最好将位置管理器的单个实例注入到环境中。然后您可以在.onAppear 中开始更新位置
  • 如果您的LocationViewNavigationLink 的目的地,则当导航链接显示在屏幕上时,将调用其init 方法。因此,您在init 中所做的任何工作都将在那时执行。
  • 感谢您的提示。这回答了我的问题 1 和 3。@Paulw11:你能描述一下“注入环境”是什么意思吗?将locationViewModel 声明为@ObservedObject 使locationManager 可用于不同的视图。我对此很好,除了无法启动/停止位置更新。我只是无法以调用 locationManager 方法的方式访问locationViewModel 实例。

标签: ios swift swiftui core-location cllocationmanager


【解决方案1】:

解决方案:

我的错误是试图在视图主体声明之前调用 locationViewModel.locationManager.startUpdatingLocation() 方法。

        .navigationTitle("Simulation")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear(perform: {locationViewModel.locationManager.startUpdatingLocation()})
        .onDisappear(perform: {locationViewModel.locationManager.stopUpdatingLocation()})

【讨论】:

    猜你喜欢
    • 2018-12-17
    • 1970-01-01
    • 2012-03-17
    • 2010-10-23
    • 2010-12-04
    • 1970-01-01
    • 2021-11-07
    • 2022-09-27
    • 1970-01-01
    相关资源
    最近更新 更多