iOS: уменьшение частоты фоновых обновлений местоположения
Я делаю фоновое отслеживание местоположения в приложении, и оно запускается слишком часто. Я не уверен, что является лучшим методом для установки минимального интервала времени для обновления местоположения. Я хочу сохранять данные о местоположении каждые 2 минуты или около того. Некоторые говорят, что используют NSTimer, но я не уверен, как и где включить это в мой текущий код. Ниже приведен весь мой код отслеживания местоположения в AppDelegate. Кто-нибудь знает лучшую технику для уменьшения частоты обновлений местоположения, учитывая мой текущий код?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
{
isBackgroundMode = NO;
_deferringUpdates = NO;
self.locationManager = [CLLocationManager new];
[self.locationManager setDelegate:self];
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
[self.locationManager startMonitoringSignificantLocationChanges];
[self initializeRegionMonitoring];
}
-(void) initializeRegionMonitoring {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// notify changes when the device has moved x meters
self.locationManager.distanceFilter = 10;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
[self.locationManager startMonitoringSignificantLocationChanges];
}
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
[self saveLocation];
//tell the centralManager that you want to deferred this updatedLocation
if (isBackgroundMode && !_deferringUpdates)
{
_deferringUpdates = YES;
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:60];
}
}
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
}
-(void) saveLocation {
// save information database/ communication with web service
}
- (void)applicationWillResignActive:(UIApplication *)application {
isBackgroundMode = YES;
[self.locationManager stopUpdatingLocation];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
self.locationManager.pausesLocationUpdatesAutomatically = NO;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[self.locationManager startUpdatingLocation];
}
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return true;
}
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[self saveLocation];
completionHandler(UIBackgroundFetchResultNewData);
NSLog(@"Fetch completed");
}
Кроме того, поскольку многое из того, что я делаю, компилируется из различных руководств, пожалуйста, не стесняйтесь указывать на все, что я делаю неправильно, с точки зрения производительности или использования батареи. Спасибо!
4 ответа
В других (с открытым исходным кодом) проектах я видел следующие стратегии для экономии энергии:
- Уменьшите запрошенную точность (setDesiredAccuracy) очень большой (не "kCLLocationAccuracyBest", а фактически "kCLLocationAccuracyKilometer")
- Уменьшите счетчик обратных вызовов "didUpdateLocations:", установив большой порог в "distanceFilter"
- Возврат из обратного вызова, если запись не нужна (с другими критериями, такими как время)
В любом случае я не вижу необходимости в дополнительном таймере здесь. То, что вы хотите сделать, это начать с грубой точности (если вы можете!) И дополнительно установить для своего distanceFilter высокое значение (например, более 10 метров).
Кроме того, вы можете сделать следующее: в вашем обратном вызове didUpdateLocations: вызывать saveLocation, только если lastSaveTime более 5 минут назад if(lastSaveTime + 5 < thisSaveTime) { ... }
при условии, что время измеряется в секундах.
Как вы заявили в своем
-(void) initializeRegionMonitoring
Значение расстояния фильтра до 10
self.locationManager.distanceFilter = 10;
Поэтому после того, как пользователь переместится на 10 метров, ваш didUpdateLocations
будет называться,
Если вы хотите минимизировать вызов этого метода делегата, вам нужно увеличить значение distanceFilter
,
- Запустите службу, когда пользователь перемещает, и остановите службу, когда местоположение. Точность меньше, чем Точность locatonManager.
Менеджер местоположений должен быть автоматически приостановлен и попытаться использовать делегат резюме местоположений.
Проверьте время последнего местоположения и нового местоположения.
Это уменьшит батарею.
self.locationManager.distanceFilter = 10;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
Попробуй это....!!