对Swift来说还是很新的。我来自Android背景,那里有BroadcastReceiver,即使该应用未运行,它也可以将位置信息传递给服务。
所以我在iOS / Swift中寻找类似的东西,看来以前不可能,但现在可能会。我正在为iOS 10开发,但是如果它向后兼容,那就太好了。
我发现
startMonitoringSignificantLocationChanges
我可以执行此操作以开始提供位置更新,尽管这会引起一些问题。一旦我打电话给我并且我的应用程序没有运行,更新是否还在发送?该应用程序将如何唤醒以响应?
还要重新启动手机并在手机返回时,这是否意味着我仍然需要再次调用startMonitoringSignificantLocationChanges,这意味着我必须等待用户执行我的应用程序。还是重新启动后还记得设置?
仍然有些困惑如何解决此问题,这是我正在尝试做的简短说明。
我想更新手机的位置,即使该应用程序未运行,也会经常将其发送到休息服务。
通过这种方式,我可以在后端服务上确定某人是否也在某人的X米之内,并向他们发送推送通知。
这可能是一个好的解决方案,也可能不是,但是如果我是您,我会同时使用startMonitoringSignificantLocationChanges和regionMonitoring。
regionMonitoring
这是我制作的与iOS 13兼容的示例。
让我们regionMonitoring先。当应用程序处于前台状态时,我们当然没有问题,我们可以使用 CLLocationManager的 didUpdate委托来获取位置并将其发送到服务器。
didUpdate
在AppDelegate的属性中保留最新的当前位置,可以这样说:
var lastLocation:CLLocation? //And a location manager var locationManager = CLLocationManager()
我们有两个 UIApplicationDelegates
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
significantLocationChanges
在使应用进入后台或终止状态时,我们可以停止位置管理器以进一步更新位置,并可以致电 startMonitoringSignificantLocationChanges
self.locationManager?.stopUpdatingLocation() self.locationManager?.startMonitoringSignificantLocationChanges()
当应用被杀死时,该位置将从didFinishLaunching方法的launchOptions?[UIApplicationLaunchOptionsKey.location]
didFinishLaunching
launchOptions?[UIApplicationLaunchOptionsKey.location]
if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil { //You have a location when app is in killed/ not running state }
确保打开 BackgroundModes 以进行 位置更新
还要确保locationManager?.requestAlwaysAuthorization()通过使用键要求
locationManager?.requestAlwaysAuthorization()
<key>NSLocationAlwaysUsageDescription</key> <string>Allow location</string>
在您的 Info.plist中
通过同时使用 2个LocationManager, 可以有第三个解决方案。
对于区域
重大地点变更
作为使用 significantLocationChanges
当设备距其先前的通知500米或更多距离时,应用程序会期望收到通知。它不应期望通知的频率超过每五分钟一次。如果设备能够从网络检索数据,则位置管理器更有可能及时传递通知。
按照给苹果文档
因此,这完全取决于您的要求,因为位置获取取决于许多因素,例如在未运行的应用程序中打开的应用程序数量,电池电量,信号强度等。
另外请记住,始终以较高的精度设置区域。
我知道这不能完全解决您的问题,但是您会根据自己的要求前进。