我正在为iOS 7创建基于导航的应用程序,我使用CoreLocation框架获取用户的位置数据,
应用程序的要求是在特定的时间开始获取用户的位置,因为我已经用didReceiveRemoteNotification fetchCompletionHandler:方法实现了沉默的推送通知,
,我已经成功地实现了,使用&它调用startUpdatingLocation,并且我能够在委托方法中获得位置数据:
使用此有效载荷:
{"aps" : {"content-available" : 1},"SilentPush" : "4"}
我为后台模式启用了location & remote notification:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
__block UIBackgroundTaskIdentifier bgTask =0;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[self.locationManager startUpdatingLocation];
}];didUpdateLocations
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
lastLoc=[locations lastObject];
[logFile addLocObject:[NSString stringWithFormat:@"Loc: %@",lastLoc]];
}但是问题是:
几秒钟后,location类的委托方法停止,如果设备移动,它将不会发送任何数据,当我将app与前台对话时,它将被称为'didFinishLaunhing‘方法,因此我猜os会在更新位置时杀死应用程序,在设备Diagnostics & usage中,我将得到以下崩溃报告:
Application Specific Information:
MockUpApp2[390] has active assertions beyond permitted time:
{(
<BKProcessAssertion: 0x145ac790> identifier: Called by MockUpApp2, from -[AppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] process: MockUpApp2[390] permittedBackgroundDuration: 40.000000 reason: finishTaskAfterBackgroundContentFetching owner pid:390 preventSuspend preventIdleSleep preventSuspendOnSleep
)}昨天我问了这个问题,现在我可以通过推送通知启动后台位置管理器了,
所以请任何人都能解决这个问题。
谢谢。
注意:如果我在调试模式下运行应用程序,意味着我通过XCode运行应用程序&不停止或不断开连接,应用程序将运行。在这种情况下,应用程序不会被OS停止。
编辑1
如@Stephen所述,如果我删除所有背景文件,
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
[self.locationManager startUpdatingLocation];
}现在应用程序连一次都不会调用didUpdateLocations,
我应该用这种方法写些什么?
Edit 2
根据苹果博士的说法:
If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method.
那么,如果我启用了位置后台模式,应用程序应该在后台运行吗?
发布于 2014-02-07 11:58:26
我认为iOS上的后台处理不像您所期望的那样有效。这不像在Mac或Windows上那样,您可以在后台无限期地运行(即使是在iOS 7中的更改)。
所以,要直接回答你的问题:你开始了一项可以继续在后台运行的任务。有两个“但是”
beginBackgroundTaskWithExpirationHandler之后的行。当你完成的时候,你说endBackgroundTask:beginBackgroundTaskWithExpirationHandler:内容的背景下工作。即使应用程序在后台,委托方法也会被调用。总结:删除beginBackgroundTaskWithExpirationHandler:语句。您只需添加startUpdatingLocation:即可。
发布于 2014-02-07 11:54:47
不久前,我使用CLLocation做了很多工作,我有一些评论和建议,但可能没有完整的解决方案。
我看到您正在将您的反应放在beginBackgroundTaskWithExpirationHandler块中的无声通知上。我认为这是不对的。不过,我确实认为您应该在backgroundTask方法上使用该CLLocationDelegate模式。
更重要的是,苹果很有可能会拒绝你在后台进程中使用位置标志。从我的经验中。我花了很多时间研究如何合理地使用定位服务,提高了我自己流程的准确性。我甚至启用了许多防止过度使用电池的保护措施,他们未经讨论就拒绝了它。我做了,所以它只使用后台服务时,设备是插入充电器。我提出了上诉,并为负责任的使用提出了一个很好的理由,但没有结果。
您应该查找这些术语,并确保您的用例按照声明准确地包含在其中,否则它不会浮出水面。
我仍然说,没有背景服务,你就能得到你想要的东西。使用重要的位置更改和区域监视,您的应用程序将不需要任何东西,但保存最新的已知位置和响应通知。
我会想到这样的方案:
在我看来,你是从错误的角度看待这件事的。这是合乎逻辑的,认为你会发送信息,然后作出回应,让CL做些什么。这不是服务的目的。基本上,您设置了位置管理器,并让它离开。
查看我在GitHub上的存储库中使用的一些模式可能会使您受益。
它已经一年没有更新了,我也不记得我在工作中学到了什么,但是它为我提供了坚实的服务,因为我没有必要去摆弄它。
按照该示例,您将停止并启动,或切换到或从区域或重要位置更改监视所有基于应用程序状态。不需要互动。
您的位置事件是处理的,因为他们来,背景或否。
在您的远程通知响应中,您只会阅读最新的位置信息或任何您需要的信息,并按照您的意图行事。这里不打电话给startUpdatingLocation。如果您在后台使用位置服务,您就不应该首先停止它。
编辑-正确使用Expiration块
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
__block UIBackgroundTaskIdentifier bgTask =0;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
// Do something here. Perhaps you'll log the error or respond with some fall back
// This block will only be run if the handler expires without having been ended
// In that case, you need to end it now or you will crash
If (bgTask != UIBackgroundTaskInvalid) {
[app endBackgroundTask:bgTask];
[bgTask = UIBackgroundTaskInvalid];
}
}];
// This is where the code you intend to run in the background starts
[self.locationManager startUpdatingLocation];
// Now tell the system you are finished, ending background task normally before exit
If (bgTask != UIBackgroundTaskInvalid) {
[app endBackgroundTask:bgTask];
[bgTask = UIBackgroundTaskInvalid;
}
}发布于 2014-02-07 11:53:42
方法beginBackgroundTaskWithExpirationHandler:给它的应用程序时间,但这并不意味着任务可以永远运行。
正如崩溃日志中所述,你的应用程序被杀死了,因为你的时间显然快用完了。
您应该得到相同的结果,只要求位置更新,而不包装到过期处理程序。
我记得,在旧系统中,我通过使用区域监视触发背景中的位置更新来管理类似的事情。
编辑
为了有最好的结果,同时玩的位置,我建议你使用真正的设备,也许你是。
https://stackoverflow.com/questions/21626286
复制相似问题