ios,startMonitoringSignificantLocationChanges - 有时会破坏监控 [英] ios, startMonitoringSignificantLocationChanges - sometimes breaks monitoring

查看:129
本文介绍了ios,startMonitoringSignificantLocationChanges - 有时会破坏监控的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有更新用户位置的奇怪问题。有时我的应用程序会更新位置,但有时会更新。我不知道问题出在哪里,我的代码(来自AppDelegate.m)如下:

I have strange problem with updating user's location. Sometimes my app updates location but from time to time breaks updating. I do not know where is problem, my code (from AppDelegate.m) is below:

- (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米。我选择了第二种方式以节省电池,但我的解决方案无法正常工作。

I need to update location every hour or if user change location more then 1000m. I chose the second way in order to save battery but my solution do not work as I need.

我非常感谢任何帮助,提前谢谢!

I would greatly appreciate any help on this, Thanks in advance!

推荐答案

我不能确定这是否是你们所有人的问题,但我会做出以下改变:

I can't say for sure if this is all of you problem but I would make the following changes:

- (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 ):

Following your lead, this would be all that remains in your didBecomeActive method (I would use willEnterForeground instead):

- (void)willEnterForeground:(UIApplication *)application
{
   [self.locationManager stopMonitoringSignificantLocationChanges];
   [self.locationManager startUpdatingLocation];
}

进入后台,返回重要位置更改:

Entering into background, go back to significant location changes only:

- (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(可选):

In your delegate method, I recommend taking out all the conditional background testing. I am wrapping in background task identifier in case the app is in the background or goes into the background before finish. I am also responding on global thread so we don't block UI (optional):

- (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的例子。

on Github for some more examples of using Core Location the way you wish to use it.

这篇关于ios,startMonitoringSignificantLocationChanges - 有时会破坏监控的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆