我正在寻找一种方法,我可以跟踪用户已经到达指定的坐标集附近。当应用程序在后台时(最好在100米内),功能需要工作。另外,为了保存电池,理想情况下我不希望得到太多的坐标读数(也许每10分钟阅读一次不超过几个小时)。
我尝试过几种方法来完成此任务,但无法获得所需的结果:
后台计时器:
我在(App.delegate)
中添加了后台任务func applicationDidEnterBackground(_ application: UIApplication)
执行重复的Timer.scheduledTimer以获取坐标和进程
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
检测用户是否在范围内。如果在短期内应用此方法,但只有在应用程序暂停后才能使用,大约需要3分钟。理想情况下,我不想经常这样做坐标。
区域监控:
我初始化了CLLocationManager,如下所示:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.activityType = .otherNavigation
locationManager.requestAlwaysAuthorization()
}
当应用程序进入后台时,LocationManager启动:
func applicationDidEnterBackground(_ application: UIApplication) {
self.monitorRegionAtLocation(center: CLLocationCoordinate2D(latitude: x, longitude: y), identifier: id)
locationManager.startUpdatingLocation()
}
区域监测守则:
func monitorRegionAtLocation(center: CLLocationCoordinate2D, identifier: String ) {
// Make sure the app is authorized.
if CLLocationManager.authorizationStatus() == .authorizedAlways {
// Make sure region monitoring is supported.
if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
// Register the region.
let maxDistance = 200.0
let region = CLCircularRegion(center: center,
radius: maxDistance, identifier: identifier)
region.notifyOnEntry = true
region.notifyOnExit = false
locationManager.startMonitoring(for: region)
}
}
}
我为CLLocationManager添加了一个didEnterRegion函数块:
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
if let region = region as? CLCircularRegion {
let identifier = region.identifier
print("FOUND: " + identifier)
}
}
该代码似乎适用于检测进入某个区域,但是在后台时坐标不会更新。
其他信息
我认为必须有更好的方法在后台运行这些检查,但我还没有发现任何检测后台其他动作的方法。
对此问题的任何指示都将不胜感激,如果您需要更多信息,请告诉我,我会尽我所能。
更新:
我已根据以下评论的建议修改了该方法,以使用区域监控。
答案 0 :(得分:3)
任何位置更新/监控都需要对其位置管理器进行正确配置,以便能够最好地提供所需的位置更新。在进行后台位置更新时检查某些要点非常重要:
1。检查位置更新的背景模式,并启用后台提取
2。检查'位置始终使用说明'和'使用位置使用说明'应在Info.plist中提供
3。检查是否要在位置更新之间暂停 - 如果是,则需要提供活动类型,以便位置管理员可以确定暂停位置更新的最佳方式
4。检查是否要应用距离过滤器 - 您希望用户(设备)移动一些最小数量的位置管理器以发送更新的位置
5。检查您是否需要所需的精度 - 这可能导致某些精度类型的功耗
在您的代码中,我可以看到位置管理器配置了一些参数,但缺少准确性和背景模式的距离过滤器。
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.activityType = .otherNavigation
另外,如果您在Apple doc中看到暂停位置更新属性,则说明:
对于具有使用中授权的应用,暂停到位置更新 结束访问位置更改,直到应用程序再次启动和 能够重新启动这些更新。如果您不希望更新位置 完全停止,请考虑禁用此属性并更改位置 当您的应用移动到时,准确度为kCLLocationAccuracyThreeKilometers 的背景。这样做可以让您继续接收位置 以电源友好的方式更新。
基本上它告诉你,如果你想要禁用暂停,那么你必须保持准确度(kCLLocationAccuracyThreeKilometers)。我猜你的方法中缺少这个。
此外,您可以检查实际启动后台任务的this link,然后在后台任务中启动位置管理器监控。 希望它有所帮助。
答案 1 :(得分:0)
问题是“CLLocationManager区域监控:检测后台到达”。这是非常可能的,但是在被杀之后检测任何东西都是不可能的(来自iOS 7)。
每当用户向您的app app切换器轻扫时,iOS会将其视为用户不希望该应用在后台运行,因此所有回叫都会停止。
This answer,this answer和this answer也说同样的话。但是Apple doc有点令人困惑。
我个人的观察是即使在杀戮模式下也会调用app,但很少。
关于获取位置,无论何时调用地理围栏的委托方法,您都可以轻松获得位置。
您的要求实际上并不需要背景模式。
不幸的是(幸运的是,对于iOS用户而言,他们节省了电量)我们实际上没有办法在应用程序被杀后1小时获取位置。