使用 startUpdatingLocation() 和 stopUpdatingLocation() 到 activate/deactivate 特定视图中的位置更新
Using startUpdatingLocation() and stopUpdatingLocation() to activate/deactivate location updates in specific Views
基于 Whosebug 中的一些代码示例,我为位置服务创建了一个 class。应用程序启动时会立即启动位置服务,由上方系统栏中的导航符号指示。我的应用仅在特定视图中需要定位服务,因此我想 activate/deactivate 特定事件的定位服务。这可以减少能源消耗并提高客户的信心,即仅在需要时才使用定位服务。
首先我定义了一个class 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 实例 class:
import SwiftUI
struct LocationView : View
{
// some say, that a @StateObject is preferred over @ObservedObject, see:
//
@ObservedObject var locationViewModel = LocationViewModel()
var body: some View
{
VStack
{
Text("Latitude: \(locationViewModel.userLatitude)")
Text("Longitude: \(locationViewModel.userLongitude)")
}
.navigationTitle("Location")
.navigationBarTitleDisplayMode(.inline)
}
}
问题:
为什么应用一启动就启动定位服务? override init() 方法调用 startUpdatingLocation(),但 LocationView(定义为 NavigationView 的一部分)不会在应用程序启动时显示。这是 NavigationView 的效果吗?
如何从实例外部访问 self.locationManager 的 startUpdatingLocation() 方法?有没有办法直接做到这一点,或者是否有必要创建一个特定的包装方法(因为我已经尝试过但没有成功)? LocationViewModel 实例不提供任何方法(XCode 表示没有完成)。
当特定视图变为 visible/invisble 时,如何 start/stop 位置更新(导航符号消失)?我发现的所有代码示例都实现了永久位置更新。
解法:
我的错误是试图在声明视图主体之前调用locationViewModel.locationManager.startUpdatingLocation()方法。
.navigationTitle("Simulation")
.navigationBarTitleDisplayMode(.inline)
.onAppear(perform: {locationViewModel.locationManager.startUpdatingLocation()})
.onDisappear(perform: {locationViewModel.locationManager.stopUpdatingLocation()})
基于 Whosebug 中的一些代码示例,我为位置服务创建了一个 class。应用程序启动时会立即启动位置服务,由上方系统栏中的导航符号指示。我的应用仅在特定视图中需要定位服务,因此我想 activate/deactivate 特定事件的定位服务。这可以减少能源消耗并提高客户的信心,即仅在需要时才使用定位服务。
首先我定义了一个class 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 实例 class:
import SwiftUI
struct LocationView : View
{
// some say, that a @StateObject is preferred over @ObservedObject, see:
//
@ObservedObject var locationViewModel = LocationViewModel()
var body: some View
{
VStack
{
Text("Latitude: \(locationViewModel.userLatitude)")
Text("Longitude: \(locationViewModel.userLongitude)")
}
.navigationTitle("Location")
.navigationBarTitleDisplayMode(.inline)
}
}
问题:
为什么应用一启动就启动定位服务? override init() 方法调用 startUpdatingLocation(),但 LocationView(定义为 NavigationView 的一部分)不会在应用程序启动时显示。这是 NavigationView 的效果吗?
如何从实例外部访问 self.locationManager 的 startUpdatingLocation() 方法?有没有办法直接做到这一点,或者是否有必要创建一个特定的包装方法(因为我已经尝试过但没有成功)? LocationViewModel 实例不提供任何方法(XCode 表示没有完成)。
当特定视图变为 visible/invisble 时,如何 start/stop 位置更新(导航符号消失)?我发现的所有代码示例都实现了永久位置更新。
解法:
我的错误是试图在声明视图主体之前调用locationViewModel.locationManager.startUpdatingLocation()方法。
.navigationTitle("Simulation")
.navigationBarTitleDisplayMode(.inline)
.onAppear(perform: {locationViewModel.locationManager.startUpdatingLocation()})
.onDisappear(perform: {locationViewModel.locationManager.stopUpdatingLocation()})