我需要一直跟踪用户位置(但不要耗尽电池)。 我了解终止应用后获取更新的唯一方法是使用startMonitoringSignificantLocationChanges。
来自Apple关于startMonitoringSignificantLocationChanges的位置感知编程指南:
如果您启动此服务,则随后会提交您的申请 终止后,系统会自动将应用程序重新启动到 新活动到来的背景。在这种情况下,选项 字典传递给应用程序:didFinishLaunchingWithOptions: 应用程序委托的方法包含密钥 UIApplicationLaunchOptionsLocationKey表示你的 应用程序是由于位置事件而启动的。 重新启动后, 您仍然必须配置位置管理器对象并调用它 继续接收位置事件的方法。当你重新启动 位置服务,当前事件将传递给您的代理人 立即。此外,您所在位置的位置属性 管理器对象甚至填充了最新的位置对象 在开始定位服务之前。
如果有人能够在代码中演示(举例)我应该使用哪种方法
,我会很高兴在下面的代码中我要说: - 在appdelegate启动位置管理器,它可以监控重要的监视器更改和启动更新。 - 在didUpdateToLocation中我正在调用stopupdating - 在didFinishLaunchingWithOptions中,当我检查是否有UIApplicationLaunchOptionsLocationKey以便知道我是否在后台并且由于显着的监视器位置更新而启动。 - 如果是这样,我再次调用startMonitoringSignificantLocationChanges(不知道为什么......) 并启动一个UIBackgeoundTaskIdentifier来调用startupdating方法。
LocationController.m :
+ (LocationController*)sharedInstance {
@synchronized(self) {
if (sharedCLDelegate == nil) {
[[self alloc] init];
}
}
return sharedCLDelegate;
}
- (id)init
{
self = [super init];
if (self != nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[self.locationManager startUpdatingLocation];
[self.locationManager startMonitoringSignificantLocationChanges];
}
return self;
}
- (void) startMonitoringSignificantLocationChanges
{
[self.locationManager startMonitoringSignificantLocationChanges];
}
- (void) stopMonitoringSignificantLocationChanges
{
[self.locationManager stopMonitoringSignificantLocationChanges];
}
-(void) start{
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation{
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) {
self.lastLocation = newLocation;
[self updateLocation]; //sending location to server
[self.locationManager stopUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager*)manager
didFailWithError:(NSError*)error{
[self.locationManager stopUpdatingLocation];
}
AppDelegate.h :
@interface AppDelegate : NSObject <UIApplicationDelegate> {
UIBackgroundTaskIdentifier bgTask;
}
AppDelegate.m :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
id locationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey];
if (locationValue) {
[[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
[[LocationController sharedInstance] start]; //startupdating
return YES;
}
else {
[[LocationController sharedInstance] init];
}
}
-(void) applicationDidEnterBackground:(UIApplication *) application
{
NSLog(@"entered background Mode");
}
-(void) applicationDidBecomeActive:(UIApplication *) application
{
NSLog(@"application Did Become Active");
}
谢谢。
答案 0 :(得分:10)
使用你的课程,这就是我要做的。
在你的AppDelegate.m中,当你的应用程序位于前台或后台时,我会移动CLLocationManager以在前台/后台运行以匹配。我这样做的原因是因为如果应用程序在后台时CLLocationManager没有移动到后台,则不会向CLLocationManager的回调发送位置更新
- (void)applicationDidEnterBackground:(UIApplication *) application {
[[LocationController sharedInstance] stop];
[[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
NSLog(@"entered background Mode");
}
- (void)applicationDidBecomeActive:(UIApplication *) application {
[[LocationController sharedInstance] stopMonitoringSignificantLocationChanges];
[[LocationController sharedInstance] start];
NSLog(@"application Did Become Active");
}
因此,假设您的应用移动到后台,过了一段时间,iOS决定使用太多内存并杀死您的应用。
几分钟后,iOS会收到位置更新,并重新生成您的应用,让它知道由于位置服务而重新生成的应用。然后,您需要重新启动后台位置服务,因为这将是您的应用程序必须这样做的唯一机会。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
[[LocationController sharedInstance] startMonitoringSignificantLocationChanges];
}
return YES;
}
哦,最后一次更改,我不确定为什么在你的locationManager:didUpdateToLocation:fromLocation:
方法中你停止了位置服务,就像你这样做时不再有更新。只需保持运行,然后每次更改位置时都可以将其发送到服务器。
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 30) {
self.lastLocation = newLocation;
[self updateLocation]; //sending location to server
}