我正在开发一个iOS应用程序,用户可以将行进路线保存到服务器(通过API发布位置)。我正在努力解决的问题是,有几位用户报告说他们保存的路线在旅途中途中断。详细地说,当用户在地图上查看其保存的路线时,路线的一部分只是一条直线,这是因为该路线部分的某个位置没有以某种方式发送到服务器,或者仅仅是因为该设备当时无法接收位置。 奇怪的是,其余路线均正常记录,因此位置服务似乎停止了一段时间,但之后又重新启动,因此我的应用程序可以很好地记录它。
最令人沮丧的是,我无法重现此问题。
以下是用户报告的问题的情况:
-用户启动了该应用程序,然后锁定了设备屏幕并将其放在口袋里,他们在整个旅程中都没有触摸它。没有电池耗尽或崩溃发生。
-行驶了大约8-9公里,并且一切正常后,在接下来的65公里左右中断了路线记录,然后在其余的80公里左右再次进行了很好的记录。
以下是我的项目设置:
-具有位置更新功能的“打开”中的背景模式。
-从位置服务接收的位置会根据时间戳和准确性进行过滤,如果位置成功发送到服务器,则会使用“ isSent”标记将其保存到核心数据中。这样,我的应用程序可以覆盖网络连接中断的情况。
-标有错误“ isSent”标志的位置将每30秒发送到服务器一次。
我的LocationManager代码:
class LocationManager: NSObject, CLLocationManagerDelegate {
var locationManager: CLLocationManager = {
var _locationManager = CLLocationManager()
_locationManager.delegate = self
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
_locationManager.activityType = .automotiveNavigation
_locationManager.allowsBackgroundLocationUpdates = true
_locationManager.pausesLocationUpdatesAutomatically = false
return _locationManager
}()
func startLocationService() {
locationManager.startUpdatingLocation()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var positionsToSavedToDb: [DbPositionModel] = []
for location in locations {
let howRecent = location.timestamp.timeIntervalSinceNow
guard abs(location.timestamp.timeIntervalSinceNow) < 10 && location.horizontalAccuracy > 0 && location.horizontalAccuracy < 33 else {
continue
}
if self.locations.count > 0 {
let distanceSinceLastLocation = location.distance(from: self.locations.last!)
let timeSinceLastLocation = location.timestamp.timeIntervalSince(self.locations.last!.timestamp)
if (distanceSinceLastLocation < 5 && abs(timeSinceLastLocation) < 10) {
continue
}
}
// Create DbPositionModel from location and append to positionsToSavedToDb
}
// Save positionsToSavedToDb to core data
}
@objc func each30Seconds(_ timer: Timer) {
// Select in database DbPositionModel objects with false “isSent” flag to send to server
}
}
你们可以帮助我找出代码中的黑洞,或者我可以做些什么来重现/解决此问题?非常感谢!!!
答案 0 :(得分:1)
您的设置对我来说很好。只是一个问题。当您说它不在60公里处工作然后又开始在80公里处工作时,是不是一直在后台?我的意思是用户不需要输入前台即可重新开始工作,对吗?
您对location.horizontalAccuracy
的限制为33。您认为这将是非常准确的。我不确定,也许设备/城市组合不好,然后您要早点回来。我建议您记录为什么要早退的原因。他们的城市可能与您的城市不同。另外,我还听说过iPhoneX的GPS尽管位置正确,但其horizontalAccuracy
返回的数字却很大。这主要是针对iPhoneX用户吗?
enum LocationAccuracyError: Error {
case stale(secondsOld: Double)
case invalid
case lowAccuracy(metersOff: Double)
}
extension LocationAccuracyError: LocalizedError{
var errorDescription: String? {
switch self {
case .stale(let seconds):
return NSLocalizedString("location was stale by: \(seconds) seconds", comment: "")
case .invalid:
return NSLocalizedString("location was invalid)", comment: "")
case .lowAccuracy(let metersOff):
return NSLocalizedString("location's horizontal Accuracy was off by likely more than: \(metersOff) meters" , comment: "")
}
}
}
然后具有类似这样的功能来检查每个位置。
private func checkLocationAccuracy(from location: CLLocation) throws {
let ageOfLocation = -location.timestamp.timeIntervalSinceNow
if ageOfLocation >= maximumAcceptedStale {
throw LocationAccuracyError.stale(secondsOld: ageOfLocation)
}
if location.horizontalAccuracy <= 0 {
throw LocationAccuracyError.invalid
}
if location.horizontalAccuracy > MaximumAcceptedHorizontalAccuracy{
throw LocationAccuracyError.lowAccuracy(metersOff: location.horizontalAccuracy)
}
}
您的最终用途将是:
do {
try checkLocationAccuracy(from: location)
} catch let error {
writelog("Bad Location: \(error.localizedDescription)")
}
我还将在您的应用状态周围添加日志,例如添加日志以捕获didEnterBackground