abr 29

En este arículo/tutorial vamos a ver en detalle cómo obtener la posición GPS del iPhone, que problemas podemos tener durante la obtención de las coordenadas y cómo podemos solucionar estos problemas.

Primero de todo si queremos usar el GPS en nuestras aplicaciones tenemos que añadir el CoreLocation a nuestro proyecto. Para eso hacemos click derecho en el grupo “Frameworks” del nuestro proyecto y seleccionamos “Add > Existing Frameworks…”.

Esto nos abrirá la ventana para seleccionar el framework a añadir. Buscamos el “CoreLocation.framework” y lo añadimos al proyecto.

Con esto tenemos todo configurado para empezar a picar código que use el GPS.

En nuestro código tenemos que incluir las cabeceras de las funciones GPS:

#import <CoreLocation/CoreLocation.h>
#import <CoreLocation/CLLocationManagerDelegate.h>

asdad—————————————-

Para obtener las coordenadas tenemos que usar el “CLLocationManager” e implementar el protocolo “CLLocationManagerDelegate“.

El CLLocationManager se inicializaría así:

CLLocationManager *gpsManager = [[CLLocationManager alloc] init];
[gpsManager setDelegate:self];
[gpsManager setDesiredAccuracy:kCLLocationAccuracyBest];
[gpsManager startUpdatingLocation];

Con startUpdatingLocation decimos al location manager que empiece a leer del dispositivo GPS.

Ahora veamos los métodos del protocolo a implementar. Nuestro gpsManager llamará a estos métodos cuando obtenga coordenadas nuevas.

//Se llama cada vez que hay una nueva coordenada
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
    //Hacer algo con newLocation (mostrar la posición en el mapa o lo que sea
}
 
//Se llama cuando se produce algún error en la obtención de datos GPS
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
   if ([error code]==kCLErrorDenied)
       NSLog(@"El usuario ha denegado el acceso a GPS");
  else
       NSLog(@"Se ha producido algún error interno");
}

Con estos métodos ya tenemos todo para leer las coordenadas. En el parámetro newLocation del primer método nuestro “Location Manager” enviará las coordenadas nuevas y nosotros las usuaríamos para hacer X en nuestro programa.

El segundo método se lamará cuando haya algún error. El error puede ser debido a que el usuario haya denegado el acceso al GPS o por otro motivo (ver la documentación para ver los posibles constantes de error existentes).

Hasta aquí lo más básico.

En una aplicación real con sólo esto no sería suficiente.

El primer problema está en la precisión de las coordenadas obtenidas. A la que se pide al locaton manager que empiece a obtener coordenadas (stratUpdatingLocation) este comienza a enviar las coordenadas que obtiene mediante triangulación de las antenas de telefonía móvil y mientras tanto intenta sincronizarse con los satélites para obtener coordenadas más precisas.

Esas primeras coordenadas que obtiene pueden ser muy imprecisas (pueden a llegar a tener un error de más de 10Km) y muchas veces es mejor que nuestro programa los ignore para no engañar al usuario. Para eso en el método donde leemos las nuevas coordenadas tenemos que filtrar los que no tienen la precisión suficiente para nuestro programa.

Para eso se usa la propiedad horizontalAccuracy (que se da en metros) del nuestro objeto de  tipo CLLocation.

Veamos un ejemplo:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
	//Si el error de la nueva coordenada es mayor o igual a 100 metros usar la coordenada
	if (newLocation.horizontalAccuracy &lt;= 100.0 ){
               ;//Usar la nueva coordenada
	}
 
}

Con esto solucionamos el posible problema que pudieramos tener con la precisión.

Otro problema que puede haber tiene que ver con la cache de coordenadas que mantiene el sistema operativo.
El location manager nos puede enviar, al principio, coordenadas que ha obtenido hace muchas horas. Entonces también tenemos que controlar eso si queremos tener siempre datos frescos. Para eso tenemos que medir el tiempo que ha pasado desde que se ha obtenido una coordenada. El método anterior con este arreglo se quedaría así:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
        //Obtenemos la fecha de obtención de la coordenada
	NSDate* newLocationeventDate = newLocation.timestamp;
 
        //Obtenemos el tiempo (en segundos) que ha pasado desde que se obtenido nuestra coordenada
	NSTimeInterval howRecentNewLocation = [newLocationeventDate timeIntervalSinceNow];
 
        //Si el error es menor u igual a 100 metros y la coordenada se ha obtenido en los útlimos 20 segundos
	if (newLocation.horizontalAccuracy &lt;= 100.0 &amp;&amp; howRecentNewLocation &lt; -0.0 &amp;&amp; howRecentNewLocation &gt; -20.0){
		;//Usar coordenada
	}
 
}

Con esto solucionamos el problema de la cache. Pero hay un detalle más a tener en cuenta y es que puede que el GPS manager nunca llegue a obtener las coordenadas con la precisión que queremos nosotros y hacer que nos quedemos a esperar a esa coordenada para siempre.
Para eso se ha de programa un timer. No voy a explicar detalles de como programarlo pero la idea consiste en que un timer llame a un método pasado N segundos (nuestro timeout definido para el gps). Ese método que se ejecutará N segundos después y comprobará si en esos N segundos se ha obtenido alguna coordenada si es que si entonces no hay problema, si es que no, entonces debería notificar al usuario o a algún subsistema del programa que deje de esperar al gps o que cambie la precisión requerida o cualquier otra cosa más que se nos ocurra.
Aquí va un pseudocódigo:

...
[NSTimer scheduledTimerWithTimeInterval: 13.0 target:self selector:@selector(gpsTimeOut:) userInfo:nil repeats: NO];
...
-(void) gpsTimeOut: (NSTimer *) theTimer {
	if ([self seHaObtenidoCoordenada] != YES){
               //Hacer lo que sea si en 13 segundos no se ha obtenido una coordenada
       }
}

Con esto cerramos este minitutorial sobre el uso de GPS. Si tenéis preguntas no dudéis en formularlos en los comentarios.

VN:F [1.9.8_1114]
Rating: 5.0/5 (5 votes cast)
VN:F [1.9.8_1114]
Rating: +4 (from 4 votes)
Tagged with:
preload preload preload