# Hola iOS: introducción a la plataforma iOS y el lenguaje Objective-C

## Introducción a iOS y al desarrollo en la plataforma

### iOS

* iOS está dividido en capas, como es habitual las capas superiores se apoyan en los servicios proporcionados por las inferiores.

  ![](/files/-LDGNaq1veXMvF7egKOA)
* **Cocoa touch**: contiene las funcionalidades de alto nivel, básicamente cuestiones relacionadas con el interfaz de usuario (*multitouch*, detección de gestos,…) pero también otras muy diversas: *Airdrop*, *Mapkit* para mostrar mapas en nuestra aplicacion, *iAd*, …
  * **Media**: contiene las tecnologías de video y audio, por ejemplo servicios de alto nivel como *Airplay* o APIs para gráficos 2D (*Core Graphics*) o animaciones (*Core animation*), gráficos 3D con OpenGL, procesamiento de audio (*Core audio*), …
  * **Core services**: contiene un conjunto de servicios básicos para las aplicaciones, por ejemplo la geolocalización, la concurrencia, el almacenamiento de datos con iCloud, SQLite o *Core Data* (para almacenar objetos de modo persistente),…
  * **Core OS** Funcionalidades básicas del sistema, como seguridad, control del *hardware* (*bluetooth*, accesorios externos, …).
* En nuestras aplicaciones podemos usar los servicios proporcionados por cualquiera de las capas, pero se recomienda intentar usar los de las capas superiores si es posible. Por ejemplo, Cocoa Touch ofrece la posibilidad de usar los interfaces estándares del sistema para listar o seleccionar contactos de la agenda en nuestras aplicaciones. De esta forma nuestra aplicación tendrá un interfaz uniforme y coherente con el resto.  Pero si necesitamos acceder a la información de contactos y queremos ofrecer un interfaz propio (o no necesitamos una interfaz) podemos usar las funcionalidades que nos ofrece la capa de “Core Services”.

### Desarrollo en iOS

* Para desarrollar aplicaciones en iOS empleamos un conjunto de lenguajes, herramientas de programación y librerías. A un nivel de abstracción algo más alto organizamos nuestro código siguiendo patrones de diseño software.
  * ***Frameworks***: lo que en muchas otras plataformas se denomina *librería*. En Objective-C consisten físicamente en una librería dinámica y un conjunto de ficheros auxiliares, básicamente cabeceras (`.h`)
    * **Lenguajes**: hasta junio del año pasado el único que estaba soportado de manera oficial era Objective-C, que usaremos al menos en los primeros módulos del curso. Ahora Apple también soporta un nuevo lenguaje: Swift.
    * **Herramientas**: la más importante es el IDE de Apple, Xcode, que se integra además con herramientas adicionales como *Instruments* para depuración y pruebas de rendimiento, el *Emulador* para probar nuestras aplicaciones, ….
    * **Patrones de diseño**: tanto los APIs de iOS como la propia arquitectura que deben seguir las aplicaciones hace un fuerte uso de determinados patrones de diseño. El más omnipresente es el Modelo-Vista-Controlador, pero hay algunos más (*delegation*, publish/subscribe,…).

## Introducción básica a Xcode

* Xcode es un IDE que nos sirve tanto para escribir el código de nuestra aplicación iOS como para
  * Diseñar la interfaz gráfica
  * Ejecutar pruebas unitarias y de rendimiento
  * Depurar el código
  * Gestionar el control de versiones
  * Distribuir la aplicación
* Áreas de trabajo: La pantalla de Xcode está dividida en 5 zonas:
  * Navegadores
  * Barra de herramientas￼
  * Editor
  * Utilidades
  * Área de depuración (inicialmente está oculta, y se muestra cuando se ejecuta la aplicación)

![Áreas de la ventana de XCode](/files/-LDGNaq6qhwiK30kaaTL)

* Vamos a crear una app que imprima “hola mundo” con `NSLog`, para
  * Escribir algo de código y compilarlo
  * Ver cómo se usa el emulador: cómo se ejecuta una aplicación y cómo se puede poner un *breakpoint* y depurar a nivel básico.

## Introducción a Objective-C y a las aplicaciones iOS con una aplicación de ejemplo

### Algunas características de Obj-C

* Es una extensión orientada a objetos de C
* Es mucho más dinámico que C++. Por ejemplo, se puede decidir el método a llamar en tiempo de ejecución, se puede definir una variable como un objeto de un tipo cualquiera (\`\`id\`\`\`).
* Todos los objetos se crean en memoria dinámica, las variables son referencias, al estilo Java, pero debemos explicitar que son punteros, al contrario que en Java.

  ```objectivec
    //Obj-C
    NSString* cadena;
    //Java
    String cadena;
  ```
* Se usan includes “al estilo C”, pero la sentencia `#import` impide automáticamente que el mismo fichero sea incluído dos veces, eliminando la necesidad de [*guardas de inclusión*](http://arco.esi.uclm.es/~david.villa/pensar_en_C++/vol1/apas07.html).
* No se usa la sintaxis OO clásica de `objeto.metodo(parametro)` sino otra mucho más atípica: `[objeto metodo: parametro]`
* La interfaz está separada de la implementación
* La gestión de memoria se puede automatizar, aunque no usa recolección de basura, sino *cuenta de referencias*

### La aplicación de ejemplo

Vamos a desarrollar una sencilla aplicación llamada **UADivino**. Podemos “preguntarle” algo en voz alta (que se pueda responder con *sí/no*) y al pulsar un botón la aplicación nos dará su respuesta.

Hacemos esta aplicación para ilustrar:

* Cómo es el Objective-C básico
* Qué estructura tiene el código de una aplicación iOS sencilla
* Cómo se comunica el controlador con el modelo y con la vista

### Modelo-Vista-Controlador

* Todas las aplicaciones iOS siguen este patrón de diseño
* Desde el punto de vista lógico nuestra aplicación se divide en tres componentes: modelo, vista y controlador
* El **modelo** es el núcleo de la aplicación, qué es
* La **vista** es el interfaz gráfico, cómo se presentan los datos
* El **controlador** se comunica con ambos haciendo de nexo de unión. Más tarde veremos los distintos mecanismos de comunicación que hay en iOS.
* Hay que tener claro que *vista y modelo no deberían comunicarse directamente*, siempre deberían hacerlo a través del controlador.

### Estructura de una aplicación iOS

* Para crear el nuevo proyecto 1. Iniciar la creación de nuevo proyecto desde la pantalla de bienvenida de Xcode: `Create a new Xcode project`

  ![Pantalla de inicio de Xcode 6](/files/-LDGNaqBcRlHi0bfIC7V)

  1. En el siguiente diálogo, que permite elegir plantilla, seleccionar la de “Single View Application”
  2. En la pantalla de opciones, elegir como se muestra:

![Opciones del proyecto](/files/-LDGNaqDUaRiQNI4KF7A)

> En Xcode 5, en esta pantalla se podía seleccionar un “prefijo” para las clases. En Objective C no hay *namespaces*, lo que impide que puedan haber dos clases con el mismo nombre. Como “parche”, en iOS/OSX era una práctica comúnmente aceptada preceder los nombres de las clases con un prefijo arbitrario para evitar colisiones. Con Xcode 6, [Apple ha cambiado la práctica habitual](http://scottberrevoets.com/2014/07/25/objective-c-prefixes-a-thing-of-the-past/) y no recomienda los prefijos salvo para el desarrollo de *frameworks*, ya que en estos sí hay riesgo de colisión de nombres al estar hechos para ser usados en diferentes proyectos. En una aplicación normal es raro reutilizar código de otra y por tanto no hay riesgo de colisiones en los nombres.

1. Finalmente, nos pedirá seleccionar la carpeta donde crear el proyecto. Automáticamente creará una carpeta con el mismo nombre del proyecto donde meterá todos los archivos. También nos preguntará si deseamos crear un repositorio Git para el proyecto. **Marcad esta casilla**, para poder probar su uso. Para ver más información sobre el uso de Git en Xcode, consultad el apéndice correspondiente.

> Si no se marca la opción de Git es posible crear luego el repositorio de forma manual (con `git init` … etc) pero no con Xcode. Para ver cómo crear el repositorio manualmente, por ejemplo consultar el apartado “Creating a Git repository” del tutorial “[Understanding Git Source Control in Xcode](https://github.com/mastermoviles/introduccion-a-objective-c-y-la-plataforma-ios/tree/e74b944a6e1a63880027110c6a0f17a355aeef1f/\[http:/www.appcoda.com/git-source-control-in-Xcode/]/README.md)”

* Si echamos un vistazo al código generado por Xcode podremos ver que tiene la siguiente estructura, común a todas las aplicaciones iOS

  ![Tomada de "iOS app programming guide”, de Apple ](/files/-LDGNaqFOYqDLb6X-bd_)
* El esquema anterior es genérico, en nuestro caso concreto:
  * Por ahora no hay modelo, ya que ¡crearlo es nuestro trabajo!
  * El `UIApplication` se crea desde la función main que está en `Supporting files/main.m`
  * El *application delegate* se ha creado automáticamente y se llama `AppDelegate`. Aquí es donde metemos el código “global” de la aplicación
  * Solo hay una vista y un controlador. El controlador es la clase `ViewController`. Para la vista no tenemos código Obj-C sino que la editamos gráficamente con el `Main.storyboard`
* En el área del navegador, a la izquierda de la pantalla, podremos ver la estructura del proyecto recién creado. Veremos que está dividido en tres carpetas, o **grupos**: uno para los fuentes, otro para las pruebas unitarias y otro para el producto final (la aplicación compilada).

![Estructura del proyecto en el navigator de Xcode](/files/-LDGNaqHcEmPILdzzu2K)

> En Xcode los grupos o **groups** son simplemente una forma interna de organizar el código. Son carpetas “virtuales” que no tienen por qué corresponderse con carpetas “reales” del sistema de archivos. Como ejemplo, podéis pulsar con botón derecho sobre el icono del proyecto y seleccionar “Show in finder” para ver la estructura de carpetas en el Finder (el explorador de archivos de OSX). Podréis ver que los grupos `UAdivino` y `UAdivinoTests`sí se corresponden con carpetas del sistema de archivos, pero no así `products` o `UAdivino/Supporting files`.

### Implementación del modelo

* En resumen:
  * Es el núcleo de nuestra aplicación, la “lógica de negocio”
  * Debe ser independiente del interfaz, por lo que no se comunicará directamente con la vista
* Nuestra “lógica de negocio” es muy simple, se limitará a darnos una respuesta elegida al azar de entre las posibles. Crearemos una clase que implemente esto.
* Crear la clase `UADivinoModel`: Menú `File > New > File...` y en la categoría `iOS` elegir `Cocoa Touch class`
* Automáticamente se creará un fichero de interfaz pública (`.h`) y otro de implementación (`.m`).
* Añadir un método en el fichero de la interfaz:

  &#x20; `- (NSString\*) obtenerRespuesta;`
* implementar el método en el fichero de implementación. Por el momento solo debería dar las respuestas “SI” o “NO” con una probabilidad del 50%
  * Ayuda: la función `arc4random()` es similar al `rand()` de C. Por ejemplo para obtener enteros entre 0 y 9 haríamos: `arc4random()%10`.

#### Constructores

* Crear un constructor en el que se inicialice un array de respuestas

#### Más sobre métodos

* Añadir un método con argumentos: `addRespuesta`, para insertar una nueva posible respuesta en el array, con un argumento `NSString*`.
* Tendremos que cambiar el `NSArray` por un `NSMutableArray`

#### Propiedades

* Añadirle a UAdivino un nombre: Zoltar, Rappel, …
* El compilador “sintetiza” automáticamente un *getter* y un *setter*. Por convenio el *getter* tiene el mismo nombre que la propiedad y el *setter* comienza por \`\`set\`\`\`(al estilo Java).

### Interfaz gráfico: vista y controlador

* En el panel de la derecha del todo desmarcar la casilla “Use size classes”
* Añadir un label para explicar la mecánica de UAdivino “formula en voz alta una pregunta y pulsa el botón para obtener la respuesta”
* Añadir un botón “obtener Respuesta”
* Crear un **action** vinculado al botón y en el `ViewController.h` a un nuevo método del controller “botonPulsado”
* Crear un **outlet** vinculado al label y a una nueva propiedad en el `ViewController.h`

### Asset catalogs

* La mayoría de aplicaciones tienen imágenes asociadas al interfaz de usuario. Como mínimo deberían tener un icono y una imagen de *launch*, que aparece mientras se carga la aplicación. Además durante la ejecución se pueden mostrar más imágenes incluidas en el *bundle* de la aplicación (no son descargadas de la red en tiempo real). Para organizar las imágenes de modo sencillo podemos usar los **Asset catalogs**
* Por defecto cada proyecto tiene inicialmente un catálogo de imágenes vacío, que aparece en el navegador con el nombre `Images.xcassets`
* Para los iconos y *launch image* usaremos formato .png y los tamaños recomendados. Podemos consultarlos por ejemplo en las [Human Inteface Guidelines](https://developer.apple.com/library/ios/documentation/userexperience/conceptual/mobilehig/IconMatrix.html#//apple_ref/doc/uid/TP40006556-CH27-SW1) de Apple
* Podemos añadir una imagen al catálogo arrastrándolas allí dentro desde el Finder o bien pulsando con el botón derecho en el catálogo y seleccionando `Import...`. En realidad lo que estamos creando es un “image set” más que una única imagen física. Para cada imagen podemos tener la versión en 1x, 2x y 3x. iOS usará automáticamente la apropiada para la resolución del dispositivo actual.
* Cada “image set” tiene un nombre, que no tiene por qué coincidir con el nombre físico del/los fichero/s. Para cargar la imagen en nuestro código podemos usar el método de clase `imageNamed:`

```
UIImage *imagen = [UIImage imageNamed:@"saludo"];
```

## Foundation framework

El *framework Foundation* define un conjunto de clases básicas y de utilidades que no están directamente incluídas en Objective-C, como colecciones, cadenas, fechas … Además define algunos elementos importantes como la raíz de la jerarquía de clases y algunos tipos primitivos para mejorar la portabilidad.

### Tipos primitivos de C vs tipos primitivos de Foundation/Cocoa

* Como Objective-C es compatible con C podemos seguir usando en nuestros programas los tipos `int`, `float`, `double`,…
* En Foundation también existen `NSInteger` y `NSUInteger` como sustitutos de las variantes de `int`. Son simplemente `typedef` definidos como enteros con la longitud apropiada para la plataforma (32/64 bits). Es decir, no son objetos sino tipos primitivos, y se recomienda su uso por razones de portabilidad.
* Algo similar ocurre con `CGFloat`, usado ampliamente en Cocoa cuando se trabaja con números reales.

### Clases básicas

* En Foundation existe el concepto de objeto *mutable* e *inmutable* inmutable significa que no se pueden insertar, eliminar o cambiar elementos de la colección. Para estas operaciones debemos usar objetos mutables. Por ejemplo, las cadenas `NSSString` que hemos visto hasta ahora son objetos inmutables.

#### `NSObject`: la raíz de la jerarquía de clases

* Todas las clases deben heredar de una clase base, en caso contrario dará error de compilación. Lo habitual es hacer que nuestras clases hereden de `NSObject`, la “clase raíz” de Foundation.

> Esto es similar a otros lenguajes, por ejemplo Java, en la que todas las clases deben heredar de `Object`. Lo que ocurre es que en Java se hace implícitamente mientras que en Objective-C se debe especificar de manera explícita. De hecho en versiones antiguas de Java también se debía hacer explícitamente.

* La clase `NSObject` incluye una serie de métodos de utilidad para nuestras clases, entre otros:
  * `initialize` es un método de clase llamado cuando ésta se carga por primera vez. Puede servir para inicializar variables estáticas.
  * En los dos siguientes apartados vamos a ver los métodos de `NSObject` para copiar objetos y obtener información sobre la instancia actual.

**Copia de objetos**

* los métodos `copy`/`mutableCopy`: sirven para hacer una copia inmutable/mutable de un objeto, respectivamente.
* Con clases de Foundation/Cocoa, podremos hacer una copia usando estos métodos cuando la clase en cuestión sea conforme al protocolo `NSCopying`. Podremos comprobar este extremo en la documentación

![Documentación del API de NSString](/files/-LDGNaqoJXaMrJkFavZo)

> Posteriormente veremos más a fondo los protocolos en Objective-C. Por ahora nos basta con saber que más o menos equivalen a los `Interface` de Java

```
// La cadena original es inmmutable
NSString *cadena = @"Mi cadena";
NSString *copiaInmutable = [cadena copy];
NSMutableString *copiaMutable = [cadena mutableCopy];
// La cadena original es mutable
NSMutableString *cadenaMutable = [NSMutableString stringWithCapacity: 32];
NSString *copiaInmutable = [cadenaMutable copy];
NSMutableString *copiaMutable = [cadenaMutable mutableCopy];
```

* Con clases propias, para que `copy` funcione, debemos
  1. Implementar un método `copyWithZone` (al que `copy` acaba llamando). En este método debemos devolver la copia. Para ayudarnos podemos hacer uso de NSCopyObject, que hace la copia *shallow* del objeto.
  2. Especificar que nuestra clase es conforme a `NSCopying`.
* Podéis ver más detalles del proceso anterior por ejemplo en [este tutorial](http://www.techotopia.com/index.php/Copying_Objects_in_Objective-C)
* Con clases propias, para `mutableCopy` debemos hacer lo mismo pero implementando un método `mutableCopyWithZone`

**Información sobre una instancia**

`NSObject` implementa una serie de métodos que ofrecen información sobre una instancia y que podemos sobreescribir para adaptar a nuestras necesidades. Como ahora veremos, la mayoría de clases de Foundation ya los sobreescriben.

* `isEqual`: como siempre se utilizan referencias para los objetos, el operador `==` lo que hará es *comprobar si apuntan a la misma dirección de memoria*. Si queremos comprobar igualdad de contenido, podemos usar `isEqual`.
  * La mayoría de clases de Cocoa/Foundation sobreescriben este método o bien proporcionan versiones algo más sofisticadas. Por ejemplo, `NSString` implementa también un método `isEqualToString`, especializado en comparar cadenas.
  * En nuestras propias clases deberíamos sobreescribir el `isEqual` ya que la versión de `NSObject` usa simplemente un `==` para comparar.
* `hash`: debe calcular (cómo no) un *hash* para nuestro objeto. La implementación por defecto simplemente devuelve la dirección del objeto, de modo que en nuestras propias clases deberíamos sobreescribirlo si lo necesitamos. La mayoría de clases de Cocoa lo sobreescriben.

> hasta iOS 7 `hash` era un método. En iOS 8 es una propiedad
>
> Como especifica la documentación de Apple, si sobreescribimos `isEqual` también debemos hacer lo propio con `hash`si queremos usar la clase en colecciones. En caso contrario podemos tener problemas, ya que dos objetos iguales deberían tener el mismo valor de *hash*.

* `description`: debería devolver un `NSString*` con una descripción del objeto (al estilo `toString` de Java). Como en los métodos anteriores, deberíamos sobreescribirlo en nuestras propias clases ya que la implementación por defecto imprime simplemente el nombre de la clase y la dirección en memoria de la instancia.

#### Cadenas

Ya hemos usado múltiples veces `NSString`. La clase tiene numerosos métodos para manipulación de cadenas, búsqueda de subcadenas, conversión entre cadenas de C y `NSString`, etc. La clase es inmutable pero su subclase `NSMutableString` sí es mutable. Podéis consultar [este tutorial](http://rypress.com/tutorials/objective-c/data-types/nsstring.html) para ver ejemplos de uso

#### Fechas

Otra clase básica es `NSDate`, para el manejo de fechas. Podéis ver ejemplos de su uso en [este tutorial](http://rypress.com/tutorials/objective-c/data-types/dates.html).

### Colecciones

* Todas las colecciones de Foundation vienen en una versión “inmutable” y otra “mutable”.
* Cuando se añade un objeto a una colección mutable lo que se está añadiendo es una referencia, no una copia, por lo que *modificar el objeto original modificará la colección*.

  **Wrappers de tipos primitivos**
* Las colecciones son conjuntos de objetos, por lo que directamente no pueden almacenar valores primitivos de C. Necesitaremos “empaquetar” estos tipos primitivos dentro de objetos usando *wrappers*.
* `NSNumber` es un *wrapper* que puede empaquetar en forma de objeto cualquier tipo numérico de C. Además de para las colecciones, ciertos métodos de Cocoa requieren de datos numéricos como objetos en lugar de tipos primitivos.
* Podemos definir un `NSNumber` precediendo un literal del símbolo `@`. Con una expresión debemos usar además paréntesis, por ejemplo

```
NSNumber *num = @7.25;
float flo = 3.5;
NSNumber *otro_num = @(flo);
```

* Un `NSNumber` no es directamente un número por lo que no puede participar en operaciones aritméticas, etc. Pero sí podemos obtener el valor empaquetado dentro con los métodos `intValue`, `floatValue`, etc.

> El compilador no chequea tipos al desempaquetar los valores, de modo que no dará error si llamamos por ejemplo a `intValue`para un valor empaquetado como `float`. En este caso simplemente truncará el valor.

* Por otro lado, no es posible añadir `nil` a una colección ya que significa “vacío”. Si queremos representar esto en una colección usaremos la clase `NSNull`. Es un *singleton*, y para obtener su única instancia se usa el método de clase `null`

```
id obj_nulo = [NSNull null];
```

#### Listas

* La versión inmutable es `NSArray` y la mutable es su subclase `NSMutableArray`
* Un `NSArray` puede contener objetos de distintas clases. Por otro lado, los `NSMutableArray` pueden cambiar no solo de contenido sino también de tamaño. Es decir, son más parecidos a las listas de Java o a los arrays de Python/Ruby… que a los arrays de C.
* La manera más sencilla de inicializar un `NSArray` es con un literal

  &#x20; NSArray \*a = @\[@1, @"hola"];
* Para inicializar un `NSMutableArray` no podemos usar literales, sino un método  de clase que actúa como una factoría:

```
//El método admite un número variable de argumentos, terminados en "nil"
NSMutableArray *mut = [NSMutableArray arrayWithObjects:
                              @1, @"Hola", nil];
```

* Podemos obtener el número de elementos que tiene la lista con el método `count`. Este método sirve también para las otras colecciones.
* Podemos añadir un elemento a un `NSMutableArray` con `addObject`. O insertarlo en una posición específica con `insertObject:atIndex`. El elemento que estuviera en esa posición y los siguientes se moverán una posición “a la derecha”.

```
[mut insertObject:@"adios" atIndex:1];
```

* También podemos eliminar elementos, reemplazarlos, ordenarlos, filtrarlos,… se pueden ver ejemplos de uso en [este tutorial](http://rypress.com/tutorials/objective-c/data-types/nsarray.html).

#### Diccionarios

* Un diccionario es un conjunto de pares `(clave, valor)`. Las claves suelen ser `NSString`, pero se puede usar cualquier objeto que sea copiable (sea conforme a `NSCopying`) e implemente `isEqual` y `hash`.
* `` `NSDictionary```es la versión inmutable y ``NSMutableDictionary\` la mutable.
* Podemos crear un `NSDictionary` con un literal. Se usan las llaves como delimitador, la clave se separa del valor por \`\`:\`\`\`y las parejas clave-valor por comas

```
NSDictionary meses = @{
       @"Enero" : @31,
       @"Febrero" : @28,
       @"Marzo" : @30
};
```

* Podemos obtener un valor a partir de la clave usando notación de array `meses[@"Enero"]`
  * Al igual que con los `NSArray`, para crear la versión mutable necesitamos un método factoría. Hay varios, por ejemplo podemos crearlo a partir de dos arrays, uno para los valores y otro para las claves

```
NSArray *nombres = @[@"Enero", @"Febrero", @"Marzo"];
NSArray *dias = @[@31, @28, @30];

NSMutableDictionary *meses = [NSMutableDictionary dictionaryWithObjects:dias forKeys:nombres];
```

* Para añadir un elemento a un diccionario mutable podemos usar la notación de array o bien usar el método `setObject:forKey`

```
meses[@"Septiembre" ] = @30;
[meses setObject:@31 forKey:@"Diciembre"];
```

* Podemos ver más ejemplos de uso de diccionarios en [este tutorial](http://rypress.com/tutorials/objective-c/data-types/nsdictionary.html).

#### Conjuntos

* Un conjunto es una colección no ordenada de elementos distintos. Al igual que en el resto de colecciones, tenemos la versión inmutable `NSSet` y la mutable `NSMutableSet`.
* No se pueden usar literales para inicializar conjuntos, pero sí hay varios métodos factoría, por ejemplo `setWithObjects`

  &#x20; NSSet \*conj = \[NSSet setWithObjects:@1, @"Hola", nil];

  * Podemos comprobar si un objeto está en una colección con `containsObject`. Aunque esto también se puede hacer con `NSArray` los conjuntos lo implementan de modo mucho más eficiente.
* Podemos añadir un objeto con `addObject` y eliminarlo con `removeObject`
* Podemos ejecutar otras operaciones típicas de conjuntos, como la unión, la intersección, etc. Para más ejemplos de uso de conjuntos, consultar [este tutorial](http://rypress.com/tutorials/objective-c/data-types/nsset.html).

#### Recorrer una colección

* La forma más simple de recorrer una colección es con la denominada *fast enumeration*, que consiste en un `for-in` al estilo Java 5.

```
for(id obj in coleccion) {
    NSLog(@"Obtenido el objeto %@", obj);
}
```

* Si el tipo de objetos de la colección es uniforme y lo conocemos, podemos especificarlo, el código quedará más claro

```
for(NSString *cad in coleccion) {
    NSLog(@"Obtenida la cadena %@", cad);
}
```

* El *fast enumeration* aplicado a diccionarios efectúa una iteración **por las claves**, pero a partir de ellas recuperar los valores es muy sencillo,como ya hemos visto

```
    for (id clave in diccionario) {
        NSLog(@"(%@, %@)", clave, [diccionario objectForKey: clave]);
    }
```

* Además de la *fast enumeration* se pueden usar *enumerators*, que son como los iteradores de Java, pero al igual que en este lenguaje el código resulta más complejo.

> Si mientras estamos recorriendo una colección mutable (tanto con for-in como con un enumerador) tratamos de modificarla, obtendremos un error en tiempo de ejecución.

## Apéndice: Git y Xcode

### Operaciones básicas de Git desde Xcode

* Al crear el proyecto marcando la opción de usar un repositorio Git, automáticamente se ha inicializado el repositorio y hecho el commit de los archivos iniciales de la plantilla que hayamos elegido.
* Cada vez que modifiquemos uno de los archivos, Xcode nos lo indicará en el navegador del proyecto con una **M**. Si añadimos alguno aparecerá una **A**.

  ![](/files/-LDGNarIo9oykD6UMHDi)
* Para hacer un **commit**, `Source Control > Commit...`. En el cuadro de diálogo podremos revisar los archivos cambiados y escribir el mensaje de commit
* Para anular todos los cambios, y **volver al último commit** `Source Control > Discard all changes...`
* Podemos **trabajar con ramas** desde la primera opción del menú `Source Control`, que pone el nombre de la rama actual (por defecto “master”) y nos permite crear una nueva, cambiar de rama, hacer un *merge*, …

<https://developer.apple.com/library/ios/documentation/general/conceptual/devpedia-cocoacore/>

## Referencias

Algunas referencias para aprender Objective-C y de introducción básica a la plataforma iOS

### Recursos generales

* [iOS Dev Center de Apple](https://developer.apple.com/devcenter/ios/index.action), con todos los recursos (guías, referencias, ejemplos de código, …) que Apple ofrece a los desarrolladores. Es necesario registrarse (gratuitamente) para ver algunos recursos (por ejemplo, los videos de las sesiones de la WWDC, muy recomendables).

### Guías de Apple

* [Programming with Objective-C](https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html)
* [Concepts in Objective-C Programming](https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010810)

### Tutoriales en la web

* [Ry’s Objective-C tutorial](http://rypress.com/tutorials/objective-c/index.html)

### Libros

Disponibles en versión electrónica desde las IPs de la UA a través del servicio [Safari Books Online](http://proquest.safaribooksonline.com/?uicode=sibyd). Aunque esta plataforma ofrece decenas de libros sobre Objective-C e iOS, son muy recomendables los siguientes:

* [iOS 7 programming fundamentals,](http://proquest.safaribooksonline.com/book/programming/mobile/9781491946039) Matt Neuburg
* [Learning Cocoa with Objective-C](http://proquest.safaribooksonline.com/book/programming/cocoa/9781491901380), 4th Edition, Paris Buttfield-Addison, Jonathon Manning & Tim Nugent
* [Learn iOS 7 App Development](http://proquest.safaribooksonline.com/book/programming/mobile/9781430250623), James Bucanek. Del estilo *hands-on*, en cada capítulo se desarrolla una pequeña aplicación.

## Ejercicios de introducción a iOS

### Mostrar imagen además de respuesta en modo texto

En lugar de mostrar solo el texto de la respuesta, también vamos a mostrar una imagen que la “ilustre”. Tendremos dos imágenes: una para cuando la respuesta es positiva y otra para cuando es negativa.

#### Parte 1: modificación del modelo

* Primero habrá que modificar el modelo para que en lugar de almacenar simplemente los textos de las respuestas para cada una se almacene el texto y además si la respuesta es positiva/negativa. **Crearemos la clase Respuesta**
* Despúes **añadirle a la clase Respuesta un constructor** `initWithTexto:andTipo:` para poderle pasar el texto y si es positiva/negativa. El constructor se usaría de este modo:

```
Respuesta *r1 = [[Respuesta alloc] initWithTexto:@"NOOO!!" andTipo:NO];
```

* Para  instanciar el `NSMutableArray` de respuestas lo más simple es usar el mismo método que hasta ahora, el método de clase `arrayWithObjects`, pero ahora le pasaremos instancias de la clase `Respuesta` en lugar de cadenas de Foundation. Es decir, aunque quede un código un poco “sucio”, para simplificar, creamos varias variables de tipo `Respuesta *` y luego las añadimos al `NSMutableArray`.

#### Parte 2: interfaz gráfico

* Crear una “Image view” en el interfaz de usuario, usando la “Object Library” (panel inferior derecho de Xcode)
* Crear un **outlet** que asocie esta “image view” con una propiedad en el `ViewController.h`. Podéis llamar a esta propiedad como queráis, por ejemplo “imagen”.
* Añadir las imágenes que están en las plantillas de la sesión al “images.xcassets”. Darles un nombre corto para referirnos luego a ellas en el código.
* En el controller, dentro del método `botonPulsado`, además de mostrar la respuesta en la etiqueta, hay que actualizar la “image view”. Recordar que se puede cargar una imagen con `imageNamed:`. Lo que tenemos que cambiar de la “image view” es la propiedad `image`

```
'//suponiendo que el outlet que se refiere a la "image view" se llama "imagen"
self.imagen.image = [UIImage imageNamed:@"nombre_de_imagen"]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mastermoviles.gitbook.io/introduccion-a-objective-c-y-la-plataforma-ios/hola-ios-introduccion-a-la-plataforma-ios-y-el-lenguaje-objective-c.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
