Как эффективно получать обновления местоположения с помощью ios, когда deferredlocationupdatesavailable возвращает NO - PullRequest
0 голосов
/ 03 июня 2018

Я пытаюсь отложить обновления местоположения в ios 11 для экономии энергии.Кажется, что по умолчанию обновление происходит как можно быстрее (т. Е. Каждую секунду), поэтому я хочу отложить обновления или сделать что-то еще более умное для создания энергоэффективного приложения.

При реализации CLLocationManager и настройке следующим образом:

    _locationManager = [[CLLocationManager alloc] init];
    _locationManager.delegate = _sharedInstance = [[LocationManager alloc] init];
    [_locationManager requestAlwaysAuthorization];
    _locationManager.allowsBackgroundLocationUpdates = true;
    _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    _locationManager.distanceFilter = 0;
    _locationManager.pausesLocationUpdatesAutomatically = NO;
    _locationManager.activityType = CLActivityTypeFitness; 

[CLLocationManager deferredLocationUpdatesAvailable] возвращает ложь в didUpdateLocations и, таким образом, я получаю ошибку 11 при попытке отложить использование метода allowDeferredLocationUpdatesUntilTraveled 1011 1010.вопросы ( здесь и здесь ) указывают на то, что обновления отложенных расположений больше не поддерживаются.

В любом случае, как вы тогда повышаете эффективность приложений определения местоположения ios, когда вам нужны обновления?каждые x (например, 15) секунд, лучшая (то есть GPS) точность и работа / работа всегда в фоновом режиме?

1 Ответ

0 голосов
/ 21 июня 2018

Этот ответ может быть немного неправильным, потому что на самом деле больше невозможно использовать функцию дефферирования, даже если документ не был удален.Но цель состояла в том, чтобы включать / выключать местоположение через определенные промежутки времени, чтобы не включать его постоянно для экономии энергии.

Чтобы приблизиться к полному включению / выключению, можно переключаться между высокой и низкой точностью,это сэкономит энергию наверняка.(высокая точность обычно <10 м будет использовать модуль GPS, низкая точность> 500 м будет обычно AGPS .

Сначала запустите NSTimer с нужным интервалом, затем начните обновление с высокой точностью.При получении местоположения в didUpdateLocations измените с высокой точности на низкую точность. Обратный вызов NSTimer запрашивает новое высокоточное обновление местоположения (то есть вызывает setupHighAccuracy). Таким образом, таймер устанавливает частоту обновлений высокой точности. Это также будет работатьв фоновом режиме, потому что служба определения местоположения все еще работает. При остановке обновлений приложение остановится в фоновом режиме. При остановке и повторном запуске диспетчера местоположений оно немедленно вызовет didUpdateLocation, но при проверке отметки времени местоположение может быть буферизовано..

Ниже показаны некоторые фрагменты, чтобы начать работу. Для производственного кода потребуется дополнительная фильтрация и тестирование:

@property (retain, nonatomic) NSTimer *atimer;

static BOOL _lowAccuracy;  

- (void)timerCallback {
    [self setupHighAccuracy];
}

- (void)setupTimer
{
    if(self.atimer != nil)
    {
        return;
    }

    UIApplication *app = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier bgTaskId =
    [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTaskId];
        bgTaskId = UIBackgroundTaskInvalid;
    }];

    dispatch_async( dispatch_get_main_queue(), ^{

                        self.atimer = [NSTimer scheduledTimerWithTimeInterval:15.0 // consider higher interval
                                    target:self
                                    selector:@selector(timerCallback)
                                    userInfo:nil
                                    repeats:YES];

                    }   

        [app endBackgroundTask:bgTaskId];
        bgTaskId = UIBackgroundTaskInvalid;
    });
}

- (void)setupHighAccuracy
{    
    if(_lowAccuracy)
    {        
        [_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
        _locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; // or kCLLocationAccuracyBest, tune yourself
        _locationManager.activityType = CLActivityTypeFitness;
        _locationManager.distanceFilter = 15; // or 0, tune yourself
        _lowAccuracy = false;
        [_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
    }
}

- (void)setupLowAccuracy
{    
    if(!_lowAccuracy)
    {
        s_initialized = true;            
        [_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
        _locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
        _locationManager.activityType = CLActivityTypeFitness;
        _locationManager.distanceFilter = 3000;
        _lowAccuracy = true;
        [_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
    }
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = locations.lastObject;
    if(!_lowAccuracy) {            
        // update system with location here
        [_locationManager.delegate setupLowAccuracy];
        self.s_lastLocation = location;
    }             
}
...