无法在后台使用应用程序保持 GPS 活动,或在前台或后台使用应用程序读取位置

Cannot keep GPS active with app in background, or read location with app in foreground or background

与此问题相关的应用旨在以高精度跟踪用户位置,包括 GPS 坐标和加速度计读数,持续 30 分钟,即使用户按下了睡眠按钮也是如此。

为此,plist 文件和应用功能设置已更改,以反映导航访问始终在线的原因,并启用后台进程以提供基于位置的服务。

应用程序在 运行 时确实会向用户询问 GPS 权限,如果被授予,则此视图控制器(包含以下代码的视图控制器)的激活确实会导致 GPS/Navigation 图标显示在 iPhone 上。

问题是,到目前为止,下面看到的四个 "print" 命令中的 none 会导致任何打印消息,因此 "newLocation" 和 "myLocation" 变量都会不产生任何数据。如果此代码与第一句中概述的目的相去甚远,那么问题是 "How can it be fixed?"。如果这是实现目标的糟糕方法,那么更好的答案将解释应该如何完成。

import UIKit
import CoreMotion
import MapKit
import CoreLocation

class ActiveSession: UIViewController, CLLocationManagerDelegate {
        lazy var locationManager: CLLocationManager! = {
        let manager = CLLocationManager()
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.delegate = self
        return manager
    }()

    func locationManager(_manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
        let myLocation:CLLocationCoordinate2D=CLLocationCoordinate2DMake(oldLocation.coordinate.latitude, oldLocation.coordinate.longitude)
        print(myLocation)

        if UIApplication.shared.applicationState == .active {
            print("at least it's active at all")
        } else {
            print(newLocation)
            print("it's active when the app isn't")
        }
    }

     func getPermission () {
        locationManager = CLLocationManager()

        switch CLLocationManager.authorizationStatus() {
        case .denied, .restricted:
            return
        case .notDetermined:
            locationManager!.requestAlwaysAuthorization()
            break
        case .authorizedAlways, .authorizedWhenInUse:
            break
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.getPermission()
        locationManager = CLLocationManager()
        locationManager!.desiredAccuracy = kCLLocationAccuracyBest
        locationManager?.startUpdatingLocation()
    }
}

你在三个地方创建了新的 CLLocationManager 实例——懒惰的 locationManager 初始化器、getPermissionviewDidLoad——在后两个地方,你既不是设置所需的准确性或代表。删除 locationManager = CLLocationManager() 行,你应该会有更好的结果。

正如 ohr 所指出的,需要额外的许可。将以下行添加到惰性 locationManager 初始值设定项以纠正此遗漏:

manager.allowsBackgroundLocationUpdates = true

按照Noah和Paulw11的建议,删除了getPermission函数,一行:

locationManager = CLLocationManager()

已从 viewDidLoad 中删除,因为存在大量冗余。这本身并没有解决问题,但向 locationManager 函数添加了逻辑,以便将最近的地图数据存储到一个数组中,如下所示:

let annotation = MKPointAnnotation()
annotation.coordinate = newLocation.coordinate    
locations.append(annotation)
while locations.count > 100 {
    let annotationToRemove = locations.first!
    locations.remove(at: 0)
}

产生了工作代码。此解决方案源自此处的代码:https://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial (谢谢,雷)

最终代码在前台和后台运行,无需从 class 中删除任何内容或在 appdelegate 中实现任何内容。