J'ai eu beaucoup de problèmes avec CLLocationManager sur l'iPhone aussi. De différentes applications, et des essais et erreurs, c'est ce que j'ai compris;
1) Utilisez une classe singleton pour le LocationManager, une seule instance, suivre les exemples:
exemple Apple LocateMe
Tweetero: http://tweetero.googlecode.com/svn/trunk
Je pense que vous ne pouvez avoir qu'un Le gestionnaire de localisation fonctionne, il n'y a qu'une seule puce GPS dans l'iPhone, donc si vous lancez plusieurs objets du gestionnaire de position, ils entreront en conflit, et vous obtiendrez des erreurs du gestionnaire de localisation GPS indiquant qu'il ne peut pas mettre à jour.
2) Soyez extrêmement prudent lorsque vous mettez à jour le locationManager.desiredAccuracy
et locationManager.distanceFilter
Suivez l'exemple dans le code d'Apple pour cela dans le FlipsideViewController:
[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet;
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet;
Cette approche fonctionne et ne provoque pas d'erreurs.Si vous mettez à jour le desiredAccuracy ou distanceFilter dans la boucle principale délégué:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
Lieu Core se plaindra probablement qu'il ne peut pas mettre à jour les valeurs, et vous donner des erreurs. En outre, utilisez uniquement les constantes pour le desiredAccuracy
fourni par Apple, et pas d'autres, ainsi;
kCLLocationAccuracyBest, kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometers
L'utilisation d'autres valeurs peut vous donner des erreurs de LocationManager. Pour distanceFilter
vous pouvez utiliser n'importe quelle valeur, mais sachez que les gens ont déclaré avoir des problèmes, la valeur par défaut est: -1 = Meilleur, j'ai utilisé 10.0 et il semble OK.
3) Pour forcer une nouvelle mise à jour, appelez la méthode startUpdates
comme dans Tweetero, cela force locationManager à le faire, et il devrait essayer de vous donner une nouvelle valeur.
4) La routine de délégation de l'emplacement de base est délicate pour obtenir des mises à jour précises. Lorsque votre application initialise d'abord vous pouvez être hors de précision de 1000 mètres ou plus, donc une tentative ne va pas le faire. Trois tentatives après l'initialisation vous donne généralement à 47 mètres ou plus, ce qui est bon. Rappelez-vous que chaque tentative successive prend pour prendre de plus en plus de temps pour améliorer votre précision, et qu'elle devient rapidement chère. C'est ce que vous devez faire: Prendre une nouvelle valeur seulement si elle est récente ET Si le nouvel emplacement a une précision légèrement meilleure prendre le nouvel emplacement OU Si le nouvel emplacement a une précision < 50 mètres prendre le nouvel emplacement OU Si le nombre de tentatives a dépassé 3 ou 5 ET la précision < 150 mètres ET l'emplacement a CHANGÉ, alors ceci est un nouvel emplacement et le dispositif déplacé alors prenez cette valeur même si sa précision est pire. Voici mon code d'emplacement pour ce faire:
- (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];
}
Si vous avez un iPhone 3GS obtenir Heading des mises à jour est beaucoup plus facile, voici le code dans le même module que ci-dessus:
//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 gens!
code Grand. Mais comme les notes de réponse ci-dessous, il peut prendre beaucoup de temps pour didUpdateToLocation: à feu. J'ai essayé et essayé et peu importe, je vois des mises à jour plutôt lentes quand je suis à l'intérieur - parfois cela prend une minute ou plus. Cependant, si je passe à Maps.app, il trouve instantanément ma position. Je souhaite que nous puissions obtenir la même précision instantanée à travers l'API qu'avec MapKit. – runmad
Je me demande pourquoi il vérifie "UseLocations" dans les valeurs par défaut de l'utilisateur? Cette valeur est-elle définie automatiquement par le système d'exploitation? – nonamelive
Bon code. Lorsque vous définissez locationChanged = YES, l'instruction if doit utiliser || au lieu de &&. Si le lat ou le lon a changé, l'emplacement a changé. –