我有更新用户位置的奇怪问题。有时我的应用程序会更新位置,但有时会更新。我不知道问题出在哪里,我的代码(来自AppDelegate.m)如下:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"Went to Background");
// Only monitor significant changes
[locationManager startMonitoringSignificantLocationChanges];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Start location services
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Only report to location manager if the user has traveled 1000 meters
locationManager.distanceFilter = 1000.0f;
locationManager.delegate = self;
locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[locationManager stopMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// Check if running in background or not
BOOL isInBackground = NO;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
isInBackground = YES;
}
if (isInBackground) {
// If we're running in the background, run sendBackgroundLocationToServer
[self sendBackgroundLocationToServer:[locations lastObject]];
} else {
// If we're not in the background wait till the GPS is accurate to send it to the server
if ([[locations lastObject] horizontalAccuracy] < 100.0f) {
[self sendDataToServer:[locations lastObject]];
}
}
}
-(void) sendBackgroundLocationToServer:(CLLocation *)location
{
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}];
// Send the data
[self sendDataToServer:location];
if (bgTask != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
}
-(void) sendDataToServer:(CLLocation *)newLocation
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *lat = [NSString stringWithFormat:@"%.8f", newLocation.coordinate.latitude];
NSString *lng = [NSString stringWithFormat:@"%.8f", newLocation.coordinate.longitude];
[APIConnection SaveMyPositionWitLat:lat withLng:lng];
});
}
我需要每小时更新一次位置,或者如果用户更改位置超过1000米。我选择第二种方式来节省电池,但我的解决方案不能正常工作。
我非常感谢任何帮助,提前谢谢!
答案 0 :(得分:32)
我不能确定这是否是你们所有人的问题,但我会做出以下改变:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Moved to didFinishLaunching... you should not be recreating every time app
// becomes active. You can check for locations key in the options Dictionary if
// it is necessary to alter your setup based on background launch
// Start location services
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Only report to location manager if the user has traveled 1000 meters
locationManager.distanceFilter = 1000.0f;
locationManager.delegate = self;
locationManager.activityType = CLActivityTypeAutomotiveNavigation;
// Start monitoring significant locations here as default, will switch to
// update locations on enter foreground
[locationManager startMonitoringSignificantLocationChanges];
// Hold in property to maintain reference
self.locationManager = locationManager;
}
在您的领导之后,这将是didBecomeActive
方法中的所有内容(我会使用willEnterForeground
代替):
- (void)willEnterForeground:(UIApplication *)application
{
[self.locationManager stopMonitoringSignificantLocationChanges];
[self.locationManager startUpdatingLocation];
}
进入后台,仅返回重要的位置更改:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"Went to Background");
// Need to stop regular updates first
[self.locationManager stopUpdatingLocation];
// Only monitor significant changes
[self.locationManager startMonitoringSignificantLocationChanges];
}
在您的委托方法中,我建议您取消所有条件后台测试。我在后台任务标识符中包装,以防应用程序在后台或在完成之前进入后台。我也在全局线程上做出响应,所以我们不阻止UI(可选):
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier locationUpdateTaskID = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (locationUpdateTaskID != UIBackgroundTaskInvalid) {
[app endBackgroundTask:locationUpdateTaskID];
locationUpdateTaskID = UIBackgroundTaskInvalid;
}
});
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// You might consider what to do here if you do not ever get a location accurate enough to pass the test.
// Also consider comparing to previous report and verifying that it is indeed beyond your threshold distance and/or recency. You cannot count on the LM not to repeat.
if ([[locations lastObject] horizontalAccuracy] < 100.0f) {
[self sendDataToServer:[locations lastObject]];
}
// Close out task Identifier on main queue
dispatch_async(dispatch_get_main_queue(), ^{
if (locationUpdateTaskID != UIBackgroundTaskInvalid) {
[app endBackgroundTask:locationUpdateTaskID];
locationUpdateTaskID = UIBackgroundTaskInvalid;
}
});
});
}
查看我的项目TTLocationHandler
在Github上了解更多使用Core Location的例子。