Возможно ли влияние на CLLocationManager других приложений? - PullRequest
4 голосов
/ 20 января 2012

Я сталкиваюсь с очень странной ситуацией с приложением, которое использует CLLocationManager для получения текущего местоположения пользователя.Я использую класс-оболочку, который очень похож на пример кода Apple CLLocationManager.Он начинает поиск местоположения и ждет, пока ему не будет дано местоположение, отвечающее некоторым критериям (возраст отметки времени, точность).Все работает хорошо, когда я нахожусь в очень доступной области GPS.

Теперь вопрос.Когда я нахожусь в моем офисе, на Wi-Fi-соединении, где сигнал GPS кажется паршивым, я открываю свое приложение, и оно никогда не может найти подходящее место.Я выхожу из своего приложения, открываю Foursquare, и он почти сразу находит места рядом со мной, заставляя меня предположить, что он нашел мое местоположение.Я выхожу из Foursquare и снова открываю свое приложение, чтобы найти его почти мгновенно.

Может кто-нибудь пролить свет на то, что здесь может происходить?Я могу опубликовать некоторый код, если люди думают, что это будет полезно, но это более общий вопрос о том, как другие приложения могут положительно или отрицательно влиять на функциональность CLLocationManager.В идеале, я бы хотел знать, что именно Foursquare делает, чтобы получить местоположение так быстро, и как это может привести к тому, что мое приложение вдруг начнет его получать.

РЕДАКТИРОВАТЬ: Судя по приведенному ниже ответу, люди испытали кеширование между приложениями, и это нормально.Однако это не объясняет, почему Foursquare получает местоположение, а мое приложение получает его только после использования Foursquare.Ниже приведен мой код CLLocationManager, надеюсь, кто-нибудь найдет пистолет для курения:

- (void) lazyInit {
    if (!self.locationManager) {
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
        self.reverseGeocoder = [[WPGeocodingService alloc] initWithDelegate:self];
        self.locationAndPlacemark = NO;
    }
}

- (void) getCurrentLocation {
    [self lazyInit];
    self.recentLocation = nil;
    [self performSelector:@selector(timeoutLocationFetch) withObject:nil afterDelay:kLocationFetchTimeout];
    [self.locationManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSLog(@"LocationService:update: <%f,%f> Accuracy: %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude,
          newLocation.horizontalAccuracy);

    // test the age of the location measurement to determine if the measurement is cached
    // in most cases you will not want to rely on cached measurements
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
    if (locationAge > 5.0) return;

    // test that the horizontal accuracy does not indicate an invalid measurement
    if (newLocation.horizontalAccuracy < 0) return;

    // test the measurement to see if it is more accurate than the previous measurement
    if (self.recentLocation == nil || self.recentLocation.horizontalAccuracy > newLocation.horizontalAccuracy) {
        // store the location as the "best effort"
        self.recentLocation = newLocation;
        // test the measurement to see if it meets the desired accuracy
        //
        // IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue 
        // accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of 
        // acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout.
        //
        if (newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy) {
            // we have a measurement that meets our requirements, so we can stop updating the location
            // 
            // IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible.
            //
            [self.locationManager stopUpdatingLocation];
            // we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeoutLocationFetch) object:nil];

            if ([self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) {
                [self.delegate locationService:self didReceiveLocation:self.recentLocation];
            }
        }
    }    
}

- (void)locationManager:(CLLocationManager *)manager  didFailWithError:(NSError *)error {
    NSLog(@"LocationService:error: %@", [error description]);
    if ([error code] != kCLErrorLocationUnknown) {
        [self.locationManager stopUpdatingLocation];
        if ([self.delegate respondsToSelector:@selector(locationService:didFailWithError:)]) {
            [self.delegate locationService:self didFailWithError:error];
        }
    }
}

- (void) timeoutLocationFetch {
    NSLog(@"LocationService:timeout");
    [self.locationManager stopUpdatingLocation];
    if (self.recentLocation && [self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) {
        if ([self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) {
            [self.delegate locationService:self didReceiveLocation:self.recentLocation];
        }
    } else {
        NSError* error = [NSError errorWithDomain:@"Location Error" code:0 userInfo:
                          [NSDictionary dictionaryWithObject:@"The application could not determine your location." forKey:NSLocalizedDescriptionKey]];
        if ([self.delegate respondsToSelector:@selector(locationService:didFailWithError:)]) {
            [self.delegate locationService:self didFailWithError:error];
        }
    }
}

Ответы [ 2 ]

1 голос
/ 23 мая 2012

Почему вы используете

self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters

а не kCLLocationAccuracyBest? Конечно, не сравнивая горизонтальную точность с этой, как вы заметили, отрицательной константой, но вместо этого есть какое-то разумное другое значение (скажем, 100.0m). Вы пробовали, имеет ли это значение?

Желаемая точность определяет, сколько усилий затрачивается на определение местоположения (для более высоких значений GPS даже не включается, как вы можете проверить с помощью Xcode / Instruments / EnergyDiagnostics). Меньшие усилия приводят к меньшей точности и / или большему времени для получения позиции. Разве это не звучит разумно?

Из моих собственных наблюдений: при запросе iOS о позиции с определенной желаемой точностью результат может быть любым: менее точным (например, в здании с плохим приемом GPS), настолько точным, насколько это необходимо, или фактически более точным, чем необходимо (другое приложение или другой объект CLlocationManager того же приложения могут одновременно запрашивать аппаратное обеспечение более высокую точность - тогда все другие приложения наследуют лучшие значения без дополнительных усилий).

В дополнение к вышесказанному может иметь значение, если ваше устройство iOS имеет доступ к Интернету, потому что это GPS-приемник с поддержкой *1015*. Может быть, есть некоторый побочный эффект при загрузке некоторых вспомогательных данных, если устройство подключено к сети из-за какой-то другой интернет-активности. Впрочем, эта последняя мысль - чистое предположение.

Еще одна вещь: Если я не пропустил это в вашем коде, значит, вы не определили фильтр расстояний. Попробуйте что-то вроде

self.locationManager.distanceFilter = kCLDistanceFilterNone;

, чтобы обеспечить получение максимально возможного количества обновлений.

0 голосов
/ 20 января 2012

да, я думаю, что CLLocationManager кеширует местоположение в некоторой степени, я попробовал несколько вещей, таких как запуск GoogleMaps, мое местоположение было найдено, затем запустил мое приложение, оно сразу нашло мое местоположение.Также попытался, запустив приложение навигации, нашел мое местоположение, немедленно убил его, запустил другие приложения, которые используют местоположение, все приложения могут найти замок в местоположении почти мгновенно.

...