我在后台状态下遇到了计时器问题。无法保证您将有一个活动的运行循环,因此计时器永远不会触发,直到您返回前台。我所做的是:
NSRunLoop *loop = [NSRunLoop currentRunLoop];
[loop addTimer:myTimer forMode:NSRunLoopCommonModes];
[loop run];
我在BackgroundIdentifierTask开始和结束调用内的后台线程上执行此操作。我并不完全相信我的所有内容都是正确的,事实上,我查看了您的问题,看看答案是否可以帮助我确认或纠正我对要求的理解。
如果您想持续监控位置,还必须在默认 info.pList 中启用位置服务的后台模式。如果您只是使用 importantLocationUpdates 或地理围栏,则不需要这样做。
我的计时器确实工作并且按照预期的方式启动。在此之前它并不能可靠地工作。
除此之外,最好不要使用计时器。使用上面的代码,只需更改位置管理器的属性即可。所需的准确性和距离过滤器是可减少管理器发送新位置通知频率的属性。
请参阅我刚刚在 github 上发布的我自己的位置处理程序的示例,供任何感兴趣的人使用:
http://github.com/dsdavids/TTLocationHandler
我不认为计时器是关键。如果您将 TTLocationHandler 类删除到项目中,请查看 LMViewController 类如何响应处理程序。
NSNotificationCenter *defaultNotificatoinCenter = [NSNotificationCenter defaultCenter];
[defaultNotificatoinCenter addObserver:self selector:@selector(handleLocationUpdate) name:LocationHandlerDidUpdateLocation object:nil];
将控制器设置为观察者。每当处理程序确定已接收到新的或更准确的位置时,就会调用handleLocationUpdate。
当调用 startUpdating 时,locationManager 将发送新的位置,一开始每秒发送多个位置,并且在移动时发送新位置,直到设备静止并达到准确度。这TTL位置处理程序正在过滤这些事件并仅根据配置根据需要发送通知。
请注意,在 -(id)init 中,_recencyThreshold 设置为 60。因此,我们每 60 秒保存或显示一个 pin。如果您想要更小的间隔,请更改此值。
事实上,TTLocationHandler 在后台时总是会切换到显着的位置变化,除非设备已插入电源。如果使用电池供电,则更新之间的间隔不会那么小,但您会获得更新。
我添加了一个属性来配置连续后台更新而无需付费。
TTLocationHandler 的使用示例
我在存储库中添加了另一个类,以展示我将如何使用我的处理程序实现您的目标。我添加了 LMPinTracker 类,您可以在其中添加用于存储和上传位置的代码。
看看LMAppDelegate.m
self.pinTracker.uploadInterval = 30.00;
将其更改为您想要的上传到服务器之间的任何间隔。
self.sharedLocationHandler.recencyThreshold = 5.0;
将 5.0 更改为您想要的存储位置之间的最短时间。它并不准确,会因行进速率和信号强度而异,但基本上,在 x 秒间隔后,它会认为存储的位置已过时,并尝试获取另一个准确的位置。
现在查看 LMPinTracker.m 文件
将数据存储代码放在这两行之后:
// Store the location into your sqlite database here
NSLog(@"Received location info: %@ \n Ready for store to database",lastKnowLocationInfo);
将您的网络上传代码放在此评论之后:
// Do your upload to web operations here
Comments
这应该可以完成您想要做的事情,同时仍然尊重用户电池和后台操作。
基本上,当用户旅行时,更新将按照您设置的时间间隔持续进行。
当用户静止时,不会有更新,也不会发生重大活动。
当没有新的活动时,您也不会上传到网络。
当用户再次开始移动时,日志记录和更新将恢复。
如果我是你,想要进一步完善它,我会考虑设置一个区域和时间来检查。如果用户长时间保持静止,则仅切换到 importantLocationUpdates。然后,您将关闭定位服务,但当用户再次开始使用时,您将重新启动定位服务。