当前位置: 首页 > 面试题库 >

即使应用未在Swift中运行,也可以接收位置

纪正德
2023-03-14
问题内容

对Swift来说还是很新的。我来自Android背景,那里有BroadcastReceiver,即使该应用未运行,它也可以将位置信息传递给服务。

所以我在iOS / Swift中寻找类似的东西,看来以前不可能,但现在可能会。我正在为iOS 10开发,但是如果它向后兼容,那就太好了。

我发现

startMonitoringSignificantLocationChanges

我可以执行此操作以开始提供位置更新,尽管这会引起一些问题。一旦我打电话给我并且我的应用程序没有运行,更新是否还在发送?该应用程序将如何唤醒以响应?

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

仍然有些困惑如何解决此问题,这是我正在尝试做的简短说明。

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

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


问题答案:

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

这是我制作的与iOS 13兼容的示例。

让我们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)
    }
}

在这里,我做了一个50m的区域半径圆。我已经对此进行了测试,通常在距您的中心点100m后才被称为。

现在我可以使用第二种方法 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()通过使用键要求

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

在您的 Info.plist中

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

  1. 对于区域

  2. 重大地点变更

作为使用 significantLocationChanges

当设备距其先前的通知500米或更多距离时,应用程序会期望收到通知。它不应期望通知的频率超过每五分钟一次。如果设备能够从网络检索数据,则位置管理器更有可能及时传递通知。

按照给苹果文档

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

另外请记住,始终以较高的精度设置区域。

我知道这不能完全解决您的问题,但是您会根据自己的要求前进。



 类似资料:
  • 问题内容: 是否可以在每次执行循环时回显?例如: 我不想看到循环结束时打印所有内容,而是希望它每次都打印每个结果。 问题答案: 最终解决方案 这就是我发现的: Flush在Apache的mod_gzip或Nginx的gzip下不起作用,因为从逻辑上讲,它正在对内容进行gzip处理,并且这样做必须缓冲内容才能对其进行gzip处理。任何类型的Web服务器gzip压缩都会影响此。简而言之,在服务器端,我

  • 问题内容: 我有一个具有2个服务的应用程序: 和 在文件中有声明。问题是,当我的应用程序进程被迫自行关闭时,服务也会被杀死。 我希望他们不要被杀死。我听说过该类的标志,但是无法覆盖这些服务中的方法以返回此标志… 问题答案: 为了回答评论,我没有找到解决问题的任何“方法”,因为这不是 问题 。如果用户想要关闭我的应用程序,则他有权。 由于我的方法属于我的应用程序,因此如果用户强行关闭该应用程序,则该

  • 问题内容: 我的一项活动遇到了一个奇怪的问题。从拍照/录像回来时,我正在显示一个对话框,允许用户命名相机。用户按下“确定”后,我将使用所请求的文件名发送给主题,该主题将复制文件(并显示进度对话框)。 由于某种原因,即使我调用,总是在主线程上调用执行复制的函数。 更改呼叫以解决问题。我还是想知道为什么它不起作用… 问题答案: 并且是那里最混乱的运营商。前者确保订阅副作用在指定的调度程序(线程)上发生

  • 问题内容: 试图让Firefox在spyder中使用硒运行。我当前的代码是 我仍然收到此错误: 即使gekodriver在该文件夹中。 证明gekodriver位置正确 我也尝试过将路径导出到〜。/ bash_profile,现在看起来像这样。 我还在spyder中设置了当前路径: gekodriver在其中 我到处都看过,大多数人说如果它位于/ usr / local / bin中,它应该自动运

  • 我想保持一个服务在后台运行,即使当我的应用程序被杀死。我使用的是事件,但服务只在屏幕解锁时运行。我尝试了,但下载应用程序后至少需要重新启动手机一次。 理想情况下,我将使用启动服务所有X分钟。然后检查条件(电池电量、网络连接……)在开始服务之前。 问题是这样的事件不能从声明和监听,而是在活动中,这意味着应用程序是“活动的”。 有办法做我想做的事吗?

  • 问题内容: 我是这里的新用户,但是我已经使用stackoverflow很多次了:)…我是android开发人员,但是现在我正在使用swift在ios应用程序中工作。我对使用xcode完全陌生,也许我的问题在很多方面都很简单…太好了,我真的需要帮助。我正在尝试实现一个背景任务,该任务每十分钟更新一次用户位置。我需要获取经纬度数据,并将此信息发送到API网络服务。我一直在介绍backgroud文档,所