【问题标题】:How to get periodicaly new location when app is in background or killed当应用程序处于后台或被杀死时如何定期获取新位置
【发布时间】:2017-05-22 08:25:10
【问题描述】:

当我的应用程序处于后台或被终止时,我希望每 1 分钟获取一次新位置。 这是我的代码:

定位服务:

class LocationService: NSObject, CLLocationManagerDelegate {

    static let shared = LocationService()
    var locationManager = CLLocationManager()
    var significatLocationManager = CLLocationManager()
    var currentLocation: CLLocation!
    var timer = Timer()
    var bgTask = UIBackgroundTaskInvalid

    func startUpdatingLocation() {
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLDistanceFilterNone
        if #available(iOS 9.0, *) {
            locationManager.allowsBackgroundLocationUpdates = true
        }
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }

    func stopUpdatingLocation() {
        locationManager.stopUpdatingLocation()
        timer.invalidate()
    }

    func restartUpdatingLocation() {
        locationManager.stopMonitoringSignificantLocationChanges()
        timer.invalidate()
        startUpdatingLocation()
    }

    func startMonitoringLocation() {
        locationManager.stopUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges()
        timer.invalidate()
    }

    func changeLocationAccuracy(){
        switch locationManager.desiredAccuracy {
        case kCLLocationAccuracyBest:
            locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
            locationManager.distanceFilter = 99999
        case kCLLocationAccuracyThreeKilometers:
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.distanceFilter = kCLDistanceFilterNone
        default: break
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        bgTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
            UIApplication.shared.endBackgroundTask(self.bgTask)
            self.bgTask = UIBackgroundTaskInvalid
        })

        currentLocation = locations.last!

        let interval = currentLocation.timestamp.timeIntervalSinceNow
        let accuracy = self.locationManager.desiredAccuracy

        if abs(interval) < 60 && accuracy != kCLLocationAccuracyThreeKilometers {        
            timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(LocationService.changeLocationAccuracy), userInfo: nil, repeats: false)
            changeLocationAccuracy()
        }
    } 
}

应用委托:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
     if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
          LocationService.shared.restartUpdatingLocation()
     }
}

func applicationDidEnterBackground(_ application: UIApplication) {
     LocationService.shared.restartUpdatingLocation()
}

func applicationWillTerminate(_ application: UIApplication) {
     LocationService.shared.startMonitoringLocation()
}

视图控制器:

override func viewDidLoad() {
    LocationService.shared.startUpdatingLocation()
}

但是我的代码不起作用,当我的应用程序在后台运行几分钟后,我没有得到新的位置。当我的应用程序被暂停或终止时也是如此。 有什么解决办法吗?请不要说我使用的是 Swift 3 和 xcode 8.1。

提前致谢

【问题讨论】:

  • 你必须走很远才能获得重要的位置变化。至少 >500 米。
  • 这是我的应用程序被杀死的时候。但是我如何才能每 1 分钟在后台无限期地更新位置?
  • 你不能。你可以尝试滥用backgroundFetch

标签: ios swift3 xcode8 cllocation


【解决方案1】:
  • 如果您在应用程序已经在后台运行时调用startUpdatingLocation,那么您只会在几分钟内收到位置更新。

  • 如果您在应用程序处于前台时调用 startUpdatingLocation,然后您的应用程序移至后台,您将继续无限期地接收位置更新。

  • 如果您在前台调用startMonitoringSignificantLocationChanges并使其保持启用状态,那么您可以在后台调用startUpdatingLocation 并无限期地接收更新。

  • 如果用户终止了您的应用程序(通过在应用程序切换器中向上滑动),那么在用户重新启动您的应用程序之前,您将不会再收到位置更新。

由于您的代码在移动到仅获取位置更新几分钟的后台时会停止并开始位置监控。如果您在应用程序移动到后台时启动位置监控前台并且什么都不做,那么您将继续接收位置更新。

【讨论】:

  • 你能告诉我我应该在上面的代码中改变什么吗?
  • 您需要添加对startMonitoringSignificantLocationChanges 的调用,您可以在其中创建位置管理器,并确保从前台调用它。您也可以从applicationWillTerminate 中删除代码,因为这没有任何作用。
  • 但重要位置仅在设备移动超过 500m 时才提供新位置。我不希望我每 1 分钟需要一次位置
  • 你不能每分钟都得到它,当位置改变时你会得到更新,如果设备正在移动,这可能比每分钟快,如果设备静止,则不到一分钟。然而,诀窍是,如果在前台启用了重要的位置监控并保持启用状态,那么您可以在没有时间限制的情况下从后台启动/停止更准确的位置监控。您也可以简单地在前台启动准确的位置监控并让它继续运行,但它会消耗更多电池。你的问题是当你移动到后台时重新启动监控
  • 您已经有了正确的代码。只是不要在后台调用stopUpdatingLocation
猜你喜欢
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-10
  • 2022-08-19
相关资源
最近更新 更多