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

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

问题描述

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



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



我发现

  startMonitoringSignificantLocationChanges 

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



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



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



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



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

解决方案

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



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



在AppDelegate的财产中保留最新的当前位置,假设:

  var lastLocation:CLLocation? 

//和位置经理
var locationManager = CLLocationManager()

我们有两个 UIApplicationDelegates

  func applicationDidEnterBackground(_ application: UIApplication){
//创建一个区域
}

func applicationWillTerminate(_ application:UIApplication){
//创建一个区域
}

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

  func createRegion(location:CLLocation?){

如果CLLocationManager.isMonitoringAvailable(for:CLCircularRegion.self){
let coordinate = CLLocationCoordinate2DMake((location?.coordinate.latitude)!,(location?.coordinate.longitude)!)
let regionRadius = 50.0

let region = CLCircularRegion(中心:CLLocationCoordinate2D(
纬度:coordinate.latitude,
经度:coordinate.longitude),
半径:regionRadius,
标识符:aabb)

region.notifyOnExit = true
region.notifyOnEntry = true

//将您获取的位置发送到服务器

//停止您的位置管理器以更新位置并启动regionMonitoring
self.locationManager?.stopUpda tingLocation()
self.locationManager?.startMonitoring(for:region)
}
else {
print(系统无法跟踪区域)
}
}

利用RegionDelegates

  func locationManager(_ manager:CLLocationManager,didEnterRegion region:CLRegion){
print(输入区域)
}

func locationManager(_ manager:CLLocationManager,didExitRegion region:CLRegion){
print(Exited Region)

locationManager?.stopMonitoring(for:region)

/ /启动位置管理器并获取当前位置
locationManager?.startUpdatingLocation()
}

抓取位置didUpdate 方法

  func locationManager(_ manager :CLLocationManager,didUpdateLocations位置:[CLLocation]){

如果UIApplication.shared.applicationState == .act ive {
} else {
//应用程序处于BG / Killed或暂停状态
//将位置发送到服务器
//创建一个具有当前获取位置的新区域
let location = locations.last
lastLocation = location

//创建区域并再次继续相同的循环。
self.createRegion(location:lastLocation)
}
}

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



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



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

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

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

  if launchOptions ?[UIApplicationLaunchOptionsKey.location]!= nil {
//当应用程序处于被杀/未运行状态时你有一个位置
}

确保为 BackgroundModes g>位置更新



同时确保要求 locationManager?.requestAlwaysAuthorization()使用密钥

 < key> NSLocationAlwaysUsageDescription< / key> 
< string>允许位置< / string> Info.plist


$

b $ b

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


  1. 对于区域< br>

  2. 重大位置变更

使用 significantLocationChanges


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


根据 Apple Doc



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

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



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


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.

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天全站免登陆