Aplicación de iOS para Abades con gestión de datos en Google App Engine

Detalles de la aplicación para iOS

¿Para qué sirve?

  • Proporciona información de los establecimientos del Grupo Abades
  • Muestra las últimas noticias, promociones, eventos y tweets de las redes de la empresa
  • Se pueden conseguir puntos de Abades, con un número de puntos suficiente, el usuario puede canjear estos por regalos que cada establecimiento pone a disposición de clientes que los frecuentan.

 

Funcionalidades de la aplicación

1.- Información de los establecimientos de la empresa:

El proceso de funcionamiento de la aplicación del Grupo Abades es el siguiente: hay una caché de días en los que la base de datos no se actualiza a menos que el usuario lo requiera. La primera vez que se arranca este número de días y otros parámetros de configuración se ponen a 0, por lo que si entramos en el listado de establecimientos de un tipo: áreas de servicio, hoteles o restaurantes, se descargará de Google App Engine, los datos que se han guardado en el modelo de datos del servidor por los empleados de la empresa en formato XML y se insertarán en la base de datos local en alrededor de un minuto. A partir del momento en que se almacenan estos datos hay 6 dias en los que no se vuelven a actualizar al ser datos de un tipo distinto a las promociones/eventos, noticias o ficheros,  se mantienen actualizados con otra frecuencia distinta.  En el caso de ser una imagen, la primera vez que se descarga se guarda en una caché (* nota programadores: de ASIDownloadCache), que hemos visto en los cursos de programación de este blog, entonces se almacenarán durante el número de días configurado, 31 por defecto, ya que son más estables y no deberían cambiar a menudo. Veréis que hay mucha info que aparece en la aplicación que es replicada en la web, sin embargo hay secciones como los puntos de sitios de interés que es más completa en esta aplicación de iOS. Las subsecciones de esta funcionalidad son las  siguientes:

  1. Información:  es una réplica de la información de un establecimiento, dispone de un texto introductorio para colocar sobre el mapa, el título del establecimiento, su imagen en miniatura, una descripción ampliada junto con la información de los servicios que ofrece y las estrellas o rango establecido en función de lo que sea.
  2. Situación:  sólo abrir la pestaña de situación de un establecimiento encontraremos la posición GPS en el mapa de Google Maps para iPhone. De hecho, si pinchamos sobre la chincheta roja aparecerá un cartel indicando el nombre del establecimiento, su rango y su localización exacta de longitud y langitud en formato de coordenadas geodésicas de gmaps. El botón a la derecha con signo más (+) indica la posición actual del usuario y el de la flecha a la derecha (>) hace que el mapa se posicione donde se encuentra el establecimiento. Por último, sin pinchamos en el icono de información (i) aparece un menú para seleccionar un sitio de interés relacionado con la posición del establecimiento, al seleccionar uno de estos sitios, el mapa “volará” hasta su posición y colocará allí una chincheta violeta, esta, muestra un cartel con el nombre y un botón al pinchar sobre ella, este botón nos muestra un recuadro de información sobre el sitio de interés, que contiene un texto con enlaces que se abrirán en el navegador Safari para ampliar la información, calcular nuestra ruta,etc. El botón de la flecha nos llevará a la aplicación de Google Maps de iPhone para mostrarnos todos los establecimientos de la empresa y poder calcular rutas o realizar cualquier otra operación con dicha aplicación.
            
  3. Imágenes: al pinchar sobre la pestaña aparecería una galería de imágenes con sus respectivos títulos en la parte superior de la ventana, los botones anterior (|< ) y siguiente ( >| ) permiten navegar con transiciones por las distintas imágenes disponibles. El botón de Play ( |> ) hace que comience la reproducción de imágenes en secuencia, hasta que volvamos a pulsar sobre la imagen una vez. Si mantenemos el dedo presionado sobre la imagen unos segundos o pulsamos sobre el icono de compartir ( []=> ) aparecerá un menú que nos brinda la opción de poder guardar la imagen en nuestra galería de imágenes. Si se ejecuta una doble pulsación, agrandaremos la imagen y el gesto de peñizcarla además modificará su tamaño. Podemos arrastrar la imagen por la pantalla o girar el dispositivo para verla con una disposición distinta.
            
  4. Contacto:  esta sección de información de un establecimiento consiste en proporcionar al cliente toda la información referente a aquel, ya sea el teléfono, la web o el email con sus respectivos botones para acceder a estas funcionalidades, hasta la dirección, Fax y por último más información sobre el emplazamiento.
  5. Mediante el uso del botón refrescar en el listado de establecimientos podemos recargar manualmente los datos de la base de datos de estos.
  6. Las opciones de configuración de la aplicación para caché de imágenes, bases de datos, GPS, segundos entre cada pase de imágenes, y otras están en la aplicación de Ajustes de iOS -> Grupo Abades

2.- Promociones y eventos:

los empleados de la empresa, a través de la herramienta web de administración de promociones, colocan en abades.com y sus otras webs una lista de promociones, esta lista es accesible por medio de un fichero XML,tal como en la funcionalidad anterior se almacena una caché temporal de estas que permite visualizar una lista con títulos, centros y una imagen asociada, al pinchar sobre cualquiera de ellas entraríamos en la presentación de la imagen de la promoción ampliada, un texto descriptivo de la misma así como la información de contacto: teléfono, web, mail, etc. Su fecha y el centro de emplazamiento de la promoción o el evento.
     

3.- Mi cuenta en Abades:

Esta sección de la aplicación se utiliza para crear una cuenta con la que poder reunir puntos y reservar, con el fin de,  luego, canjear regalos, que ofrece la empresa a sus clientes, agradeciendo la estancia de estos en sus establecimientos. Lo primero que debemos hacer es entrar en Mi cuenta -> Crear Cuenta , rellenar los datos de: e-mail, contraseña y tu nombre y pulsar en el botón “Crear Cuenta“. Hecho esto nos llegará un e-mail de activación en el que debemos buscar un enlace para activar la cuenta en la aplicación de google app engine. Una vez activada nuestra cuenta, podemos rellenar los datos en “Mi cuenta -> Tengo Cuenta”  y pinchar en “Entrar con mi cuenta“, si todo ha ido bien aparecerá una ventana con los datos de tu cuenta, e-mail, nombre y puntos abades.
Estos puntos se consiguen por medio de checkins usando una cuenta de Foursquare. Es un requisito fundamental ya que todos los establecimientos se encuentran asociados a la cuenta de foursquare. Ahora pincharemos en el activador ON/OFF de Foursquare e introducimos nuestro usuario (email/teléfono) y password de esta red. Al pinchar aceptar debe aparecer un botón “Cerrar sesión“, lo cual nos indica que hemos iniciado la sesión correctamente, podemos usar el icono de cerrar (x) para volver a los datos de nuestra cuenta y ahora el indicador on/off estará activado, ya podemos hacer checkins desde el Mapa de la aplicación.

4.- Mapa:

Esta funcionalidad de la aplicación del Grupo Abades se utiliza para colocar todos los establecimientos de la empresa sobre el mapa y poder encontrar el que esté más próximo a nosotros con objetivo de realizar un checkin (estoy aquí) y recibir los puntos que proporciona el establecimiento por hacerlo cada día.
Hay que tener en cuenta que el cálculo de la distancia se realiza en línea recta por lo que si queremos saber la verdadera medida de distancia para viajar al establecimiento debemos usar otro software de GPS, para eso podemos utilizar el botón Google Maps para ver las posiciones de los establecimientos sobre la aplicación Google Maps de iPhone y calcular una ruta óptima en coche, bici, transporte público o a pie desde nuestra posición actual. Sólo cargar el mapa aparece una chincheta roja y si pulsamos sobre ella veremos que refleja nuestra posición GPS actual,

     

tal como reza el cartel superior derecho de Latitud y Longitud. En este mismo cartel podemos controlar el nivel de zoom del mapa con el deslizador dispuesto a tal efecto. Otros controles útiles son el centrador de posición ,con el botón “Mi posición“,  tendremos actualizada nuestra posición en todo momento, centrando el mapa en esta cada cierto número de segundos. Los botones Mapa|Sat|Híb modifican el formato de visualización de aquel de mapa a satélite o híbrido (mezcla de los dos primeros). Ahora, usaremos el botón con fondo azul y un radar blanco para que la aplicación busque el establecimiento más cercano a nuestra posición (si es que hemos permitido a esta el uso de nuestra localización,claro), y se mostraría una ventana con el título “El sitio más cercano es:” y el título y los kilómetros de distancia, al aceptar observaríamos que el mapa ahora está posicionado con el centro en dicho establecimiento y que pinchando sobre el icono de chincheta de Abades ([a]) aparece un recuadro con el título, categoría y un botón para mostrar una ventana que contiene información del sitio y un botón para hacer Checkin.

    
Al hacer checkin la aplicación intentará conectar con el servidor enviando los datos de nuestra cuenta y si hemos configurado que se muestren nuestros checkins en foursquare y redes sociales twitter y facebook aparecerá un mensaje del tipo “Chekin desde la app de Abades en el establecimiento…., obteniendo … puntos” con la información correspondiente, en estas redes sociales y en una ventana de información que nos confirma que todo ha ido correctamente, con nuestro nuevo saldo de puntos de Abades, ahora podemos consultar nuestra cuenta ,de la funcionalidad anterior y asegurarnos de que efectivamente tenemos esa cantidad de puntos de la que nos han informado. Lógicamente un usuario sólo puede hacer uso de una cuenta de Foursquare, en el momento en que la cuenta se utiliza para hacer un checkin en otra cuenta que no es la suya se borrarán todos los regalos reservados y puntos asociados.En el momento de hacer checkin además seremos informados de las últimas ofertas exclusivas para Foursquare y el Grupo Abades.

5.- Noticias y tweets:

este módulo consiste en la lectura del RSS generado por Yahoo! Pipes pasado a través de Feedburner para gestionar social media de todas las últimas noticias de todos los blogs y webs de la empresa, se muestra un listado de las últimas novedades y al pinchar en una de ellas aparece un resumen,  con título y fecha, podemos leer la noticia ampliada en la misma ventana mediante el icono del mundo o bien abrirla en el navegador Safari por medio del botón de “enviar a”  ([]=>). La sección de tweets accesible desde el logotipo de la empresa es exactamente igual en cuanto a funcionamiento pero sólo de la red Tweeter.
            

6.- Sección de regalos:

quizás la parte más interesante para los clientes, pues reciben algo físico a partir de su acción virtual. Consiste en reunir puntos de Abades por medio de checkins en los distintos establecimientos de la empresa, y ,tras consultar el listado donde aparece con un scroll horizontal, los diferentes premios
 
que podemos conseguir con estos puntos, seleccionamos el que deseemos y lo reservamos, después nos dirigimos al establecimiento donde se encuentra dicho item reservado y lo canjeamos en el punto habilitado para ello. En caso de cancelación se devolverían los puntos a la cuenta.

Para programadores:

El Reto

El reto de esta app consistió en poder crear una herramienta que sincronizara los datos de la web actual (abades.com) con los demás dominios (abadestriana.com, abadesnevadapalace.com) y appspot.com, y después crear un algoritmo para hacer un checkin válido así como sincronizar todos los elementos RSS en un único canal y adjuntarlo al programa de promociones actuales de las webs (blogs, noticias, etc. para cada idioma, inglés y español).

¿Qué usa la aplicación?

  • Un conjunto de servicios webs habilitados en una aplicación en Google App Engine para rellenar el contenido de la base de datos SQLite que trae (populate) instalada.
  • API de Foursquare para hacer checkin (con twitter y facebook habilitados)
  •  CoreLocation de iOS para comprobar la distancia al establecimiento más cercano, enviando si las condiciones se cumplen, un mensaje encriptado al servidor de appspot que los comprueba y aumenta los puntos de la cuenta de usuario que está utilizando la app.

¿Cómo se hizo?

La programación empezó donde véis el artículo de como crear una aplicación productiva y social, el esquema era el mismo, pero había que añadirle toda la parte de programación de servidor, ya que la empresa necesita tener actualizada la información que se comparte con los dispositivos y sus webs, la opción de crear un algoritmo en PHP era tentadora pero una aplicación de móbil necesita una buena respuesta y un servidor web no es precisamente una máquina en la que uno desee confiar plenamente, es decir, no siempre está operativa 100% porque tiene muchos usuarios desde la web, por lo que opté por un servidor de google app engine y usando Java creé todas las estructuras de datos donde almacenar la información de establecimientos como en las guías de los cursos de este blog, después lancé los servicios web que permiten dar de alta todos estos datos, y que son capturados por los analizadores sintácticos de la aplicación móvil, más adelante configuré efectos gráficos, mejoré el diseño y añadí la API de Foursquare gracias a frameworks ya disponibles en la red.

El analizador sintáctico es NSXMLparser, el framework ASIHttp permite descargar imágenes con caché de forma síncrona o asíncrona, el scroll view de regalos usa una caché para poder crear todos los que hagan falta, el modelo de datos es sencillo, contiene elementos transformables para almacenar listas, estas listas en Google App Engine con DataStore son persistentes y embebidas en clases que permiten la serialización de objetos, etc.

En cuanto a los mapas no hay mucho que contar, es lo que se suele hacer, una clase para las anotaciones, se captura el evento del dibujado para dibujar un icono distinto e intercalar un botón en recuadro que se muestra al pulsar sobre una chincheta o anotación, y las animaciones están hechas con QuartzCore, es decir UVAnimation con cambios entre transiciones de opacidad, tamaño y posición,…lo sé ,aún se puede mejorar :)

Puedes descargar la aplicación desde su sección: aquí.

Aplicación para iPhone: Carta Astral

Esta aplicación surgió como un proyecto personal a partir de la necesidad de crear cartas astrales.

El reto comenzó con la forma en que se han realizar los cálculos de una carta astral. Por suerte, hay un software escrito en C, de los alemanes Dieter Koch and Alois Treindl y Astrodienst Zurich llamado SWISSEPH, conecté por consola ssh con mi servidor, utilicé wget con la última versión ( 1.76 ) y tras el make probé Swetest que a partir de una serie de argumentos de entrada muestra por pantalla un “ephemeris”, el resultado de leer una base de datos de posiciones de planetas, asteroides, estrellas, etc. y devolver las posiciones para cada una de las casas de dicha fecha y hora en el lugar especificado por longitud y latitud.Este programa además lanza una serie de datos para generar gráficas como “spreadsheets”.

Usando estos datos y un pequeño script:

//Analizar sintácticamente la fecha,hora,longitud y latitud
exec ("swetest -edir../src/ -b$utdatenow -ut$utnow -p0123456789
-eswe -house$longitud,$latitud, -fPlj -g, -head", $salida);
 foreach ($salida as $key =&gt; $linea)
      {
        $row = explode(',',$linea);
        $pl_name[$key] = $row[0];
        $longitude[$key] = $row[1];
        $house_pos[$key] = $row[3];
      };

Donde cada línea de salida de swetest se divide en arrays $row, con los elementos:0 = planeta,1 = longitud,2 = posición de casa, planetas en 0 – 9, cúspides en 10 – 21. Los nombres de los componentes,empiezan por 0 = Sol, que es la estrella del sistema solar,junto con la Luna=1 y Mercurio = 2 hasta Plutón = 9, los símbolos serían del 1 = Aries hasta 12 = Piscis. Para asociar la longitud y latitud al signo se hace una regla de 30 que limita la longitud y la combina con la casa asociada que devuelve el programa, de esta forma, podemos generar una imagen con instrucciones de dibujado geométrico (círculos, líneas, símbolos como texto)…Podéis ver un ejemplo aquí.

Para generar textos más completos he utilizado webs que los devuelven gratuitamente a partir de los datos, como grupovenus.
Finalmente, con un script en Python dentro de Google App Engine se crean todas las consultas en segundo plano, se construye el XML con HTML+CSS embebido, imágenes, etc. y se guardan, previo análisis sintáctico mediante la clase NSXMLParser en la base de datos SQlite asociada al Modelo de Datos, tal como vimos en los cursos.

Las animaciones de la app: las transiciones están hechas en OpenGL (HMGLTransition) y con las clases CAAnimation. El menú giratorio es una extensión de la clase UIGestureRecognizer ( KTOneFingerRotationGestureRecognizer ) modificada adaptando cada sección a un ángulo con una animación UIView…

Para la base de datos, primero se genera el modelo de datos, luego se compila y ejecuta la aplicación para que el mismo SDK cree el fichero SQlite así, tenemos la base sobre la que insertar los datos, una vez hemos rellenado todas las tablas, copiamos el fichero sqlite al proyecto y con un código como este:

 

NSString *storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:
 @"Carta_Astral.sqlite"];
 
// Set up the store.
// For the sake of illustration, provide a pre-populated default store.
 
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn’t exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle]
pathForResource:@"Carta_Astral" ofType:@"sqlite"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath
toPath:storePath error:NULL];
}
}

la primera vez que se ejecuta la aplicación, se copia al directorio de Documentos y ahí es donde se graban los datos del usuario, hago especial énfasis en que los tipos de datos complejos como Arrays de imágenes, textos y nombres se guardan en un tipo de dato del Modelo de Datos de Cocoa llamado Transformable.

En la sección de manuales hay tres tipos de manuales, los vídeos de youtube que se cargan sobre un objeto WebView, los textos con imagen que se cargan sobre una vista a mano y los pdf’s que se descargan a una caché con ASIHttp DownloadCache…Para paginar todos los documentos, libros, vídeos he usado una clase que crea un número infinito (gracias Andreas Katzian) de ScrollViews y los guarda en una caché de vistas para no tener que ir generándolos cada vez que se cambia de página, de forma que sólo se consulta una vez a la base de datos, se guarda una caché de tuplas y luego una caché de vistas con sus correspondientes botones, etc., así es mucho más eficiente y sencillo.
Para compartir textos e imágenes se utilizó ShareKit.

Veréis que las barras de navegación y las barras botones (tab) tienen una textura de fondo, esto se hace sobrecargando la clase correspondiente, en concreto el método de dibujado, para hacer que pinte una imagen por debajo y luego el resto del contenido.

La aplicación está siendo desarrollada

Conexión de la interfaz con el código fuente: XCode + Interface Builder | Objective C

Conexión de la interfaz con el código: aplicaciones de iOS

Un poco de teoría: Diseño de la aplicación

Guía de estilo para la interfaz de usuario: PDF.

MVC & Eventos

  • El patrón de ingeniería del software Modelo-Vista-Controlador actúa en base a clases que tienen la forma: el Modelo define las estructuras de datos, la Vista las ventanas, widgets, etc. que interactúan por medio de los Controladores que unifica los dos anteriores y en sus acciones determina cómo manejar los eventos.
  • Estos eventos pueden ser de varios tipos: un gesto (o gesture: secuencia de eventos desde que el usuario toca la pantalla hasta que deja de hacerlo), toque (touch: el dedo está en la pantalla) y el clásico click o tap que es cuando el usuario toca la pantalla por un instante. A los eventos se les captura por medio de una cadena de clases UIResponder,

    que responden una a una, esto se logra con la herencia (subclases de UIView, UIControl,etc.)

    siendo la primera de las instancias que responden la que interactúa con el usuario. Lo que se hace una vez despachado el evento por el primer Responder es redirigirlo al siguiente respondedor a mano con la función “nextResponder”.
  • Podemos controlar los eventos de tipo Touch, siendo estos pertenecientes a una vista sobrecargando la función “touchesBegan”, capturando así el inicio de la interacción:
    – (
    void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSUInteger
    numTaps = [[touches anyObject tapCount;
    NSUInteger
    numTouches = [touches count;
    }

    Podéis seguir investigando con métodos como touchesMoved, touchesEnded y touchesCancelled. Con locationInView obtenemos la posición del touch.
    Más información >
  • Tipos de gestos: swipe (sigue la acción del usuario en un eje determinado, puede implicar dragging o arrastrar y soltar –UIPanGestureRecognizer-) -> UISwipeGestureRecognizer, tapping (cualquier número de toques) -> UITapGestureRecognizer, pinching (acercar o alejar dedos para zoom por ejemplo),  rotating (mover dedos en direcciones opuestas) -> UIRotationGestureRecognizer y long press (tocar y mantener) -> UILongPressGestureRecognizer. Todas estas clases reconocedoras son utilizables por medio de la declaración de una clase (entre paréntesis) asociada a la ventana UIWindow (que está asociada a una UIApplication al mismo tiempo) y hace posible la gestión de estos eventos:
    Los posibles estados con sus transiciones:
    Evidentemente ,un gesto contínuo lanzará varios eventos para poder hacer un seguimiento del mismo, mientras que uno discreto sólo tendrá un evento.
  • Los eventos de movimiento están encapsulados por el objeto CMAccelerometerData que guarda en una estructura la aceleración sobre cada uno de los ejes espaciales. CMGyroData guarda datos sobre la velocidad y CMDeviceMotion encapsula varias medidas, incluyendo la postura, rotación y aceleración. El acelerómetro se ha de configurar antes de usarse, con la clase UIAccelerometer definimos los parámetros.
  • La orientación se obtiene con la clase UIDevice invocando el método beginGeneratingDeviceOrientationNotifications, hay un begin y un end para gestionar la secuencia.
  • El tipo de eventos que necesitan recoger información de los sensores del giroscopio y el acelerómetro deben ser los primeros en responder por lo que usamos la función canBecomeFirstResponder de una vista y si tenemos permiso entonces activamos con beginReceivingRemoteControlEvent,y desactivándolo cuando no se use la vista con resignFirstResponder.
  • Éste es el ciclo de vida de una aplicación, podemos ver como se enmarca la gestión de eventos justo en mitad del loop de eventos:

Recordemos MVC

  • El modelo encapsula el estado de la aplicación, contiene los datos, notifica de cambios, etc. La vista representa en pantalla los modelos, pide actualizaciones de estos, envía gestos al controlador, permite al controlador seleccionar una vista, etc. Y el Controlador define el marco de la aplicación, selecciona una vista para la respuesta a una petición, etc.

    ahora la versión de Cocoa:
    si combinamos el MVC con la aplicación, el modelo de datos y las vistas de cocoa junto con los controladores, esto es lo que obtenemos:
    Con este patrón podemos separar el código en función de lo que hace.
  • Como hemos visto, los controladores no deciden totalmente lo que hacer con las vistas sino que son estas las que les dicen cuáles pueden utilizar, lo cual no es totalmente un patrón MVC sino Modelo-Vista-Presentación, aquí tenéis el esquema real del funcionamiento actual de una aplicación en iOS:

    que se puede ver así representado :
      

    Leer más acerca de la diferencia entre MVC y MVP »

Conexión del constructor de interfaces (I.B.) con las vistas: los controladores de las vistas y los modelos

Controladores de las Vistas

Sabemos que una instancia de una clase controlador tiene la lógica que une los datos de un modelo de una aplicación con las entidades visuales usadas para presentarlos al usuario en el dispositivo. En iOS ,los controladores de las vistas o View Controllers, son objetos que heredan de la clase genérica de Objective C llamada UIViewController. Gracias a los controladores de las vistas definimos el comportamiento de las interfaces de usuario, podemos encontrar tres tipos de controladores de vistas:

  • Custom View Controller: para representar a “nuestra manera” la información, es algo más personalizado; se usa en listas de elementos, presentaciones de estos, propiedades, etc. ( ejemplos: de un UITableViewCell -> UIViewController)
  • Container View Controller: sirven para embeber dentro a otros controladores de vistas, definiendo relaciones de navegación entre ellos, suelen utilizarse de forma automatizada los que trae el sistema por defecto (ejemplos: UITabBarController, UINavigationController), establecen relaciones entre controladores
  • Modal View Controller: describen las relaciones entre controladores y cómo modifican la representación de los datos, puede ser utilizado por cualquier controlador (en realidad es un modo de funcionamiento, la ventana modal, que no permite continuar con el resto de la aplicación hasta que se ha cerrado la vista/ventana modal)

Por dónde empezar

  • Hemos visto que los eventos se gestionan en mitad del ciclo de vida de una aplicación, lo que pasa antes y después se puede controlar por medio del denominado “Application Delegate”, que no es otra cosa que los eventos que ocurren antes ,durante y después del inicio de una aplicación. XCode genera por defecto los archivos {nombre_proyecto}AppDelegate.h y .m que contienen el código que se ejecuta cuando la aplicación se lanza y finaliza, aprovecharemos estas funciones para cargar datos, inicializar componentes, etc. Luego sólo cargar la aplicación, este es el esquema de funcionamiento de iOS:
    una vez cargada, puede pasar al estado en segundo plano, de modo que quedaría así:
    si,ahora es cuando deberíamos programar los eventos de la clase {loquesea}ApplicationDelegate para  descargar memoria o realizar tareas de sincronización mientras trabaja en segundo plano…ya hablaremos de eso más adelante en el capítulo de multitarea…podéis leer más acerca de la implementación de funciones en el marco común de comportamiento de la aplicación aquí. Ahora debemos reemplazar el esquema de ciclo de aplicación que vimos antes en los eventos por el nuevo esquema en segundo plano:
    y si aún no os queda muy claro, podéis echar un vistazo a este esquema:
    sacado de cocoanetics: understanding iOS 4 Backgrounding and delegate messaging

Creación de interfaces con el Interface Builder

Conceptos básicos

  • Las interfaces se guardan en ficheros .XIB que es un XML y puede editarse a mano aunque para eso está el editor visual :)  Cuando se compilan se genera un NIB que puede usarse para inicializar una vista.
  • La manera en que utilizamos los widgets, ventanas, vistas y demás objetos en el código es a través de un outlet (llamado IBOutlet en el código), tenemos que definir una variable con este apóstrofe y luego el tipo que sea, normalmente se llaman UI___ por lo que es fácil distinguir las clases de la interfaz. Al posponer la palabra clave IBOutlet a una variable no modifica ni su contenido ni su comportamiento, pero avisa al compilador y al I.B. de que puede ser conectada a un objeto de interfaz incluído en el XIB asociado a dicha clase
  • Para definir acciones, es decir, funciones que se puedan activar a través de un evento generado por un elemento de la interfaz (de una vista), utilizamos las bien denominadas IBAction en el código, en este caso el prefijo que se utiliza para definir una función es como un tipo de dato, por lo que si afecta a la declaración de una función ( y no se pueden utilizar dos tipos seguidos en la declaración, recordemos Objective C ) . IBAction indica al editor de interfaces que la función se utiliza por objetos para eventos concretos, como pueda ser, pulsar un botón o cualquier otro…

Interface Builder: ¿qué es?

  • Editor que provee de una paleta de objetos para el interfaz de programación con Objective C
  • Objetos asociados: cada .xib tiene una clase asociada, este objeto dentro de la ventana de edición de interfaz se llama “File’s owner”, y si recordamos lo que era el first responder, pues este objeto representa al que el usuario tiene asociado para interaccionar, lo mismo pasa con View, que es la vista principal de la clase. Para realizar las asociaciones usamos el botón derecho del ratón y arrastrando y soltando asignamos los outlets y actions que hayamos definido en el código ( Ver ejemplo de asociación )

    …simple
  • Gracias a la ventana de la biblioteca de objetos podremos arrastrar y soltar los widgets, vistas, etc. que necesitemos y por medio del inspector editamos los atributos de estos, podemos escribir una clase que luego sea la que controle un objeto (aquí la definimos)

Ejercicio:

Escribe un proyecto nuevo View-Based, abre la vista principal y crea una label, desde el código crea una asociación con un atributo -> propiedad con el prefijo IBOutlet, asóciala en el I.B. y luego en el evento de recién cargada la aplicación (appdelegate -> didlaunch with options) accede a dicho objeto de la interfaz para establecer el texto “Hola mundo”, algo sencillo, puedo corregírtela si me la envías en el formulario de contacto.

<< Volver al curso de programación de aplicaciones de iOS

Siguiente: Persistencia de datos en iOS y Google Web Toolkit (Google App Engine) >>

Curso de creación de aplicaciones para iOS (iPhone-iPad-iPod)

Este curso es para aquellos que están empezando a diseñar sus propias aplicaciones o expertos que desean realizar tareas más complejas.
El contenido del curso:

  1. Introducción al IDE de XCode, Objective C e iOS
  2. Conectar código con interfaz: patrón Modelo Vista Controlador
  3. Persistencia de datos en iOS y Google App Engine (GWT) – Servicios Web – XML – Modelo de datos
  4. Configuración y traducción de una aplicación de iOS
  5. Geolocalización con MapKit de Google y CoreLocation y Multitarea

Se irán añadiendo más contenidos conforme se vaya desarrollando el curso…

Introducción al IDE de XCode, Objective C e iOS

Curso de creación de aplicaciones de iOS

Hardware y Software que “nos exigen”

  • OSX (Snow Leopard al menos) actualizado a la última versión, para poder instalar el IDE de la manzanita. Nos quieren obligar a comprarnos un Mac, peeero, también podéis instalaros el VMWare Fusion  en un PC (o el VMWare normal pero sin soporte OpenGL), u Oracle VM VirtualBox sobre Windows o GNU/Linux y descargar una imagen de OSX de la red para este software-emulador, e incluso…crearos un Hackintosh, que no es muy caro y están de moda jeje
  • XCode 4 + iPhone SDK: podéis descargarlo de Internet si no tenéis dinero para la licencia de developer, aunque si queréis publicar pronto una aplicación podéis daros de alta en el programa de desarrolladores de la empresa, pagando claro!…
  • iPhone/iPad/iPod: pues hombre, estaría bien  tenerlo para poder probar lo que escribamos, ya que el simulador (no es un emulador!) que trae el IDE se comporta de manera algo distinta a como debería ser…pero bueno, para empezar tampoco vamos a tirar la casa por la ventana jeje Si tienes un dispositivo intenta instalarte el AppWizard para el siguiente paso -no te diré como conseguirlo-

Hardware de los dispositivos iOS

  • El iPhone 4 tiene una resolución de pantalla de 960×640 a 326 ppi.
  • El iPhone 3 tiene una resolución de 480×320 píxels
  • La resolución del iPad es de 1024×768 a 132 ppi

Habilidades que necesitamos para programar aplicaciones de iOS

  • Programar en Objective C: programar aplicaciones de iPhone en XCode es, básicamente, empezar a conocer cómo funciona Objective C y cómo asociar los objetos del Interface Builder a nuestro código. Para eso existen cientos de tutoriales, algunos más famosos que otros como “Masters of the Void“, pero lo mejor es seguir un libro gratuito de la propia empresa (en el apartado de desarrolladores) o ir a una biblioteca y pillarse libros como Objective C for dummies, iPhone application development for dummies, y luego algo más serio como iOs4 Programming Cookbook de O’Reilly, ya que contienen multitud de ejemplos y trucos para desarrollar todo lo que deseemos/necesitemos.
  • Hay un libro de la web de MacProgramadores bastante bueno sobre Objective C con especial énfasis en su origen (NeXT) y XCode, lo han borrado de la web, pero seguro que lo encontráis…

Introducción a XCode e iOS4 SDK

Conceptos básicos:

XCode

  • Xcode es el IDE que nos ofrece Apple para desarrollar aplicaciones de iOS.
  • El SDK (Software Development Kit) incorpora herramientas para el desarrollo (entre ellas, el simulador de iPhone/iPad).
  • El lenguaje de programación es Objective-C
  • Simulador de iOS: Permite simular tanto iPhone como iPad en nuestro Mac.
  • Interface Builder: Editor visual para diseñar interfaces de usuario para nuestras aplicaciones.
  • Instruments: Herramienta de análisis que nos ayuda a optimizar y monitorizar la aplicación

Sistema Operativo iOS

  • El Sistema Operativo de los dispositivos de Apple (iOS), está formado por un conjunto de capas, que conforman el conjunto de servicios ofrecidos por el dispositivo. Arquitectura:
  • Cada capa de la arquitectura está compuesta por un conjunto de frameworks
  • La capa Core OS es la base del sistema operativo. Se encarga de realizar la gestión de memoria, el sistema de ficheros, conexión a la red y procesos que interactúan con el hardware
  • Core Services nos permite el acceso a los servicios básicos, tales como la agenda, el acceso a la base de datos, preferencias, conexión a servidores y procesamiento de URLs, etc…
  • La capa Media nos permite la ejecución de tareas multimedia. Entre ella el acceso al Audio, OpenGL, Imágenes y PDF, Animaciones, etc…
  • Cocoa Touch nos permite acceder al acelerómetro, los eventos y controles táctiles, la jerarquía de vistas, alertas, etc…gestiona la interacción visual con el usuario
  • Novedades de iOS4:
  • Multitarea: mientras ejecutamos una aplicación, al pulsar el botón “home” no se cierra sino que pasa a segundo plano, pueden continuar ejecutándose o pueden suspenderse
  • Notificaciones Locales: completa el sistema de notificaciones push (desde un servidor remoto que nosotros mismos podemos crear)
  • Core Motion: conjunto de interfaces para acceder a toda la información basada en el movimiento (giroscopio ,motion-based)
  • Data protection: sistema integrado de encriptación
  • Soporte para pantalla de alta resolución (adaptación a la antigua)

Frameworks

  • Un framework es un conjunto de librerías que nos permite añadir una funcionalidad concreta a nuestra aplicación
  • Por defecto, cuando creamos un proyecto, tenemos los frameworks esenciales para el funcionamiento básico
  • Por ejemplo, para usar bases de datos SQLite usaremos su framework, simplemente con copiar el directorio descargado de su web, aunque en la versión de XCode4 ya viene integrado, también haremos lo mismo con Cocos2D
  • Cocoa Touch: conjunto de frameworks orientados a objetos que permiten el desarrollo de aplicaciones nativas para iOS

Crear una aplicación

Pasos

  1. Abrir XCode y crear un proyecto
  2. Diseñar la interfaz de usuario
  3. Escribir el código asociado de la aplicación
  4. Compilar, ejecutar y probar (vuelta al paso 2)
  5. Medir y ajustar el rendimiento de la aplicación
  6. Producir y publicar la aplicación

Tipos de proyecto

  • Cocos 2d: para crear juegos (necesita el framework Cocos2D),lo veremos en otro curso, de programación de videojuegos para iPhone
  • Navigation-based : presentan la información de forma jerárquica usando múltiples vistas (diseño de pantallas)
  • Open GL : igual que cocos, además de juegos podemos crear cualquier tipo de aplicación que represente imágenes, animaciones o gráficos 3D
  • Split View-based : Aplicaciones enfocadas para iPad que muestran más de una vista en la pantalla al mismo tiempo (un control listado y una vista detalle de elementos normalmente)
  • Tab Bar : presentan una interfaz de “radio” que permite al usuario elegir entre varias opciones
  • Utility : aplicaciones que presentan una vista principal y permiten que el usuario acceda a otra vista para realizar personalizaciones básicas
  • View-based : una vista simple para implementar la interfaz
  • Window-based : plantilla universal (cualquier dispositivo con iOS) que sirve de punto de partida con un delegado y una ventana. Útil para aplicaciones con jerarquía propia

Recordar que no todos los tipos de aplicaciones pueden ser universales (para cualquier iDevice) y las que lo son tienen diferentes diseños de interfaces de usuario en subdirectorios con su nombre.

Interfaz de XCode

XCode4: editor en una ventana

XCode4: Interface Builder

XCode4: Git integrado

Tipos de ficheros de un proyecto

  • Info.plist: como todos los plist, es un XML (introducido por NeXT) constituído de propiedades de configuración en UTF-8
  • Ficheros.h: declaraciones de interfaces ,clases y atributos
  • Ficheros.m: implementación de clases y métodos definididos en los .h (aunque no necesariamente requieren un .h)
  • Ficheros .pch: cabeceras precompiladas que se añaden a las clases
  • Ficheros de objetivo: resultado de la compilación de un conjunto de ficheros de código, puede ser una librería o una aplicación. Un conjunto de objetivos forman un producto. Lo utilizaremos para publicar una aplicación en la tienda

Perfiles de compilación

  • Depuración: incluye la opción de depuración al compilar con gcc, es más lenta pero encuentra errores lógicos. Se puede depurar en el editor de texto, mini-depurador, depurador y en la consola [(gdb)]. Opción: GCC_GENERATE_DEBUGGING_SYMBOLS. Podemos usar breakpoints.
    Mientras el programa está siendo depurado podemos modificarlo (como pasaba en VisualBasic y otros lenguajes! :D) : cambiar el nº y tipo de argumentos de una función o método que esté en la pila,el tipo del valor de retorno o el nombre de una  función o método también en la pila, así como cambiar el tipo de las variables estáticas, un fichero NIB, añadir clases o cambiar sus métodos…
    Leer más >
  • Lanzamiento: mayor rendimiento de la app, tamaño de objeto final compilado menor.
  • Distribución: como el anterior pero necesita un certificado o firma de Distribución válida (con apple hemos topado xD, aunque podemos arreglar esto con algún que otro truco de Cydia…). Se añade meta-información necesaria para ser validada en la tienda.

Introducción a Objective C

¿Qué es?

  • Pequeño set de extensiones de ANSI C
  • Sus añadidos a C están basados en Smalltalk, uno de los primeros lenguajes orientados a objetos
  • Diseñado para dotar a C de toda la potencia de la orientación a objetos

Clases

  • Sintáxis normal de creación de clases: interfaz (.h) + implentación (.m)
  • Ejemplo de clase Persona.h:
    @interface Persona : NSObject {
    NSString *nombre;
    NSString *apellidos;
    }
    -(NSString*) nombre;
    -(NSString*) apellidos;-(void) setNombre: (NSString *) _Nombre;
    -(void) setApellidos: (NSString *) _Apellidos;
     
    +(NSString *) soyMetodoEstatico: (NSString *)  mensaje;
    @end

    Ejemplo de clase Persona.m:

    #import "Persona.h"
    @implementation Persona
    -(NSString*) nombre {
    return self.nombre;
    }
    -(NSString*) apellidos {
    return self.apellidos;
    }
    -(void) setNombre: (NSString *) _Nombre {
    self.nombre = _Nombre;
    }
    -(void) setApellidos: (NSString *) _Apellidos{
    self.apellidos = _Apellidos;
    }
    +(NSString) soyMetodoEstatico: (NSString *) mensaje{
    return mensaje;
    }
    @end
  • Ejempo de función que toma datos de la clase padre de la que hereda:
    - (id) init {
    if ( self = [super init] ) {
    [self setNombre:@"nombre por defecto"];
    [self setApellidos:@"apellidos por defecto"];
    }
     
    return self;
    }

    self es la propia instancia del objeto y super es la clase de la que hereda

  • Declaración de un método:
  • A través del corchete accedemos a un objeto, que es el primer parámetro, el segundo es la llamada al método, es como hacer
    $this->método en PHP , o puntero_a_clase -> método , en C / C++,Java.
    Por ejemplo , un método sin entrada

    [object method];

    Con entrada:

    [object methodWithInput:input];

    Con salida:

    output = [object methodWithOutput];

    Con entrada y salida:

    output = [object methodWithInputAndOutput:input];
  • Recordar que si queremos especificar una función con varios parámetros se ponen dos nombres, uno para el nombre clave de llamada y otro para el nombre interno del parámetro, el primer nombre de nombre clave no se pone, ejemplo:
    -(void) miFuncion: (int)parametro1 nombre1: (bool) parametro2 nombre3:(NSString*) parametro3;
    a esta función accedemos así, ejemplo con datos:
    [miObjeto miFuncion:7 nombre1:true nombre3: @”cadena”
    Fijaros que una cadena siempre se precede de una arroba.
  • Propiedades de una clase: (@property)
    permiten generar automáticamente métodos de acceso para los atributos de una clase, podemos sobrecargar los métodos setter & getter si no usamos las especificaciones por defecto de una propiedad, para saber cuál nos conviene primero debemos ver la gestión de memoria. Por defecto, el setter se añade automática a la propiedad definida como setNombre_variable (set+UCase(nombre_variable)), y el getter es el nombre de la variable atributo tal cual, en Persona.h el setter es setNombre y el getter nombre. Fácil.
    Para que podamos usar las propiedades es obligatorio inicializarlas con @synthesize en Persona.m (la implementación de la clase),este genera los setters y getters automáticamente. Una vez hecho además podemos especificar en esta línea de sintetización el nombre local del acceso o accesser, algo como @synthesize nombre = _nombre_local;
  • Ver más >

Gestión de memoria!: de lo más importante en Objective C

  • Con el método dealloc liberamos memoria utilizada en las instancias de nuestras clases, lo vamos a sobrecargar para hacer “release” de todas las instancias de objetos que hayamos creado
  • Se debe liberar por completo el propio objeto también ,con [super dealloc] .
  • Debemos liberar las variables de tipado fuerte
  • Para aprovechar la memoria tenemos que crear nuestro propio “recolector de basura”, algunos ven esto como muy buena idea y otros no son partícipes de que el lenguaje no tenga las bondades de Java…
  • Para gestionar qué variables están siendo utilizadas en memoria, tenemos lo que se llama el “contador de referencia” de Objective C, sólo tenemos que especificar qué hacer con las variables al asignarlas, crearlas, copiarlas, pasarlas por parámetro, etc. y la ejecución del programa hace el resto.
  • Con alloc inicializamos memoria en función del tipo o clase de una variable, por ejemplo, cuando declaramos una variable de tipo NSNumber con una instrucción como esta:
    NSNumber *number = [[NSNumberalloc initWithFloat:8.75;
    lo que pasa internamente es que el contador de referencias se pone a 1.
  • Con retain aumentamos el contador de referencias en uno, por ejemplo si deseamos liberar en un contexto la variable pero no queremos que se pierda la variable porque se usa en otro contexto, por ejemplo:
    -(
    void) setNombre: (NSString *) _Nombre {
    [self.nombre
    autorelease;
    self.nombre = [_Nombre
    retain;
    }
    Usando autorelease se libera al objeto de manera diferida, es decir, es posible usar la variable de la primera línea durante un tiempo más, le dice al compilador que la variable self.nombre se decremente al salir del contexto de la clase de la función setNombre, después le asigna un nuevo valor, el del parámetro, pero a este le dice que lo retenga aunque se borre fuera, para que sea gestionado desde la clase.
  • Con release se decrementa el contador en una unidad, si tiene valor 1 ,se borra la variable, es decir, le decimos al sistema que no la necesitamos y éste llama a dealloc automáticamente (primer punto)
  • Ojo entonces, si por ejemplo creamos un método en una clase para asignar un valor y hacemos que use release para luego hacer retain con el nuevo valor que le pasamos, siendo este no una variable sino una llamada de una función, algo así:
    ________
    – (
    void) setNombre: (NSString*) _Nombre {
    [self.nombre
    release;
    self.nombre = [_Nombre
    retain;
    }


    persona
    * ego = [[personaalloc init];

    [ego
    setNombre:[ego nombre];
    ________
    al llamar a la función setNombre, primero se libera el objeto self.nombre antes de retenerlo, por lo que ya no hay espacio reservado en memoria para esta variable y aquella pasa a estado incoherente ya que el valor que le hemos pasado es precisamente el que hemos liberado, para solucionarlo ponemos autorelease en lugar de release.
  • Ahora podremos saber qué tipo de gestión de memoria asignarle a una propiedad, por ejemplo para el nombre en nuestra clase Persona.h:
    @property (retain) NSString* nombre;
    al poner retain hemos declarado que el setter (función como setNombre pero automática) debe hacer retain sobre el valor de entrada. Pero podemos especificar con setter=setNombre nuestra propia función ;)
  • A veces tenemos que tener cuidado con lo que liberamos de la memoria, no podemos dejar todo en autorelease porque al pasar la referencia de una variable entre funciones es posible que se libere antes de tiempo, sin embargo de esto nos daremos cuenta cuando el simulador haga CRASH! jaja

Variables

  • Tipado débil: int, bool, float, etc.
  • Tipado fuerte: objetos como NSString, NSNumber, etc.
  • ejemplos de métodos con tipos distintos:
    - (int) multiplica: (int)a por:(int)b {
    return a * b;
    }
     
    - (NSString *) cadenaResultado: (int)resultado {
    NSString *res = [NSString stringWithFormat:@"El resultado es: %d", resultado];
     
    return res;
    }
     
    int resultado = [self multiplica:2 por:3];
    NSString *cadena = [self cadenaResultado:resultado];
    NSLog(@"%@", cadena); //devuelve 6
  • Un protocolo (@protocol) permite que la lista de métodos que contienen se puedan implementar por cualquier clase, puede especificarse al crear una clase en su definición de la clase que hereda de otra…
    @protocol MyProtocol
    - (void)requiredMethod;
    @optional
    - (void)anOptionalMethod;
    - (void)anotherOptionalMethod;
    @required
    - (void)anotherRequiredMethod;
    @end
     
    @interface ClassName : ItsSuperclass < protocol list >
  • Otro método para depurar es usar el log, la función NSLog(cadena) usa el mismo formato que un printf, recordar el formato:

    NSLog(@”La fecha y hora actual es %@”, [NSDatedate );

XCode Organizer

  • Una vez creada la aplicación, si queremos usarla en un iDevice, tenemos que desplegarla (necesita certificado), conectar el dispositivo por USB y probar! Pero también podemos usar el simulador ,aunque no refleja el comportamiento exacto (real) de la aplicación si que sabremos si funciona o no :)

Consejos

Diseñar como un ingeniero y producir como un artista: echad mano de vuestro amigo el arquitecto de información para encontrar la mejor manera para guardar los datos,… no es lo mismo una base de datos en SQLite que un conjunto de ficheros XML.

  • Hay que conocer el flujo de la información en el sistema de aplicaciones, por ejemplo un sistema de etiquetas debe ser recurrente en cuanto a que hay tags que se repiten, la forma óptima de hacer esto es como lo hace WordPress o algunas aplicaciones web si lo prefieres. Debemos consultar a nuestro amigo experto en marketing para el nombre del programa, así será el dominio para publicarlo, también nos aconseja qué tipo de características son viables en cuanto a lo que el público demanda y nos da su perspectiva como experto lo bonito, barato y bueno. Efectivamente, necesitamos conocer cómo construir diagramas pero no son indispensables, aunque sería ideal diseñar previamente la app con UML
  • Beta tester: antes de empezar si quiera a pensar en querer programar algo para iOS ,lo primero que debemos hacer es conocer los dispositivos, el iOS y OSX, todos los widgets del sistema operativo, así que al menos tenemos que haber probado todas las aplicaciones antes mencionadas, aunque sea en el ifón de un amigo, no vale haberlo visto en vídeo, tenemos que tocar la esencia de la magia de esta tecnología para sentir qué queremos hacer realmente.

Otros tutoriales para conocer el IDE XCode 3: nos sirve para empezar.

Ahora que conocemos el IDE de la mano de Noemi gracias a sus tutoriales de Youtube, vamos a seguir un poco más adelante, tenemos la ayuda necesitamos aquí:

Ejercicios (Deberes :)

  1. Ejercicio 1: crear un proyecto tipo “View-based”, crear una clase Persona y otra clase Usuario, establecer propiedades en las clases asociadas a sus atributos, una clase Usuario debe tener un atributo que sea una clase Persona.
  2. Ejercicio 2: Crear un NSArray e inicializarlo con clases NSNumber, luego mostrarlo con NSLog
  3. Ejercicio 3: Crear un NSMutableArray e inicializarlo con clases Persona, añadir  a dicha clase la función (sobrecargada) description para que NSLog pueda mostrar el contenido de todos sus atributos

Para corregirlo podéis enviármelo con el formulario de contacto.

<< Volver al curso de programación de aplicaciones de iOS

Siguiente: conectar interfaz con el código

Aplicaciones para MAC con XCode y SQLite

He estado realizando en los últimos meses algunas tareas para clientes, tanto extranjeros (de Grecia) como locales y aquí van algunos consejos a raíz de las experiencias que he tenido tras la investigación del IDE XCode y del Snow Leopard.

Ahora os muestro un vídeo con un ejemplo sencillo de lo que se puede hacer con Objetive C de XCode de Apple y SQlite, creación de una base de datos, una tabla y dos tuplas para luego mostrarla en un objeto de Cocoa:

Lo primero, para diseñar interfaces y escribir código hay que descargarse las herramientas, esto es, la última versión de XCode y las Developers Tools, así podremos compilar el código que escribamos asociado a las interfaces.

Para poder tener un almacén de datos exportable y que se pueda utilizar en cualquier plataforma (iPhone,iPod, PC, MAC,etc) usaremos SQLite, y para comunicar este motor con XCode usaremos el framework FMDB (del cual hay una versión específica para iPhone/iPod) ,esto es tan fácil como descargarse el framework y copiar los ficheros, después se crea una clase base de datos como esta:

#import 
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
 
#define FMDBQuickCheck(SomeBool) { if (!(SomeBool)) {
 NSLog(@"Failure on line %d", __LINE__); return 123;
 } }
 
@interface bd : NSObject {
	FMDatabase *fmdb;
 
}
- (void) crearBD;
@end

La implementación:

#import "bd.h"
 
@implementation bd
 
- (void) crearBD {
 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 fmdb = [FMDatabase databaseWithPath:
   @"/Users/juaxix/Documents/miBD.sqlite"];
 if (![fmdb open]) {
	NSLog(@"No se pudo abrir la base de datos.");
	[pool release];
	return NULL;
 }
 return self;
}
 
-(NSMutableArray*) seleccionSQL:(NSString*)sql{
	FMResultSet *rs = [fmdb executeQuery:sql, @"hi'"];
	NSMutableArray  *datos = [[NSMutableArray alloc] init] ;	
    while ([rs next]) {
        // just print out what we've got in a number of formats.
       /* NSLog(@"%d %@ %@ %@ %@ %f %f",
              [rs intForColumn:@"c"],
              [rs stringForColumn:@"b"],
              [rs stringForColumn:@"a"],
              [rs stringForColumn:@"rowid"],
              [rs dateForColumn:@"d"],
              [rs doubleForColumn:@"d"],
              [rs doubleForColumn:@"e"]);
        */
 
        if (!([[rs columnNameForIndex:0] isEqualToString:@"idu"] &&
              [[rs columnNameForIndex:1] isEqualToString:@"usuario"])
			) {
            return 7;
        } else {
         NSString *cadena = [NSString  stringWithFormat:
         @"idu: %d usuario:%@ ",[rs intForColumn:@"idu"],
         [rs stringForColumn:@"usuario"]];
	 NSLog( cadena );
	NSMutableArray *aux = [[NSMutableArray alloc] init];
	[aux addObject:[NSString stringWithFormat:@"%d",
	[rs intForColumn:@"idu"]]];
	[aux addObject:[NSString stringWithFormat:@"%@",
	[rs stringForColumn:@"usuario"]]];
	[aux addObject:[NSString stringWithFormat:@"%@",
	[rs stringForColumn:@"email"]]];	
	[datos addObject:aux];
       }
    } 
    [rs close]; 
	return datos;
}
 
@end

Ahora que tenemos la base de datos debemos crear un controlador para asociar las acciones de la Interfaz al código fuente, algo sencillo como esto:

#import 
#import "bd.h"	
 
@interface controlador : NSObject {
	IBOutlet NSTableView *tablaDatos;
	bd *mi_bd;
}
- (IBAction)cargarDatos:(id)sender;
@end

esta es la implementación

#import "controlador.h"
#import "bd.h"
#import "personas.h"
 
@implementation controlador
- (IBAction)cargarDatos:(id)sender {
	if (!mi_bd){
	 mi_bd = [[bd alloc] init] ;
	 [mi_bd crearBD];
	}
	NSMutableArray *datos = [mi_bd seleccionSQL:
              @"select * from usuarios"];
	if (datos){
	 //Ahora vamos a meter los datos en el objeto
	personas *p = [[personas alloc] init];
	[p meterDatos:datos];
 	[tablaDatos setDataSource:p];
 
	}
}
@end

Como hace falta una clase que le de los datos a la vista de tabla (el datagrid) he creado una llamada personas:

#import 
 
@interface personas : NSObject {
	NSMutableArray *datos;
}
-(void) meterDatos:(NSMutableArray*)kdatos;
- (int)numberOfRowsInTableView:(NSTableView *)tableView;
- (id)tableView:(NSTableView *)tableView
 objectValueForTableColumn:(NSTableColumn *) tableColumn row:(int)row;
@end

esta clase implementa las acciones que necesita este tipo de objeto para representar la información y poder acceder a los datos…

#import "personas.h"
 
@implementation personas
-(void) meterDatos:(NSMutableArray*) kdatos {
  datos = kdatos;
}
- (int)numberOfRowsInTableView:(NSTableView *)tableView{
 return	[datos count];
}
 
- (id)tableView:(NSTableView *)tableView 
   objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
	id value =nil; //creamos un objeto
	NSString *identifier =[tableColumn identifier]; 
	NSMutableArray *aux  =[datos objectAtIndex:row];
 
	/*creamos un objeto de la clase que queremos listar y 
          le asignamos el valor de la fila en la que estamos*/
	if ([identifier isEqual:@"id"])
		value=[aux objectAtIndex:0];
	else if ([identifier isEqual:@"nombre"])
		value=[aux objectAtIndex:1];
	else if([identifier isEqual:@"email"])
		value=[aux objectAtIndex:2];
	else NSLog("No encuentro el valor");
	NSLog([aux objectAtIndex:0]);
	return value;
}
 
@end

y básicamente ya lo tenemos todo, el main es una línea:

#import 
#import "bd.h"
 
#import "controlador.h"
 
int main(int argc, char *argv[])
{
 
    return NSApplicationMain(argc,  (const char **) argv);
}

footer
jbelon © | sitemap.xml