Ce n'est pas vraiment un algorithme définitif, parfait (je doute qu'il y en a une pour cette tâche, en raison des conditions extérieures, je veux dire, vous pouvez obtenir ur emplacement sur le terrain plaine ou dans une tombe), c'est un ad hoc, et ça marche pour moi.
J'ai fait un wrapper pour LocationManager, comme
@protocol LocationManagerWrapperDelegate <NSObject>
@required
- (void) locationUpdated: (CLLocation *) locationUpdate;
- (void) errorOccured: (NSError *) error;
@end
@interface LocationManagerWrapper : NSObject <CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
id delegate;
CLLocation *mostAccurateLocation;
int updatesCounter;
BOOL m_acceptableTimePeriodElapsed;
}
@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) CLLocation *mostAccurateLocation;
@property (nonatomic, assign) id <LocationManagerWrapperDelegate> delegate;
- (void) startUpdatingLocation;
- (void) locationManager: (CLLocationManager *) manager
didUpdateToLocation: (CLLocation *) newLocation
fromLocation: (CLLocation *) oldLocation;
- (void) locationManager: (CLLocationManager *) manager
didFailWithError: (NSError *) error;
+ (LocationManagerWrapper *) sharedInstance;
@end
mise en œuvre
#define NUMBER_OF_TRIES 4
#define ACCEPTABLE_TIME_PERIOD 15.0
- (void) startUpdatingLocation
{
NSAssert(self.delegate != nil, @"No delegate set to receive location update.");
updatesCounter = 0;
self.mostAccurateLocation = nil;
m_acceptableTimePeriodElapsed = NO;
[NSTimer scheduledTimerWithTimeInterval:ACCEPTABLE_TIME_PERIOD
target:self
selector:@selector(acceptableTimePeriodElapsed:)
userInfo:nil
repeats:NO];
[self.locationManager startUpdatingLocation];
}
- (void) acceptableTimePeriodElapsed: (NSTimer *) timer
{
@synchronized(self)
{
m_acceptableTimePeriodElapsed = YES;
// TODO: if period is set by user - check we have mostAccurateLocation at this point
[self.delegate locationUpdated:self.mostAccurateLocation];
[self.locationManager stopUpdatingLocation];
}
}
- (void) locationManager: (CLLocationManager *) manager
didUpdateToLocation: (CLLocation *) newLocation
fromLocation: (CLLocation *) oldLocation
{
@synchronized(self)
{
if (m_acceptableTimePeriodElapsed) return;
NSLog([NSString stringWithFormat:@"lat: %@, long: %@, acc: %@",
[ [NSNumber numberWithDouble:newLocation.coordinate.latitude] stringValue],
[ [NSNumber numberWithDouble:newLocation.coordinate.longitude] stringValue],
[ [NSNumber numberWithDouble:newLocation.horizontalAccuracy] stringValue] ]);
updatesCounter++;
// ignore first returned value
if (updatesCounter <= 1) return;
if (self.mostAccurateLocation == nil ||
self.mostAccurateLocation.horizontalAccuracy > newLocation.horizontalAccuracy)
{
self.mostAccurateLocation = newLocation;
}
if (updatesCounter >= NUMBER_OF_TRIES)
{
[self.delegate locationUpdated:self.mostAccurateLocation];
[self.locationManager stopUpdatingLocation];
}
}
}
Le code n'est pas excellent (ni formatage), mais l'idée, je pense, est simple et claire, Obtenez le premier emplacement, jetez-le, c'est un caché, faites 3 essais maximum pour un endroit le plus précis. Cela peut prendre beaucoup de temps, et si l'utilisateur attend (comme dans mon cas), définissez une limite de temps. Une fois de plus, cela fonctionne pour mon application, mais n'hésitez pas à la modifier ou à adopter une autre approche.
ok c'est plus ou moins ce que j'ai trouvé aussi. Je ne l'ai pas enveloppé dans une classe mais il semble que j'ai couvert tout ce que vous avez mis en œuvre. Merci pour une réponse. – morgman
@morgman vous pouvez voter alors;) – fspirit