Tengo una aplicación que gira en torno al GPS del dispositivo y la información que proviene de él. Es importante que los datos de ubicación sean precisos y estén actualizados. Sé que el dispositivo está limitado por su GPS y los límites del GPS, pero me preguntaba si hay algo que pueda hacer para modificar/mejorar el rendimiento del iPhone GPS, particularmente en el área de velocidad. Debido a que las actualizaciones de ubicación se retrasan de 3 a 5 segundos detrás de la ubicación en tiempo real del dispositivo, la velocidad informada por el administrador de ubicación también está muy por detrás del valor en tiempo real. En mi caso, eso es simplemente demasiado largo. Entiendo que quizás no haya nada que pueda hacer, pero ¿alguien ha tenido éxito en mejorar la capacidad de respuesta del iPhone GPS? Cada poco hace la diferencia.Capacidad de respuesta de CLLocationManager
Edición 1:
Mi manager ubicación es dentro de una clase Singleton, ya que Apple recomienda.
Dentro SingletonDataController.m:
static CLLocationManager* locationManager;
locationManager = [CLLocationManager new];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.headingFilter = kCLHeadingFilterNone;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) {
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
} else {
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
[sharedSingleton setLocationManager:locationManager];
[locationManager release];
Dentro MapView.m (donde se utiliza en realidad el jefe de locación):
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
//setup
[SingletonDataController sharedSingleton].locationManager.delegate = self;
//more setup
}
- (void)batteryChanged {
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) {
[SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
} else {
[SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
}
- (void)viewDidLoad {
//setup
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(batteryChanged)
name:UIDeviceBatteryStateDidChangeNotification
object:nil];
//other setup
}
El manejo de datos ocurre en el interior locationManager:didUpdateToLocation:fromLocation:
. No creo que la ineficacia aquí sea la causa del retraso.
locationManager:didUpdateToLocation:fromLocation:
llama a este método para actualizar la interfaz de usuario:
- (void)setLabels:(CLLocation*)newLocation fromOldLocation:(CLLocation*)oldLocation {
//set speed label
if(iterations > 0) {
if(currentSpeed > keyStopSpeedFilter) {
if(isFollowing) {
[mapViewGlobal setRegion:MKCoordinateRegionMake([newLocation coordinate], mapViewGlobal.region.span)];
}
NSString* currentSpeedString;
if(isCustomary) {
currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (currentSpeed * 2.23693629f)];
} else {
currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (currentSpeed * 3.6f)];
}
[speedLabel setText:currentSpeedString];
[currentSpeedString release];
} else {
speedLabel.text = @"Not moving";
}
}
//set average speed label
if(iterations > 4 && movementIterations > 2) {
NSString* averageSpeedString;
if(isCustomary) {
averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (float)((speedAverages/(long double)movementIterations) * 2.23693629f)];
} else {
averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (float)((speedAverages/(long double)movementIterations) * 3.6f)];
}
[averageSpeedLabel setText:averageSpeedString];
[averageSpeedString release];
}
//set elapsed time label
NSInteger seconds = [[NSDate date] timeIntervalSinceDate:dataObject.locationManagerStartDate];
NSInteger minutes = seconds/60;
NSInteger hours = minutes/60;
//get remainder
seconds %= 60;
NSString* timeString;
NSString* secondsString;
NSString* minutesString;
NSString* hoursString;
if((seconds % 60) < 10) {
secondsString = [[NSString alloc] initWithFormat:@"0%i", seconds];
} else {
secondsString = [[NSString alloc] initWithFormat:@"%i", seconds];
}
if((minutes % 60) < 10) {
minutesString = [[NSString alloc] initWithFormat:@"0%i", minutes];
} else {
minutesString = [[NSString alloc] initWithFormat:@"%i", minutes];
}
if((hours % 60) < 10) {
hoursString = [[NSString alloc] initWithFormat:@"0%i", hours];
} else {
hoursString = [[NSString alloc] initWithFormat:@"%i", hours];
}
timeString = [[NSString alloc] initWithFormat:@"%@:%@:%@", hoursString, minutesString, secondsString];
[elapsedTimeLabel setText:timeString];
[timeString release], timeString = nil;
[secondsString release], secondsString = nil;
[minutesString release], minutesString = nil;
[hoursString release], hoursString = nil;
NSString* totalDistanceString;
if(isCustomary) {
totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f mi", (float)distance * 0.000621371192f];
} else {
totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f km", (float)distance/1000.0f];
}
[customTopBar setTitle:totalDistanceString];
[totalDistanceString release];
}
Con un par de NSDates y NSLogs he encontrado que la ejecución de la totalidad (no sólo el método de actualización etiqueta) locationManager:didUpdateToLocation:fromLocation:
nunca toma más de unos 8ms en mi iPhone 4; en otras palabras, el manejo de datos no es el problema.
Muestre cómo obtiene los datos de ubicación. Ese retraso no es normal. – sosborn
Código agregado. Puedo publicar más si es necesario. –
3-5 segundos puede ser un poco exagerado; es tarde y el rango 3-5 acaba de aparecer en mi cabeza por alguna razón. Mañana haré algunas pruebas para obtener los números exactos. –