CLLocationManager在后台时不更新,并获得混乱的位置坐标Swift

时间:2018-08-24 14:08:02

标签: ios swift core-location

我具有跟踪功能,但是在后台时它不会更新位置。

第一种情况:在应用程序处于前台时进行跟踪->跟踪实际上正在进行中,但无法获得精确的坐标。我将更改为locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation,以查看是否可以提高跟踪的准确性。

第二种情况:屏幕关闭时进行跟踪->跟踪是从a到b的直线,跟踪不会更新坐标。

第3种情况:在应用程序处于后台(按下主页按钮)时进行跟踪->与情况1一样发生跟踪。

我找到了一篇帖子,说明如果将授权设置为始终,则必须指定要在后台继续更新位置,但没有任何更改。这是代码和info.plist:

override func viewDidLoad() {
        super.viewDidLoad()


        mapView.delegate = self
        locationManager.delegate = self
//        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
//        locationManager.allowsBackgroundLocationUpdates = true  //for getting user location in background mode as well

        mapView.showsUserLocation = true
        mapView.userTrackingMode = .follow   //map following user                    

        configureLocationServices()
        addDoubleTap() // enabling duble tap gesture recognizer
//        mapView.isUserInteractionEnabled = true

        let location = locationManager.location?.coordinate
        let region = MKCoordinateRegionMakeWithDistance(location!, 1000, 1000) // set mapView based on user location coordinates
        mapView.setRegion(region, animated: true)
        centerMapOnLocation()

        // alerts coordinates to post to Firebase
        let alertDrawLatitude =  alertDrawCoordinates?.latitude  // not used ?
        let alertDrawLomgitude = alertDrawCoordinates?.longitude
        let title: String? = alertNotificationType
        var subtitle: String? = alertNotificationType

        //  user alert notification. takes coordinates from alertNotificationArray( populated with firebase returning coordinate for all alerts

         displayAlerts()
    }            

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let mostRecentLocation = locations.last else { return }        
        self.actualRouteInUseCoordinatesArray.append(mostRecentLocation.coordinate)

    }            

    func configureLocationServices() {
            if authorizationStatus == .notDetermined{
                locationManager.requestAlwaysAuthorization()
            } else if authorizationStatus == .authorizedAlways {
            locationManager.showsBackgroundLocationIndicator = true //set update location even if in background. very imposrtant!!
          }
        }

info.plist

更新:

改变精度只会使情况变得更糟。

具有AccuracyBest: accuracy best

并带有AccuracyBestForNAvigation

accuracy best for navigation

第二次跟踪实际上更糟。.导航应用程序如何依靠这种跟踪?我的LocationManager代码有什么问题吗?

第二次更新: 现在,它在后台时会获得更新的位置,但距离还很远。。我从未经过黄色的街道,它显示出在它醒来10分钟后的感觉。

第三次编辑:

我发现我应该过滤掉GPS原始数据,所以我使用的是卡尔曼过滤器,它确实可以平滑最终的跟踪。 因此,我微调了两个参数,为了能够更改这些参数,我添加了两个文本字段@IBOutlet weak var filterValueTextField: UITextField!@IBOutlet weak var horizontalAccuracyTextField: UITextField!并将它们连接到参数

hcKalmanFilter?.rValue = Double(String( describing:filterValueTextField?.text!))!guard mostRecentLocation.horizontalAccuracy < Double(String( describing: horizontalAccuracyTextField?.text!))! else { return }。 我的问题是,当在horizo​​ntalAccuracy参数中解包值时,它会找到nil。 如果在horizo​​ntalAccuracy中,我只是放置了一个接受整数的值,但是当我从将textfield.text转换为Int的texField中获取它时,编译器将引发错误Binary operator '<' cannot be applied to operands of type 'CLLocationAccuracy' (aka 'Double') and 'Int',而如果将其转换为Double则不会,但结果为零。 为什么filterValue从它的textField中找到一个值,而水平Accuracy却找不到?它们被声明,并且使用相同的方式。 有想法吗?

traking is way off

2 个答案:

答案 0 :(得分:0)

首先,当应用程序进入后台时,您的时间有限,该时间取决于设备操作系统的负载,但最可能的时间约为。 30秒。因此,这就是您在屏幕关闭或应用程序进入后台时无法获取位置更新的原因。

但是Apple允许应用程序在某些任务在后台运行,位置更新就是其中之一,因此即使您的应用程序进入后台,也可以通过为应用程序启用Background Fetch功能来获取位置更新。

有关更多详细信息,请遵循以下官方文档。苹果的:

https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background

其次,尝试在应用程序的全局范围内维护locationmanager对象,就像您可以为应用程序维护任何对象一样,可以将其放置在AppDelegate或Singleton类中,因此它始终是可用。

答案 1 :(得分:0)

有时候,您收到的位置信息的准确性不理想,尤其是当您刚刚开始跟踪时,前几个位置信息会很不理想。您可以使用location's horizontal accuracy property来过滤位置精度例如小于50m的位置