Swift: 在应用程序处于后台时调用 .requestLocation()

Swift: Calling .requestLocation() while app is in background

如果我在我的应用程序后台调用 .requestLocation(),则永远不会调用 locationManager didUpateLocations 方法。它在应用程序打开时起作用。我设置了 .allowsBackgroundLocationUpdates = true 并且测试 phone 选择了 .authorizedAlways 作为授权状态。 requestLocation 后台不工作吗?

为了澄清,我在 didReceiveRemoteNotification 委托方法中调用它。每次我向设备发送远程推送通知时,如果应用程序在后台,我希望调用 .requestLocation()。这不可能吗?

didReceiveRemoteNotification:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    if CLLocationManager.authorizationStatus() == .authorizedAlways {
        locationManager.requestLocation()
    }

    completionHandler(UIBackgroundFetchResult.newData)
}

您的问题是 requestLocation 将异步完成;确定用户位置并调用 didUpdateLocations 委托方法可能需要一些时间。

调用 completionHandler 告诉 iOS 您已完成后台处理。当您在 requestLocation iOS 调用位置委托之前暂停您的应用程序后立即执行此操作时。

您可以使用 DispatchGroup 来确定位置何时被检索并且您准备好被暂停:

class AppDelegate: UIApplicationDelegate, CLLocationManagerDelegate {
    var backgroundDispatchGroup: DispatchGroup?


    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

        if CLLocationManager.authorizationStatus() == .authorizedAlways {

            self.backgroundDispatchGroup = DispatchGroup()
            self.backgroundDispatchGroup?.enter()
            locationManager.requestLocation()

            self.backgroundDispatchGroup?.notify {
                completionHandler(UIBackgroundFetchResult.newData)
                self.backgroundDispatchGroup = nil
            }

         } else {
             completionHandler(UIBackgroundFetchResult.noData)
         }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // Do whatever with the location

        self.backgroundDispatchGroup?.leave()
    }
}