即使应用程序未在 Swift 中运行,也能接收位置信息 [英] Receiving Location even when app is not running in Swift

查看:16
本文介绍了即使应用程序未在 Swift 中运行,也能接收位置信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对 Swift 来说还是很新的.我来自 Android 背景,其中有 BroadcastReceiver,即使应用未运行,它也可以向服务提供位置信息.

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

我找到了

startMonitoringSignificantLocationChanges

我可以执行它以开始提供位置更新,尽管这会引发一些问题.一旦我调用它并且我的应用程序没有运行,是否仍在发送更新?应用如何唤醒以响应?

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

仍然有点困惑如何解决这个问题,这里是我正在尝试做的事情的简要说明.

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

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

解决方案

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

还要确保使用密钥

请求 locationManager?.requestAlwaysAuthorization()

NSLocationAlwaysUsageDescription<string>允许位置</string>

在您的Info.plist

可以通过同时使用 2 个 LocationManager 来获得第三种解决方案.

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

使用重要位置变化

<块引用>

应用可以在设备移动 500 米后立即收到通知或更多来自其先前的通知.它不应该期待通知频率高于每五分钟一次.如果设备能够从网络中检索数据,位置管理器更有可能及时发送通知.

根据给定 Apple Doc

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

还要记住始终以良好的精度设置区域.

我知道这不会完全解决您的问题,但您会根据自己的要求获得前进的想法.

Still very new to Swift. I have come from an Android background where there is BroadcastReceiver that can deliver location info to a service even though the app isn't running.

So I was looking for something similar in iOS/Swift and it appears that before this wasn't possible but it may be now. I am developing for iOS 10 but would be great if it was backwards compatible.

I found

startMonitoringSignificantLocationChanges

which I can execute to start delivering location updates, although this raises a few questions. Once I call this and my app is NOT running, are the updates still being sent ? And how would the app wake up to respond ?

Also restarting the phone and when it return, does this mean I still need call startMonitoringSignificantLocationChanges again meaning that I would have to wait for the user to execute my app. Or does it remember the setting after reboot ?

Still a little confused how to get around this, here's a brief explanation of what I am trying to do.

I would like to update the location of the phone even though the app is not running, this would be sent to a rest service every so often.

This way on the backend services I could determine if somebody is within X meters of somebody also and send them a push notification.

解决方案

It may or may not be a good solution but if I were you I would have used both startMonitoringSignificantLocationChanges and regionMonitoring.

Here is the sample I made which worked well with iOS 13.

Lets take regionMonitoring first. We have certainly no problems when the app is in foreground state and we can use the CLLocationManager's didUpdate delegate to get the location and send it to the server.

Keep latest current location in AppDelegate's property, lets say:

var lastLocation:CLLocation?

//And a location manager
var locationManager = CLLocationManager()

We have two UIApplicationDelegates

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

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

So whenever the user kills the app or makes the app go to background, we can certainly create a region around the latest current location fetched. Here is an example to 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")
        }
    }

Make use of 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()
}

Grab the location from didUpdate method

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)
    }
}

Here I have made a 50m region radius circle. I have tested this and it is called generally after crossing 100m from your center point.

Now the second approach can me using significantLocationChanges

On making the app go background or terminated, we can just stop location manager for further updating locations and can call the startMonitoringSignificantLocationChanges

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

When the app is killed, the location is grabbed from didFinishLaunching method's launchOptions?[UIApplicationLaunchOptionsKey.location]

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

Make sure to keep BackgroundModes On for Location Updates

Also make sure to ask for locationManager?.requestAlwaysAuthorization() by using the key

<key>NSLocationAlwaysUsageDescription</key>
    <string>Allow location</string>

in your Info.plist

There can be a third solution by taking 2 LocationManagers simultaneously.

  1. For region
  2. Significant Location Changes

As using significantLocationChanges

Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.

as per the give Apple Doc

So it totally depends on your requirements as the location fetching depends on many factors like the number of apps opened, battery power, signal strength etc when the app is not running.

Also keep in mind to always setup a region with good accuracy.

I know that this will not solve your problem completely but you will get an idea to move forward as per your requirements.

这篇关于即使应用程序未在 Swift 中运行,也能接收位置信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆