Si recordáis, el mes pasado vimos cómo acceder a los datos estáticos de un dispositivo iOS para conocer sus principales características hardware y software, así como el nivel de batería o la orientación de la pantalla. Todo eso está muy bien para utilizar el dispositivo como si de un ordenador se tratara, pero estaríamos desperdiciando la gran característica del cacharro: su movilidad.
Así pues, si antes accedíamos a la denominada información estática del dispositivo, ahora vamos a aprender cómo disponer de la información dinámica, aquella que varía continuamente y que nos viene a mostrar cómo se está moviendo. Básicamente, nos van a interesar dos datos:
-
Cómo se mueve el dispositivo con respecto a sus propios ejes, tanto en dirección como en velocidad. Estos datos nos los ofrecen los acelerómetros internos.
-
Dónde se encuentra el dispositivo en el plano de la superficie terrestre, dato que se obtiene a partir del GPS u otro tipo de triangulaciones.
Datos de aceleración
Gracias al acelerómetro integrado en los dispositivos iOS y al giroscopio presente desde el iPhone 4, podemos conocer prácticamente cualquier movimiento que el aparato esté realizando. Gracias a ello, podemos utilizar estos movimientos como nuevos datos de entrada, lo que es especialmente útil en juegos, aunque también en aplicaciones de texto, donde una sacudida del teléfono haga las veces de Ctrl+Z, en reproductores donde podamos pasar de canción con un movimiento de muñeca, etc.
Lo fundamental es que debemos tener en cuenta que esta información no se nos da como la estática, que era una especie de fotografía del estado actual del móvil. Ahora debemos mantener presente la componente temporal que va implícita en el movimiento, ya que no es lo mismo un giro de 90º realizado en un segundo (lo que sería bastante suave), que uno realizado en 100 milisegundos (que sería mucho más brusco).
Por ello, a la hora de acceder al objeto UIAccelerometer
, debemos establecer el tiempo de muestreo con el que queremos que se nos ofrezca información de aceleración, así como el delegado al que se pasará esta información. Por defecto, el intervalo de actualización será de 100 veces por segundo. Si nuestra aplicación requiere medir movimientos muy precisos (como por ejemplo las aplicaciones de detección de terremotos), será necesario que forcemos al dispositivo a realizar mediciones con más frecuencia, pero hay que tener cuidado, ya que éste puede ser uno de los grandes enemigos de nuestra batería.
De este modo, si queremos que el delegado que se encargue de tramitar la información de la aceleración sea un ViewController
, en la carga del mismo debemos establecer las dos propiedades:
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0 / constFrecuenciaMuestreo]; [[UIAccelerometer sharedAccelerometer] setDelegate:self];
Fijaos que establecemos un intervalo de actualización que es un tiempo muy pequeño, por lo que lo normal será definirlo como uno partido por la frecuencia por segundo que queremos obtener, en lugar de usar un número con muchos decimales.
Ahora, cada vez que se produzca un movimiento, nuestro delegado recibirá un mensaje donde se le pasa el acelerómetro y un objeto UIAcceleration
que contendrá las tres componentes espaciales del movimiento, llamados con el propio nombre de los ejes. El eje X recorre la pantalla del dispositivo de izquierda a derecha, el eje Y desde abajo a arriba y el eje Z desde atrás hacia delante, tal y como podéis ver en este esquema.
El valor de cada una de las variables se corresponde con la aceleración en ese eje, medida como múltiplo de G, la aceleración de la gravedad en la Tierra. Por tanto, con el móvil quieto, apoyado sobre el dorso, X e Y valdrán 0 y Z valdrá -1 (está atraído hacia el suelo con una aceleración de una G = 9.81 m/s2).
Del mismo modo, el iPhone 4 y posteriores incorporan un giroscopio que de forma independiente a la aceleración, es capaz de informarnos acerca de rotaciones producidas en torno a los mismos ejes. Su uso ha hecho que el método delegado didAccelerate
se empiece a desaconsejar con la llegada de iOS 5, recomendándose el uso del CoreMotion Framework
. Así, el uso del giroscopio es casi idéntico al del acelerómetro, siendo CMGyroData
la clase que contiene los valores de la rotación en los ejes X, Y, Z.
Información de geoposicionamiento
Aunque no todos los dispositivos iOS tienen GPS, las versiones de iPhone anteriores al 3G pueden geoposicionarse basándose en la situación de las antenas de telefonía, e incluso gracias a las redes WiFi accesibles, que serán el único medio disponible en los primeros iPod Touch. Es más, si el dispositivo posee las tres tecnologías, puede usar la que considere más precisa en un momento dado, siendo prácticamente transparente para el programador.
Y digo lo de casi transparente porque el CoreLocation Framework
no sólo nos informa de cuándo ha cambiado nuestra posición, sino también de cuándo hay disponible una señal nueva o mejor. En cuanto a los datos proporcionados, no sólo se envían las coordenadas en 2D, sino que son todos los siguientes:
-
Latitud y longitud, así como la precisión vertical y horizontal aproximada de dicha medición.
-
Altitud, y su precisión vertical.
-
Hora en la que se determinó la última posición medida.
-
La posición anterior.
Para empezar a recibir las notificaciones, sólo hay que crear una instancia del objeto CLLocationManager
, y configurar dos valores: distanceFilter
, la distancia mínima en metros para la que queremos que se nos notifique, y desiredAccuracy
, el nivel de precisión que deseamos, dependiendo del tipo de uso que le vamos a dar (no es igual la precisión que queremos en un navegador GPS que en una aplicación que sólo va a tomar la ciudad donde te encuentras). Tras esto, invocamos a startUpdatingLocation
y empezaremos a recibir las notificaciones mediante el método didUpdateToLocation:fromLocation
de nuestro delegado.
CLLocationManager *gestorLocalizacion = [[CLLocationManager alloc] init]; [gestorLocalizacion setDistanceFilter:10]; [gestorLocalizacion setDesiredAccuracy:kCLLocationAccuracyBestForNavigation]; [gestorLocalizacion setDelegate:self]; [gestorLocalizacion startUpdatingLocation];
Si queremos ahorrar batería, es importante no empezar a acaparar datos hasta que realmente los necesitemos, e invocar a stopUpdatingLocation
en cuanto dejemos de necesitarlos, ya que el GPS consume batería a raudales.
Por último, hay que tener en cuenta que el usuario puede desactivar el permiso de localización para nuestra aplicación, o que la señal puede ser mala, por lo que es importante el manejo que se haga del error que se nos notifique mediante el segundo método del delegado, didFailWithError
. Si no hay error, pero la señal es pobre, podemos usar un timer no muy grande y escuchar todas las mediciones que se realicen antes de que éste venza, para entonces tomar como dato bueno el que más precisión horizontal y vertical nos pueda ofrecer.
Guías de referencia |UIAccelerometer, UIAcceleration, CMGyroData, CLLocationManager, CLLocationManagerDelegate Código de ejemplo | Gráfico del movimiento del dispositivo con los acelerómetros, Localización y desplazamiento del dispositivo Más información | Programar del GPS del iPhone para obtener las coordenadas del dispositivo