我对swift相对较新,我正在尝试为我的应用添加一项功能,该功能会跟踪在有限的时间内行进的距离。
然而,当我运行应用程序时,即使手机收到的纬度和经度准确,我也遇到了多个问题: 1.应用程序仅记录位置变化几秒钟 即使设备静止,该应用程序也会录制剧烈的动作。
感谢任何和所有帮助。这是我的代码:
import UIKit
import CoreLocation
import FirebaseAuth
import FirebaseDatabase
class MWTCountdownViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var metersLabel: UILabel!
@IBOutlet weak var ConfirmTrialButton: UIButton!
var zeroTime = TimeInterval()
var timer : Timer = Timer()
var ref: DatabaseReference?
let locationManager = CLLocationManager()
var startLocation: CLLocation!
var lastLocation: CLLocation!
var distanceTraveled: Double = 0.0
override func viewDidLoad() {
super.viewDidLoad()
ConfirmTrialButton.isHidden = true
ConfirmTrialButton.isEnabled = false
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
distanceTraveled = 0.0
startLocation = nil
lastLocation = nil
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
locationManager.distanceFilter = 10
} else {
print("Need to Enable Location")
}
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(MWTCountdownViewController.updateTime), userInfo: nil, repeats: true)
zeroTime = Date.timeIntervalSinceReferenceDate
ref = Database.database().reference()
}
func updateTime() {
let currentTime = Date.timeIntervalSinceReferenceDate
var timePassed: TimeInterval = currentTime - zeroTime
let minutes = UInt8(timePassed / 60.0)
timePassed -= (TimeInterval(minutes) * 60)
let seconds = UInt8(timePassed)
timePassed -= TimeInterval(seconds)
let millisecsX10 = UInt8(timePassed * 100)
let strMinutes = String(format: "%02d", minutes)
let strSeconds = String(format: "%02d", seconds)
let strMSX10 = String(format: "%02d", millisecsX10)
timerLabel.text = "\(strMinutes):\(strSeconds):\(strMSX10)"
if timerLabel.text == "06:00:00" {
timer.invalidate()
locationManager.stopUpdatingLocation()
ConfirmTrialButton.isHidden = false
ConfirmTrialButton.isEnabled = true
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if startLocation == nil {
startLocation = locations.first as CLLocation!
} else if let location = locations.last {
let lastDistance = lastLocation.distance(from: location)
distanceTraveled += lastDistance
let trimmedDistance = String(format: "%.2f", distanceTraveled)
metersLabel.text = "\(trimmedDistance) m"
}
lastLocation = locations.last as CLLocation!
}
答案 0 :(得分:1)
你目前计算行走距离的策略是高估估计距离,可能会有很大的差距。
目前,您假设您始终可以将报告到locationManager(didUpdateLocations:)
的最后位置与您的总行程距离相加。不幸的是,这不是一个安全的假设。
在startUpdatingLocation
的文档中,我们看到:
接收器主要在超出distanceFilter属性值时生成更新事件。但是,更新可能会在其他情况下提供。例如,如果硬件收集更准确的位置读数,接收器可以发送另一个通知。
设备的初始位置修复可能非常不准确。您收到的前几个位置更新可能并不表示设备的任何移动,而是指示越来越精确的测量。您至少应该考虑新位置的horizontalAccuracy
,以确定您是否可以使用您收到的数据。例如。如果你得到10米相距10米的多次测量,但都精确到100米,你真的不知道设备是否移动了。
这里值得注意的是desiredAccuracy
阻止了不准确位置的传递,它只是指明设备应该有多难以获得越来越准确的位置。
在请求高精度位置数据时,位置服务提供的初始事件可能没有您请求的准确性。定位服务尽快提供初始事件。然后,它会继续以您请求的准确度确定位置,并在数据可用时根据需要提供其他事件。
即使在最高精度下,CLLocation数据也会包含相当多的抖动。即使设备保持静止,计算每个报告位置之间的距离也会显示很多运动。相反,您可能希望收集所有报告的位置,并使用某种平滑或曲线拟合来估计实际的行进路径。
您想在这里使用的策略究竟取决于您可以对设备移动做出哪些假设。导航应用程序通常会将估计位置固定到已知道路。运行应用程序需要处理相当紧密的循环,以便它们可以跟踪在60米宽的轨道上运行。一个速降滑雪应用程序可能需要处理大量的横向移动,但能够在跑步过程中假设没有明显的上坡回溯。