2012-07-04 34 views
3

我试图构建一个iPhone应用程序,要求我随时使用核心位置来跟踪用户的位置。我正在使用startMonitoringSignificantLocationChanges,以便它在后台更新,并且因为每当发生重大更改时更新的准确性都不如重新更新那么重要。如何在iOS应用程序中在线更新后台位置?

当前我向Web服务发出HTTP请求以更新位置。这在我运行应用程序时完美运行 - 我的位置在我正在存储位置数据的MySQL数据库中更新。但是当应用程序进入后台时 - 我可以看到手机右上角的位置服务图标仍然在运行,但是当我回去查看数据库时,它根本没有更新我的位置。我测试了这一点,通过在城市中进行驱动器,以应用程序运行的一种方式,以及在后台使用应用程序的方式。

从苹果公司的文档:

如果你离开这个业务正常运行,您的应用程序随后被暂停或终止,服务时新的位置数据到达时自动唤醒您的应用程序。在起床时,您的应用程序会被置于后台,并给予少量时间来处理位置数据。由于您的应用程序位于后台,因此它应该尽可能减少工作并避免任何可能阻止其在分配的时间到期之前返回的任务(如查询网络)。如果没有,您的申请可能会被终止。

这种“处理位置数据的时间很少”究竟有多长?是不是建议查询网络,还是不可能在那个时候查询网络?即使应用程序处于后台,是否有更好的方式来跟踪几个不同用户的位置?

回答

4

你应该看看后台任务。

当Apple说small amount of time to process location data时,在locationManager:didUpdateToLocation:fromLocation:方法返回后,您不应该真正依赖获取任何处理时间。假设你正在一个单独的线程中异步运行HTTP请求,在你的应用程序被暂停之前,你可能没有足够的时间来完成它。

UIBackgroundTasks让您在后台向操作系统要求额外的处理时间。发出HTTP请求可能是这样的任务。时间限制是10分钟,尽管你不能保证获得这么多时间。

在您的位置回调中,您应该为您的请求定义新的后台任务。如果操作系统决定它不能再给你任何处理时间,则随时触发到期处理程序块。

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 
    // Start your request here 
    UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     backgroundTask = UIBackgroundTaskInvalid; 
     // Cancel your request here 
    }]; 
} 

当请求已经完成,你应该告诉大家,任务完成后的应用程序:

- (void)requestFinished:(id)request { 
    [[UIApplication sharedApplication] endBackgroundTask:backgroundTask]; 
    backgroundTask = UIBackgroundTaskInvalid; 
} 

在这个例子中,我还没有考虑,你可能会收到多个前位置回调帐户请求已完成。如果发生这种情况,则需要在开始新请求和当前后台任务之前取消该请求和当前后台任务,或者为每个请求创建单独的后台任务。

这样做的另一种方法是在位置回调方法中的主线程上同步运行HTTP请求,但这样做会因为多种原因而做一件坏事,例如,如果用户打开应用程序正在运行。

+0

太棒了,男人。这应该工作。现在调整和测试... – unsunghero

+0

这很好。快速问题 - 它如何确定在后台执行哪个代码块?它只是后台任务启动的整个功能吗? – unsunghero

+2

当开始一个后台任务时,你基本上告诉系统你有一个你想要执行的任务,在这种情况下是一个HTTP请求。系统不知道你在开始和结束任务之间做了什么,这就是为什么它给了你UIBackgroundTaskIdentifier,所以你可以在任务完成时向你报告。我的示例代码可能有点不清楚,因为我将UIBackgroundTaskIdentifier声明为局部变量。它应该是一个实例变量,您可以在请求完成并传递给endBackgroundTask时访问它。 –

相关问题