即使应用程序未在Swift中运行,也会接收位置

对Swift来说还是一个新手。 我来自Android背景,其中有BroadcastReceiver,即使应用程序未运行,也可以向服务提供位置信息。

所以我在iOS / Swift中寻找类似的东西,看起来在此之前不可能,但现在可能。 我正在为iOS 10开发,但如果它是向后兼容的话会很棒。

我发现

startMonitoringSignificantLocationChanges 

我可以执行以开始提供位置更新,虽然这提出了一些问题。 一旦我打电话给我并且我的应用程序没有运行,更新是否仍在发送? 应用程序如何醒来响应?

还重新启动手机,当它返回时,这是否意味着我仍然需要再次调用startMonitoringSignificantLocationChanges,这意味着我将不得不等待用户执行我的应用程序。 或者它是否记得重启后的设置?

还有点困惑如何解决这个问题,这里是对我要做的事情的简要解释。

我想更新手机的位置,即使应用程序没有运行,这也会经常发送到rest服务。

这种方式在后端服务上我可以确定某人是否在某人的X米范围内并向他们发送推送通知。

它可能是也可能不是一个好的解决方案,但如果我是你,我会使用startMonitoringSignificantLocationChangesregionMonitoring

让我们先regionMonitoring 。 当应用程序处于前台状态时,我们当然没有问题,我们可以使用CLLocationManager的 didUpdate委托来获取位置并将其发送到服务器。

保留AppDelegate属性中的最新当前位置,让我们说:

 var lastLocation:CLLocation? //And a location manager var locationManager = CLLocationManager() 

我们有两个UIApplicationDelegates

 func applicationDidEnterBackground(_ application: UIApplication) { //Create a region } func applicationWillTerminate(_ application: UIApplication) { //Create a region } 

因此,每当用户杀死应用程序或使应用程序转到后台时,我们当然可以在获取的最新当前位置周围创建一个区域。 以下是创建区域的示例。

 func createRegion(location:CLLocation?) { if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) { let coordinate = CLLocationCoordinate2DMake((location?.coordinate.latitude)!, (location?.coordinate.longitude)!) let regionRadius = 50.0 let region = CLCircularRegion(center: CLLocationCoordinate2D( latitude: coordinate.latitude, longitude: coordinate.longitude), radius: regionRadius, identifier: "aabb") region.notifyOnExit = true region.notifyOnEntry = true //Send your fetched location to server //Stop your location manager for updating location and start regionMonitoring self.locationManager?.stopUpdatingLocation() self.locationManager?.startMonitoring(for: region) } else { print("System can't track regions") } } 

使用RegionDelegates

 func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) { print("Entered Region") } func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) { print("Exited Region") locationManager?.stopMonitoring(for: region) //Start location manager and fetch current location locationManager?.startUpdatingLocation() } 

didUpdate方法中获取位置

 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if UIApplication.shared.applicationState == .active { } else { //App is in BG/ Killed or suspended state //send location to server // create a New Region with current fetched location let location = locations.last lastLocation = location //Make region and again the same cycle continues. self.createRegion(location: lastLocation) } } 

在这里,我制作了一个50米的区域半径圆。 我测试了这个,一般在从你的中心点穿过100米后调用它。

现在第二种方法可以使用significantLocationChanges

在使应用程序进入后台或终止时,我们可以停止位置管理器以进一步更新位置,并可以调用startMonitoringSignificantLocationChanges

 self.locationManager?.stopUpdatingLocation() self.locationManager?.startMonitoringSignificantLocationChanges() 

当应用程序被杀死时,该位置是从didFinishLaunching方法的launchOptions?[UIApplicationLaunchOptionsKey.location]

 if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil { //You have a location when app is in killed/ not running state } 

确保为位置更新保留BackgroundModes 在此处输入图像描述

还要确保使用密钥请求locationManager?.requestAlwaysAuthorization()

 NSLocationAlwaysUsageDescription Allow location 

在您的Info.plist中

通过同时使用2个LocationManage可以有第三种解决方案。

  1. 对于地区
  2. 重要的位置变化

使用significantLocationChanges

只要设备从之前的通知移动500米或更长时间,应用就会收到通知。 它不应该比每五分钟更频繁地预期通知。 如果设备能够从网络检索数据,则位置管理器更有可能及时发送通知。

按照Apple Doc的说法

因此,它完全取决于您的要求,因为位置提取取决于许多因素,例如应用程序未运行时打开的应用程序数量,电池电量,信号强度等。

另外请记住始终设置一个准确度高的区域。

我知道这不会完全解决您的问题,但您会根据自己的要求提出建议。