- filtrare cache (vecchi) dati di posizione,
- filtrare validi spilli risultati (accuratezza < 0),
- Set requisito precisione impostato
kCLLocationAccuracyBest
,
- impostare un filtro distanza minima, preferibilmente almeno 10 metri per filtrare il rumore di posizione.
- MODIFICA: Non calcolare la distanza quando lo
oldLocation
è nullo.
C'è altro che si può fare, ma questo dovrebbe funzionare a condizione di avere una buona orizonalità orizzontale (< 30m). Puoi filtrare i risultati di bassa precisione, ma dovresti tenere traccia della vecchia posizione, che è un po 'più complicata.
Aggiungi un NSLog (vedi sotto) in modo da poter scoprire cosa sta succedendo. Se non ottieni ancora buoni risultati, pubblica l'output di NSLog in modo che possiamo vedere cosa sta succedendo e aiutare di più.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow];
if (age > 120) return; // ignore old (cached) updates
if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates
// EDIT: need a valid oldLocation to be able to compute distance
if (oldLocation == nil || oldLocation.horizontalAccuracy < 0) return;
CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation];
NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
oldLocation.coordinate.latitude,
oldLocation.coordinate.longitude,
newLocation.coordinate.latitude,
newLocation.coordinate.longitude,
distance,
newLocation.horizontalAccuracy);
distanceMoved += distance;
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
}
- (void)viewDidLoad
{
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyBest;
locMan.distanceFilter = 10;
[locMan startUpdatingLocation];
isInitial = true;
distanceMoved = 0.0;
[super viewDidLoad];
}
EDIT per iOS6 se si voleva fare lo stesso usando didUpdateLocations: (in quanto il metodo di cui sopra è ora sconsigliato) la soluzione più semplice è quello di salvare semplicemente ogni posizione in una proprietà in modo che il prossimo aggiornamento si dispone la posizione precedente.Dichiarare una proprietà nella classe per tenere la oldLocation
:
@property (nonatomic, retain) CLLocation* oldLocation;
Poi nel metodo delegato di salvare ogni newLocation
per l'uso come oldLocation
per la prossima volta il metodo delegato si chiama:
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocations:(NSArray *)locations
{
CLLocation* newLocation = [locations lastObject];
NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow];
if (age > 120) return; // ignore old (cached) updates
if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates
// EDIT: need a valid oldLocation to be able to compute distance
if (self.oldLocation == nil || self.oldLocation.horizontalAccuracy < 0) {
self.oldLocation = newLocation;
return;
}
CLLocationDistance distance = [newLocation distanceFromLocation: self.oldLocation];
NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
self.oldLocation.coordinate.latitude,
self.oldLocation.coordinate.longitude,
newLocation.coordinate.latitude,
newLocation.coordinate.longitude,
distance,
newLocation.horizontalAccuracy);
distanceMoved += distance;
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
self.oldLocation = newLocation; // save newLocation for next time
}
Ho appena usato questo codice esatto, ma ho modificato il filtro della distanza su 1. Per qualche ragione, la mia distanza spostata inizia a -1. Ecco la mia uscita dopo aver camminato a circa 2m avanti: 2012-04-17 17: 58: 05.341 LocationManagerTest2 [422: 707] 0,000000/0,000000 a 39,856110/-74,940113 per -1m, precisione +/- 10 m 2012-04 -17 17: 58: 10.248 LocationManagerTest2 [422: 707] 39.856110/-74.940113 a 39.856165/-74.940107 per 6m, precisione +/- 50m 2012-04-17 17: 58: 11.248 LocationManagerTest2 [422: 707] 39.856165/- 74.940107 a 39.856223/-74.940010 per 10m, precisione +/- 50m Il DistanceMoved è uscito a circa 15m - decisamente troppo – bnasty
Ho provato a usare questo codice alcune volte prima e ho ottenuto risultati apparentemente accurati e alcuni erano lontani – bnasty
la distanza -1 è dove la tua oldLocation era 0, il che probabilmente significa che il parametro oldLocation era nullo. Dovrai aggiungere anche un assegno (vedi la mia modifica sopra). Non puoi aspettarti un'elevata precisione quando segnala che l'accuratezza è 50m !!! Ciò significa che il GPS non ha un segnale abbastanza buono, significa che la posizione riportata può essere disattivata di 50 metri in qualsiasi direzione. – progrmr