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

时间:2017-06-05 12:38:31

标签: ios swift swift3 geolocation

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

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

我找到了

startMonitoringSignificantLocationChanges

我可以执行以开始提供位置更新,但这会引发一些问题。一旦我调用此应用程序并且我的应用程序未运行,是否仍在发送更新?应用程序如何醒来回应?

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

如何解决这个问题还有点困惑,这里简要说明了我要做的事情。

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

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

1 个答案:

答案 0 :(得分:12)

它可能是也可能不是一个好的解决方案,但如果我是你,我会同时使用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 enter image description here

另外,请务必使用密钥

来询问locationManager?.requestAlwaysAuthorization()
<key>NSLocationAlwaysUsageDescription</key>
    <string>Allow location</string>
Info.plist

中的

同时采用 2 LocationManagers 可以有第三种解决方案。

  1. 对于区域
  2. 重大位置变更
  3. 使用significantLocationChanges

      

    只要设备移动500米,应用就会收到通知   或者更多来自之前的通知。不应该期待   通知频率高于每五分钟一次。如果   设备能够从网络中检索位置管理器的数据   更有可能及时发送通知。

    根据给定Apple Doc

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

    另请注意,始终要准确设置一个区域。

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