CLLocationManager и вопросы точности - есть опыт? - PullRequest
27 голосов
/ 08 января 2011

Так что я имею дело с некоторыми проблемами точности с iPhone GPS. У меня есть приложение, которое использует местоположение.

В методе делегата locationManager: didUpdateToLocation: fromLocation: Мне возвращается местоположение. После небольшого исследования выясняется, что GPS не всегда точен при первом возвращаемом результате, даже если для свойства desiredAccuracy установлено значение kCLLocationAccuracyBest.

Чтобы обойти это, я не звоню stopUpdatingLocation, пока он не будет возвращен newLocation: как минимум 3 раза (это очень быстро). Я также поигрался с двумя другими «требованиями» относительно того, следует ли stopUpdatingLocation и вернуть newLocation. Один из способов, которым я пытался, состоял в том, чтобы проверить lat и long для newLocation и сравнить с oldLocation, и если они не были идентичны, тогда продолжать обновление местоположения. Я также попытался проверить расстояние между oldLocation и newLocation, и если оно меньше 20 метров, это нормально. Оба из них проверены с возвратом не менее 3 прогонов. Последний способ менее "строг", поскольку newLocation и oldLocation довольно сложно избежать 100% идентичности, если пользователь находится в движущемся транспортном средстве.

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

Иногда было бы исправлено, если бы я покинул приложение, зашел в Maps.app, использовал GPS, затем открыл многозадачность, принудительно вышел из приложения и снова открыл его, чтобы получить чистый запуск.

Какой опыт и возможные решения люди использовали для решения той же проблемы? Комментарии и решения приветствуются:)

Ответы [ 2 ]

45 голосов
/ 09 января 2011

Я не помню, из какого проекта я получил следующий код, но он мне очень помог (помню, он был из видео WWDC 2010).В своем коде я оставил комментарии исходного проекта в такте, поэтому надеюсь, что это поможет.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    // 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 (bestEffortAtLocation == nil || bestEffortAtLocation.horizontalAccuracy > newLocation.horizontalAccuracy) {
        // store the location as the "best effort"
        self.bestEffortAtLocation = 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 <= 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 stopUpdatingLocation:NSLocalizedString(@"Acquired Location", @"Acquired Location")];

            // we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpdatingLocation:) object:nil];
        }
    }
}

Надеюсь, это поможет!

Через GetLocationViewController.m в примере Apple "Locate Me"проект, доступный по адресу:

https://developer.apple.com/library/content/samplecode/LocateMe/Introduction/Intro.html

0 голосов
/ 02 июля 2012

Из ответа donkim рассмотрите возможность замены этой строки

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpdatingLocation:) object:nil];

со строкой

[NSObject cancelPreviousPerformRequestsWithTarget: self];
...