Mam również wiele problemów z CLLocationManager na iPhone również. Z różnych Aplikacji oraz prób i błędów to właśnie wymyśliłem;
1) Użyj klasę singleton dla locationManager, tylko jedną instancję, wykonaj następujące przykłady w: przykład
Apple LocateMe
Tweetero: http://tweetero.googlecode.com/svn/trunk
myślę może masz tylko jedno Menedżer lokalizacji działa, w iPhonie jest tylko jeden układ GPS, więc jeśli uruchomisz wiele obiektów menedżera lokalizacji, będą one w konflikcie, a ty otrzymasz błędy od menedżera lokalizacji GPS, który twierdzi, że nie może go zaktualizować.
2) Bądź bardzo ostrożny w jaki sposób zaktualizować locationManager.desiredAccuracy
i locationManager.distanceFilter
Śledź przykład w kodzie Apple'a za to w FlipsideViewController:
[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet;
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet;
Podejście to działa i nie powoduje żadnych błędów.Po zaktualizowaniu desiredAccuracy lub distanceFilter w pętli głównej Delegat:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
Rdzeń Lokalizacja najprawdopodobniej skarżą się, że nie można zaktualizować wartości i daje błędy. W ten sposób należy używać tylko stałych dla desiredAccuracy
dostarczonych przez Apple, a nie innych, tym samym;
kCLLocationAccuracyBest, kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometers
użycie innych wartości może dać błędy z locationManager. Dla distanceFilter
możesz użyć dowolnej wartości, ale bądź świadomy, że ludzie orzekli, że ma problemy, główną wartością domyślną jest: -1 = Najlepsza, użyłem 10.0 i wygląda na to, że jest OK.
3) Aby wymusić nową aktualizację, wywołaj metodę startUpdates
, tak jak w Tweetero, wymusza to locationManager, aby to zrobić, i powinien spróbować uzyskać nową wartość.
4) Podstawowa procedura delegowania lokalizacji jest trudna do uzyskania dokładnych aktualizacji. Po pierwszej inicjalizacji aplikacji możesz wyłączyć się z dokładnością do 1000 metrów lub więcej, a więc jedna próba nie będzie tego robić. Trzy próby po inicjalizacji zwykle sprawiają, że jesteś w odległości 47 lub więcej metrów, co jest dobre. Pamiętaj, że każda kolejna próba trwa dłużej i dłużej, aby poprawić swoją dokładność, przez co szybko staje się droga. Oto, co musisz zrobić: Podejmij nową wartość tylko, jeśli jest ostatnia ORAZ Jeśli nowa lokalizacja ma nieco lepszą dokładność, wybierz nową lokalizację LUB Jeśli nowa lokalizacja ma dokładność < 50 metrów podejmie nową lokalizację LUB Jeśli liczba prób przekroczyła 3 lub 5, a dokładność: < 150 metrów ORAZ lokalizacja zmieniła się, to jest to nowe położenie, a urządzenie zostało przeniesione, więc zmień tę wartość na , nawet jeśli jej dokładność jest gorsza. Oto mój kod Położenie to zrobić:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
locationDenied = NO;
if(![[NSUserDefaults standardUserDefaults] boolForKey:@"UseLocations"])
{
[self stopAllUpdates];
return;
}
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = abs([eventDate timeIntervalSinceNow]);
attempts++;
if((newLocation.coordinate.latitude != oldLocation.coordinate.latitude) && (newLocation.coordinate.longitude != oldLocation.coordinate.longitude))
locationChanged = YES;
else
locationChanged = NO;
#ifdef __i386__
//Do this for the simulator since location always returns Cupertino
if (howRecent < 5.0)
#else
// Here's the theory of operation
// If the value is recent AND
// If the new location has slightly better accuracy take the new location OR
// If the new location has an accuracy < 50 meters take the new location OR
// If the attempts is maxed (3 -5) AND the accuracy < 150 AND the location has changed, then this must be a new location and the device moved
// so take this new value even though it's accuracy might be worse
if ((howRecent < 5.0) && ((newLocation.horizontalAccuracy < (oldLocation.horizontalAccuracy - 10.0)) || (newLocation.horizontalAccuracy < 50.0)
|| ((attempts >= attempt) && (newLocation.horizontalAccuracy <= 150.0) && locationChanged)))
#endif
{
attempts = 0;
latitude = newLocation.coordinate.latitude;
longitude = newLocation.coordinate.longitude;
[currentLocation release];
currentLocation = [newLocation retain];
goodLocation = YES;
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateLocationNotification" object: nil];
if (oldLocation != nil) {
distanceMoved = [newLocation getDistanceFrom:oldLocation];
currentSpeed = newLocation.speed;
distanceTimeDelta = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp];
}
}
// Send the update to our delegate
[self.delegate newLocationUpdate:currentLocation];
}
Jeśli masz iPhone 3GS aktualizowanie Nagłówek jest dużo łatwiejsze, oto kod w tym samym module jak wyżej:
//This is the Heading or Compass values
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
if (newHeading.headingAccuracy > 0)
{
[newHeading retain];
// headingType = YES for True North or NO for Magnetic North
if(headingType) {
currentHeading = newHeading.trueHeading;
} else {
currentHeading = newHeading.magneticHeading;
}
goodHeading = YES;
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateHeadingNotification" object: nil];
}
}
Hope this helps ludzie!
Wielka kod. Ale, jak zaznaczono w poniższej odpowiedzi, metoda ta mogła zająć dużo czasu: doupdateToLocation: do ognia. Próbowałem i próbowałem i niezależnie od tego, widzę raczej powolne aktualizacje, gdy jestem w środku - czasami zajmuje to minutę lub dłużej. Jeśli jednak przejdę na Maps.app, natychmiast znajdzie moją lokalizację. Szkoda, że nie możemy uzyskać takiej samej natychmiastowej dokładności za pośrednictwem interfejsu API, co w przypadku MapKit. – runmad
Zastanawiam się, dlaczego sprawdza "UseLocations" w domyślnych ustawieniach użytkownika? Czy ta wartość jest automatycznie ustawiana przez system operacyjny? – nonamelive
Świetny kod. Po ustawieniu locationChanged = YES, instrukcja if powinna używać || zamiast &&. Jeśli zmienił się lat lub lon, zmieniła się lokalizacja. –