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()
}
}
如果我在我的应用程序后台调用 .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()
}
}