2011-01-08 14 views
27

Tak więc mam do czynienia z pewnymi problemami z dokładnością w przypadku iPhone'a GPS. Mam aplikację, która korzysta z lokalizacji.CLLocationManager i problemy z dokładnością - jakiekolwiek doświadczenia?

W metodzie delegata locationManager: didUpdateToLocation: fromLocation: otrzymuję informację o lokalizacji. Z badań wynika, że ​​GPS nie zawsze jest dokładny przy pierwszym wyniku, który powraca, nawet po ustawieniu właściwości desiredAccuracy na kCLLocationAccuracyBest.

Aby obejść ten problem, nie wzywam numeru stopUpdatingLocation, zanim zostanie on zwrócony newLocation: co najmniej 3 razy (jest to bardzo szybkie). Grałem też z dwoma innymi "wymaganiami", czy do stopUpdatingLocation i zwróciłem newLocation. Jednym ze sposobów, w jaki próbowałem, było sprawdzenie czasu i długości dla newLocation i porównanie z oldLocation, a jeśli nie były identyczne, to utrzymywanie aktualizacji lokalizacji działa. Próbowałem też sprawdzić odległość między oldLocation i newLocation, a jeśli jest mniejsza niż 20 metrów, to jest w porządku. Oba są testowane po powrocie co najmniej 3 przebiegów. Ten drugi sposób jest mniej "ścisły", ponieważ trudno jest uzyskać newLocation i oldLocation będąc w 100% identycznym, jeśli użytkownik znajduje się w poruszającym się pojeździe.

Mój problem polega na tym, że nawet podczas wykonywania powyższych czynności (zasadniczo nie akceptuję lokalizacji, dopóki kilka aktualizacji nie wystąpiło na CLLocationManager I sprawdzanie odległości między CLLocations (lub czy są one identyczne) wciąż widzę coś dziwne wyniki dla lokalizacji czasami, podczas testowania.

Będzie to naprawiać czasami, gdy opuszczę aplikację, przejdź do Maps.app, użyj GPS, a następnie otwórz wielozadaniowość, wymuś zamknięcie aplikacji, a następnie ponownie otwórz, aby uzyskać czyste Uruchomienie:

Wszelkie doświadczenia i możliwe rozwiązania, które ludzie wykorzystali do obejścia tego samego rodzaju zagadnień Komentarze i rozwiązania doceniane :)

Odpowiedz

45

Nie pamiętam, z którego projektu pochodzi dokładnie ten kod, ale to zadziałało bardzo dobrze (pamiętam, że pochodziło z wideo z WWDC 2010). W moim kodzie zostawiłem komentarze z oryginalnego projektu w takt, więc mam nadzieję, że to pomoże.

- (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]; 
     } 
    } 
} 

Mam nadzieję, że to pomoże!

Via GetLocationViewController.m w "Znajdź mnie" przykładowy projekt Apple, dostępny pod adresem:

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

+0

Ah , doskonały! Powinienem przyjrzeć się bliżej właściwościom zwróconej nowej lokacji CLLocation, nie zdawałem sobie sprawy, że ma ona również timeStamp. Prawdopodobnie użyję tego razem z moim własnym kodem. Wielkie dzięki! – runmad

+1

na przykładzie Apple "Zlokalizuj mnie": https://developer.apple.com/library/ios/#samplecode/LocateMe/Listings/Classes_TrackLocationViewController_m.html#//apple_ref/doc/uid/DTS40007801-Classes_TrackLocationViewController_m-DontLinkElementID_14 – Garoal

+0

this jest dokładnie tym, czego szukam. Dziękuję Ci. – bselvan

0

Od odpowiedzi donkim za rozważyć zastąpienie tej linii

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

z linii

[NSObject cancelPreviousPerformRequestsWithTarget: self]; 
Powiązane problemy