watchOS didUpdateLocation 在位置更改期间冻结
watchOS didUpdateLocation freezes during location change
我正在为 watchOS 在 SwiftUI 中开发一个 运行ning 应用程序。问题是,当我启动 运行 时,测量工作正常 0.55 0.56 0.57
公里等。然后它随机冻结,并从 0.57
直接跳到 0.71
。甚至总距离有时也不准确。当我查看运行的地图时,有时会看到尖角和曲线中的直线,这意味着测量非常不准确。 OS 是 watchOS 8.0。我已经尝试 kCLLocationAccuracyBest
没有用。
我在名为 DistanceObservable
的 ObservableObject 中使用了 CLLocationManager
,并且我在 iOS 应用程序中有这个精确的代码可以完美地测量距离。
... @Published var distance: Double = 0.0
func startUpdate() {
self.manager = CLLocationManager()
self.manager?.delegate = self
self.manager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.manager?.requestWhenInUseAuthorization()
self.manager?.distanceFilter = 10.0
self.manager?.allowsBackgroundLocationUpdates = true
self.manager?.startUpdatingLocation()
}
这是我的watchOS
didUpdateLocations
方法。
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var locations = locations
for newLocation in locations {
let howRecent = newLocation.timestamp.timeIntervalSinceNow
guard newLocation.horizontalAccuracy < 20 && abs(howRecent) < 10 else { continue }
if let lastLocation = locationList.last {
let delta = newLocation.distance(from: lastLocation)
if (delta < 60) { // To prevent inaccurate "jumps" in distance
distance = distance + delta
if UserDefaults.standard.value(forKey: "hasSet") as!Bool == false {
distance = 0
locations.removeAll()
UserDefaults.standard.setValue(true, forKey: "hasSet")
}
latPoints.append(Double(locationList.last!.coordinate.latitude))
lonPoints.append(Double(locationList.last!.coordinate.longitude))
}
}
locationList.append(newLocation)
}
}
最后我在 SwiftUI 视图中使用 @EnvironmentObject
。
struct MyView: View {
@EnvironmentObject var loc: DistanceObservable
var body: some View {
Text("\(loc.distance)")
}
}
我已经通过开始新的 HealthKit 锻炼解决了这个问题。
import HealthKit
- 符合
ObservableObject
及其方法
class SwiftUILocation: NSObject, CLLocationManagerDelegate, ObservableObject, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
print("A")
}
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
print("B")
}
func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
print("C")
}
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
print("D")
}
//.. rest of the code
}
- 在锻炼开始时启动 HealthKit
func startHealtKit(){
let configuration = HKWorkoutConfiguration()
configuration.activityType = .running
configuration.locationType = .outdoor
do {
self.workoutSession = try HKWorkoutSession(healthStore: healthStore,
configuration:configuration)
self.builder = self.workoutSession?.associatedWorkoutBuilder()
self.builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore,
workoutConfiguration: configuration)
self.workoutSession?.delegate = self
self.builder?.delegate = self
self.workoutSession?.startActivity(with: Date())
self.builder?.beginCollection(withStart: Date()) { (success, error) in
// Indicate that the session has started.
}
}
catch {
print("HealthKit problem \(error.localizedDescription)")
}
}
- 在锻炼结束时停止 HealtkKit
func stopHealthKit(){
self.builder?.workoutSession?.stopActivity(with: Date())
self.builder?.endCollection(withEnd: Date()) { (success, error) in
// Indicate that the session has started.
}
}
我正在为 watchOS 在 SwiftUI 中开发一个 运行ning 应用程序。问题是,当我启动 运行 时,测量工作正常 0.55 0.56 0.57
公里等。然后它随机冻结,并从 0.57
直接跳到 0.71
。甚至总距离有时也不准确。当我查看运行的地图时,有时会看到尖角和曲线中的直线,这意味着测量非常不准确。 OS 是 watchOS 8.0。我已经尝试 kCLLocationAccuracyBest
没有用。
我在名为 DistanceObservable
的 ObservableObject 中使用了 CLLocationManager
,并且我在 iOS 应用程序中有这个精确的代码可以完美地测量距离。
... @Published var distance: Double = 0.0
func startUpdate() {
self.manager = CLLocationManager()
self.manager?.delegate = self
self.manager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.manager?.requestWhenInUseAuthorization()
self.manager?.distanceFilter = 10.0
self.manager?.allowsBackgroundLocationUpdates = true
self.manager?.startUpdatingLocation()
}
这是我的watchOS
didUpdateLocations
方法。
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var locations = locations
for newLocation in locations {
let howRecent = newLocation.timestamp.timeIntervalSinceNow
guard newLocation.horizontalAccuracy < 20 && abs(howRecent) < 10 else { continue }
if let lastLocation = locationList.last {
let delta = newLocation.distance(from: lastLocation)
if (delta < 60) { // To prevent inaccurate "jumps" in distance
distance = distance + delta
if UserDefaults.standard.value(forKey: "hasSet") as!Bool == false {
distance = 0
locations.removeAll()
UserDefaults.standard.setValue(true, forKey: "hasSet")
}
latPoints.append(Double(locationList.last!.coordinate.latitude))
lonPoints.append(Double(locationList.last!.coordinate.longitude))
}
}
locationList.append(newLocation)
}
}
最后我在 SwiftUI 视图中使用 @EnvironmentObject
。
struct MyView: View {
@EnvironmentObject var loc: DistanceObservable
var body: some View {
Text("\(loc.distance)")
}
}
我已经通过开始新的 HealthKit 锻炼解决了这个问题。
import HealthKit
- 符合
ObservableObject
及其方法
class SwiftUILocation: NSObject, CLLocationManagerDelegate, ObservableObject, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
print("A")
}
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
print("B")
}
func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
print("C")
}
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
print("D")
}
//.. rest of the code
}
- 在锻炼开始时启动 HealthKit
func startHealtKit(){
let configuration = HKWorkoutConfiguration()
configuration.activityType = .running
configuration.locationType = .outdoor
do {
self.workoutSession = try HKWorkoutSession(healthStore: healthStore,
configuration:configuration)
self.builder = self.workoutSession?.associatedWorkoutBuilder()
self.builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore,
workoutConfiguration: configuration)
self.workoutSession?.delegate = self
self.builder?.delegate = self
self.workoutSession?.startActivity(with: Date())
self.builder?.beginCollection(withStart: Date()) { (success, error) in
// Indicate that the session has started.
}
}
catch {
print("HealthKit problem \(error.localizedDescription)")
}
}
- 在锻炼结束时停止 HealtkKit
func stopHealthKit(){
self.builder?.workoutSession?.stopActivity(with: Date())
self.builder?.endCollection(withEnd: Date()) { (success, error) in
// Indicate that the session has started.
}
}