Anda di halaman 1dari 381

CURSO IOS 8

FERNANDO ALAVA

Esta pgina se ha dejado vaca a propsito

ndice de contenidos
Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Captulo 1 Presentacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.1 Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.2 Portales en Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Captulo 2 Dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.1 iPhone. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.2 iPad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.3 Comparativa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.4 Fechas y otros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Captulo 3 Apple Developer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29


3.1 Portal para desarrolladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.2 Apple ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Captulo 4 Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.1 Instalacin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.2 Workspace. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.3 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

Captulo 5 Trucos de Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39


5.1 Referencias y videos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.2 Atajos de teclado Mac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3 Atajos de teclado Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.4 Con el ratn. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.5 Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

Captulo 6 App: HolaMundo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43


6.1 Abrir Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.2 Nuevo proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.3 Testear en Simulador. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
6.4 Crear controles en el Storyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6.5 Crear conectores Outlet y Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.6 Notas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.7 Ejercicio 1: delegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

6.8 Ejercicio 2: nuevo mtodo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

Captulo 7 Objective C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.1 Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.2 Objective C es C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.3 Objective C aade objetos a C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.4 Objective C aade el tipo BOOL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.5 Objective C usa las sentencias y operadores de C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.6 Vocabulario bsico de orientacin a objetos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.7 Creacin de clases en Objective C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.8 Propiedades. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.9 Tipos y memoria. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.10 Creacin de objetos en Objective C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.11 Mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.12 Mensajes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
7.13 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Captulo 8 App: Cuestionario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67


8.1 Simulador. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.2 Storyboard. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.3 Cdigo de ayuda. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.4 Tarea 1: Proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8.5 Tarea 2: Storyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8.6 Tarea 3: Outlets y Actions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8.7 Tarea 4: Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
8.8 Tarea 5: Propiedad indice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.9 Tarea 6: Inicializacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.10 Tarea 7: Ver Respuesta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.11 Tarea 8: Siguiente Pregunta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.12 Tarea extra: Ms preguntas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.13 Tarea extra: Anterior Pregunta. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

Captulo 9 Gestin de la memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73


9.1 ARC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
9.2 Sin ARC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

Captulo 10 MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

10.1 Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
10.2 Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
10.3 View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
10.4 Comunicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

Captulo 11 App: Calculadora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81


11.1 Ayuda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
11.2 Tarea 1: Proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
11.3 Tarea 2: Storyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
11.4 Tarea 3: Modelo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
11.5 Tarea 4: Propiedades del modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
11.6 Tarea 5: Mtodos del modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
11.7 Tarea 6: Controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
11.8 Tarea 7: Conectar outlets y acciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
11.9 Tarea 8: Conectar el controlador con el modelo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
11.10 Tarea 9: Implementar el modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

Captulo 12 Documentacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
12.1 Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
12.2 Internet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Captulo 13 Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
13.1 All exceptions breakpoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
13.2 Visualizar valores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
13.3 Condicional breakpoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Captulo 14 App: Cartas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91


14.1 Storyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
14.2 Recursos grficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.3 Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.4 Controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.5 Ayuda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

Captulo 15 Paths y URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95


15.1 Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
15.2 URLs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

Captulo 16 Protocolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

16.1 Ayuda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

Captulo 17 App: Cervezas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101


17.1 Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
17.2 Storyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
17.3 Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
17.4 Listado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
17.5 Detalle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
17.6 Edicin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
17.7 Protocolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
17.8 Persistencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
17.9 Custom Picker (nuevo control) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
17.10 Ayuda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Captulo 18 Persistencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115


18.1 NSUserDefaults. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
18.2 Property Lists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
18.3 Archivado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
18.4 NSKeyed[Un]Archiver. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
18.5 File System. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
18.6 NSFileManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
18.7 NSString. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
18.8 SQLite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
18.9 Core Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

Captulo 19 App: Libros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121


19.1 Tarea 1: Proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
19.2 Tarea 2: Importar recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
19.3 Tarea 3: Modelo Libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
19.4 Tarea 4: Modelo Libros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
19.5 Tarea 5: Pantalla Listado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
19.6 Tarea 6: Controlador de navegacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
19.7 Tarea 7: Botones Nuevo y Editar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
19.8 Tarea 8: Pantalla Detalle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
19.9 Tarea 9: Transicin Detalle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
19.10 Tarea 10: Pantalla Editar/Nuevo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

19.11 Tarea 11: Transiciones Editar y Nuevo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123


19.12 Tarea 12: Protocolo y delegate en Editar/Nuevo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
19.13 Tarea 13: Protocolo y delegate en Listado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
19.14 Tarea 14: Guardar cambios de edicin, nuevo y borrar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
19.15 Tarea 15: Clase Libro archivable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
19.16 Tarea 16: Ruta al Sandbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
19.17 Tarea 17: Persistencia mediante archivado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
19.18 Tarea 18: Archivado y desarchivado en clase Libros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Captulo 20 Blocks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125


20.1 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
20.2 Qu es un block? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
20.3 Guardar un bloque en una variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
20.4 Definir un tipo para varios bloques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
20.5 Enumerar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
20.6 Ordenar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
20.7 Animar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
20.8 Accin al completar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

Captulo 21 Grand Central Dispatch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129


21.1 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
21.2 Ejecutar un bloque en una de las colas globales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
21.3 Ejecutar un bloque en la cola principal (main queue). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
21.4 Anidar dos dispatch_async para prevenir problemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
21.5 Cmo declarar nuestros propios tipos completion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Captulo 22 Core Data: Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133


22.1 Creacin del esquema. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
22.2 La pila de Core Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
22.3 Incluir Framework Core Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
22.4 La clase que representa al esquema: NSManagedObjectModel . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
22.5 Generacin de las Clases del modelo: NSManagedObject. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
22.6 Categoras de Objective C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
22.7 Contexto de Core Data: NSManagedObjectContext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
22.8 Documentos de nuestra aplicacin: UIManagedDocument . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
22.9 Consultas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

Captulo 23 App: Ejemplo Core Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147


23.1 Activar CoreData SQLDebug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
23.2 ViewController.h. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
23.3 ViewController.m. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
23.4 Foto+Metodos.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
23.5 Foto+Metodos.m. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
23.6 Fotografo+Metodos.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
23.7 Fotografo+Metodos.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

Captulo 24 NSFetchedResultsController . . . . . . . . . . . . . . . . . . . . . . . . . 155


24.1 Creacin del controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
24.2 Construccin del TableView. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
24.3 Delegacin y eventos NSFetchedResultsControllerDelegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Captulo 25 iCloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161


25.1 Introduccin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
25.2 Coordinacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
25.3 Enumerar el contenido de iCloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
25.4 Procesar notificaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
25.5 Estados del documento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
25.6 Mover un archivo entre dispositivos e iCloud. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
25.7 Compartir un fichero usando iCloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
25.8 NSUbiquitousKeyValueStore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

Captulo 26 Servicios Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169


26.1 SOAP/WSDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
26.2 REST basado en XML o JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

Captulo 27 Cmara: Fotos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173


27.1 Introduccin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
27.2 Ejemplo: UIImagePickerController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
27.3 Ejemplo: UIImagePickerControllerDelegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
27.4 Ejemplo: AVCaptureDevice. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
27.5 Referencias: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

Captulo 28 Cmara en el Simulador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177


28.1 Usar una imgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

28.2 Guardar una imgen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178


28.3 Imgenes de ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
28.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

Captulo 29 App: Libros Avanzado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183


29.1 Core Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
29.2 Pantallas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
29.3 Google Books API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
29.4 Cmara de fotos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
29.5 Escanear ISBN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
29.6 Recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
29.7 Ejemplos de cdigo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

Foundation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Captulo NS.1 NSLog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
NS.1.1 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195

Captulo NS.2 NSObject. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197


NS.2.1 Introspeccin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
NS.2.2 Mensaje class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
NS.2.3 Conversin @selector() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
NS.2.4 Tipo genrico id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198

Captulo NS.3 NSString. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199


NS.3.1 Mtodos tiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
NS.3.2 Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
NS.3.3 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204

Captulo NS.4 NSMutableString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205


NS.4.1 Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
NS.4.2 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206

Captulo NS.5 NSNumber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207


NS.5.1 Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

Captulo NS.6 NSDate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211


NS.6.1 Creacion de fechas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
NS.6.2 Formatos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
NS.6.3 Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212

NS.6.4 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213

Captulo NS.7 NSValue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215


NS.7.1 Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

Captulo NS.8 NSData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217


NS.8.1 Tareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

Captulo NS.9 NSArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219


NS.9.1 Mtodos tiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

Captulo NS.10 NSMutableArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221


NS.10.1 Mtodos tiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221

Captulo NS.11 NSDictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223


NS.11.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

Captulo NS.12 NSMutableDictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227


NS.12.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227

Captulo NS.13 NSSet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229


NS.13.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Captulo NS.14 NSMutableSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231


NS.14.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

Captulo NS.15 NSOrderedSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233


NS.15.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

Captulo NS.16 NSMutableOrderedSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237


NS.16.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Captulo NS.17 NSCountedSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239


NS.17.1 Tareas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

Captulo NS.18 Enumeracin rpida. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241


NS.18.1 Sentencia for(... in ...) { ... }. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
NS.18.2 Ejemplo 1: NSArray de objetos NSString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
NS.18.3 Ejemplo 2: NSDictionary con claves y valores NSString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

Captulo NS.19 Sintaxis Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243


NS.19.1 Crear nuevo proyecto de Xcode Single View. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
NS.19.2 NSString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
NS.19.3 NSNumber. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

NS.19.4 NSArray. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244


NS.19.5 NSDictionary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
NS.19.6 NSSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
NS.19.7 NSCountedSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

Captulo NS.20 Property Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247


Captulo NS.21 NSUserDefaults. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Captulo NS.22 Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
NS.22.1 Interfaz pblico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
NS.22.2 Implementacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

UIKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
Captulo UI.1 UIViewController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
UI.1.1 Ciclo de vida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255

Captulo UI.2 UIView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259


UI.2.1 Vistas o views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Captulo UI.3 UIGestureRecognizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265


UI.3.1 Cmo reconocemos toques?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
UI.3.2 UIGestureRecognizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
UI.3.3 Cmo implementamos el target de un gesture recognizer? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
UI.3.4 Otros gestos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

Captulo UI.4 UIScrollView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269


UI.4.1 App de Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

Captulo UI.5 UICollectionViewController . . . . . . . . . . . . . . . . . . . . . . . . 273


UI.5.1 Mtodos en UICollectionViewDatasource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
UI.5.2 Celda personalizada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
UI.5.3 Referencia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273

Captulo UI.6 UISplitView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275


UI.6.1 MaestroTableViewController.h. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
UI.6.2 MaestroTableViewController.m. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

Captulo UI.7 UIPopoverController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279


UI.7.1 Bugs! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279

Cocoapods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Captulo POD.1 Cocoapods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285


POD.1.1 Documentacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
POD.1.2 Instalacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
POD.1.3 Ejemplo de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
POD.1.4 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

Captulo POD.2 ZBarSDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287


POD.2.1 Documentacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
POD.2.2 Instalacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
POD.2.3 Cdigo de ejemplo bsico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

Stanford CS193P . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291


Captulo S Stanford CS193p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
S.1 Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
S.2 Presentaciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
S.3 Videos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
S.4 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Captulo S.1 Stanford: Lecture 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297


S.1.1 Componentes de la Plataforma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
S.1.2 Vocabulario bsico de Orientacin a Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
S.1.3 MVC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
S.1.4 Objective C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
S.1.5 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299

Captulo S.2 Stanford: Lecture 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301


S.2.1 App: Cartas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
S.2.2 Objective C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
S.2.3 Paseo por Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
S.2.4 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

Captulo S.3 Stanford: Lecture 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303


S.3.1 App: Cartas (continuacin) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
S.3.2 Repaso MVC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
S.3.3 Repaso Xcode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
S.3.4 Repaso Objective C. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
S.3.5 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307

Captulo S.4 Stanford: Lecture 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309


S.4.1 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
S.4.2 Crear objetos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
S.4.3 nil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
S.4.4 Ligadura dinmica o dynamic binding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
S.4.5 Instrospeccin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
S.4.6 Foundation Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
S.4.7 Attributed Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
S.4.8 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326

Captulo S.5 Stanford: Lecture 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327


S.5.1 UITextView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
S.5.2 View Controller Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
S.5.3 NSNotification. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
S.5.4 Demo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
S.5.5 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328

Captulo S.6 Stanford: Lecture 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329


S.6.1 Multiple MVCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
S.6.2 UINavigarionController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
S.6.3 UITabBarController. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
S.6.4 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331

Captulo S.7 Stanford: Lecture 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333


S.7.1 Vistas y UIVIew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
S.7.2 Gestos y UIGestureRecognizer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
S.7.3 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335

Captulo S.8 Stanford: Lecture 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337


S.8.1 Protocolos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
S.8.2 Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
S.8.3 Animaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
S.8.4 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339

Captulo S.9 Stanford: Lecture 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341


S.9.1 Autolayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
S.9.2 Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

Captulo S.10 Stanford: Lecture 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343


S.10.1 Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
S.10.2 UIScrollView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
S.10.3 UITableView. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
S.10.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

Captulo S.11 Stanford: Lecture 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347


S.11.1 UITableView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
S.11.2 iPad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
S.11.3 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Captulo S.12 Stanford: Lecture 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351


S.12.1 Core Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
S.12.2 UIManagedDocument . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
S.12.3 NSNotification. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
S.12.4 Categoras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
S.12.5 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354

Captulo S.13 Stanford: Lecture 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355


S.13.1 Core Data y UITableView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
S.13.2 NSFetchedResultsController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
S.13.3 CoreDataTableViewController. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
S.13.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357

Captulo S.14 Stanford: Lecture 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359


S.14.1 UIApplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
S.14.2 Network Activity Indicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
S.14.3 Core Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
S.14.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

Captulo S.15 Stanford: Lecture 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363


S.15.1 Map Kit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
S.15.2 MkAnnotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
S.15.3 MkDirections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
S.15.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365

Captulo S.16 Stanford: Lecture 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367


S.16.1 Modal View Controllers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

S.16.2 UITextField. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368


S.16.3 Action Sheet y Alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
S.16.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369

Captulo S.17 Stanford: Lecture 17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371


S.17.1 Cmara y UIImagePickerController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
S.17.2 Core Motion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
S.17.3 Application State. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
S.17.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373

Captulo S.18 Stanford: Lecture 18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375


S.18.1 Internacionalizacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
S.18.2 NSNumberFormatter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
S.18.3 NSDateFormatter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
S.18.4 Referencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377

Apndice A Descargas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379


A.1 Curso completo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
A.2 Recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
A.3 Apps. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
A.4 Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

Esta pgina se ha dejado vaca a propsito

Introduccin

Esta pgina se ha dejado vaca a propsito

18

Captulo 1

Presentacin
1.1 Objetivo

Aprender a desarrollar aplicaciones para iOS: iPhone e iPad.


Para ello deberemos aprender a usar...

1.1.1 Xcode 6
Entorno de desarrollo integrado.
19

Captulo 1 Presentacin

1.1.2 Objective-C
Lenguaje de programacin orientado a objetos, ampla C.

20

Curso iOS 8

Curso iOS 8

Captulo 1 Presentacin

1.1.3 Swift
Nuevo lenguaje de programacin de Apple, compatible con Objective-C, quizs lo sustituya.

1.1.4 Componentes iOS


Core OS
Core Services
Media
Cocoa
Frameworks: Foundation, UIKit, Core Data, Core Location, Map Kit
Importante manejar documentacin

1.1.5 MVC
Estrategia para disear aplicaciones orientadas a objetos.

21

Captulo 1 Presentacin

1.2 Portales en Internet


1.2.1 Apple Developer
Apple Developer (https://developer.apple.com/) : iOS Developer Program.

22

Curso iOS 8

Curso iOS 8

Captulo 1 Presentacin

1.2.2 iOS Dev Center


iOS Dev Center (https://developer.apple.com/devcenter/ios/index.action) :
Documentacin, videos, foros y soporte. Tambin betas iOS y SDK.

1.2.3 iOS Provisioning Portal


iOS Provisioning Portal (https://developer.apple.com/ios/manage/overview/
index.action) : Certificados, dispositivos, app ids, betas, provisioning profiles.

23

Captulo 1 Presentacin

1.2.4 iTunes Connect


iTunes Connect (http://itunesconnect.apple.com/) : Gestin App Store.

24

Curso iOS 8

Captulo 2

Dispositivos
2.1 iPhone

Modelo

Tamao

Resolucin px

PPI

Ratio

iPhone

3.5

320x480

163

3:2

iPhone 3G

3.5

320x480

163

3:2

iPhone 3GS

3.5

320x480

163

3:2

iPhone 4

3.5

640x960

326

3:2
25

Captulo 2 Dispositivos

Curso iOS 8

iPhone 4S

3.5

640x960

326

3:2

iPhone 5

640x1136

326

16:9

iPhone 5C

640x1136

326

16:9

iPhone 5S

640x1136

326

16:9

iPhone 6

4.7

750x1334

326

16:9

iPhone 6 Plus

5.5

1080x1920

401

16:9

2.2 iPad

Modelo

Tamao

Resolucin px

PPI

Ratio

iPad

9.7

768x1024

132

4:3

iPad 2

9.7

768x1024

132

4:3

iPad Retina (3 y 4)

9.7

1536x2048

264

4:3

iPad mini

7.9

768x1024

163

4:3

iPad mini 2

7.9

1536x2048

326

4:3

iPad mini 3

7.9

1536x2048

326

4:3

iPad Air

9.7

1536x2048

264

4:3

iPad Air 2

9.7

1536x2048

264

4:3

26

Curso iOS 8

Captulo 2 Dispositivos

2.3 Comparativa
iPhone

http://www.apple.com/iphone/compare-iphones/

iPad

http://www.apple.com/ipad/compare/

iPod

http://www.apple.com/ipod/compare-ipod-models/

2.4 Fechas y otros


iPhone

http://en.wikipedia.org/wiki/IPhone

iPad

http://en.wikipedia.org/wiki/IPad

MacRumors

http://buyersguide.macrumors.com/

27

Esta pgina se ha dejado vaca a propsito

28

Captulo 3

Apple Developer
3.1 Portal para desarrolladores

Sitio web para registrarse como Apple Developer e inscribirse en los programas para desarrolladores:
https://developer.apple.com/

Es el punto de entrada para acceder al Dev Center de iOS, desde donde podremos:
Acceder a la documentacin online, videos y foros
29

Captulo 3 Apple Developer

Curso iOS 8

Descargar Xcode (tambin nuevas versiones beta)


iOS Provisioning Portal: para gestionar nuestros certificados y las betas de nuestras
apps
iTunes Connect: para gestionar nuestras apps en la App Store

3.2 Apple ID

Para para registrarse como Apple Developer es necesario crear un Apple ID, si no tenemos
ya uno.
Los Apple ID tambin se utiliza para comprar en las App Store, acceder a iCloud y muchas
otras cosas.
Para crear un nuevo Apple ID:
https://appleid.apple.com/

30

Captulo 4

Xcode
Figura 4.1 Xcode es la herramienta de Apple para desarrolladores iOS y Mac

4.1 Instalacin
Pgina de Xcode para desarrolladores (https://developer.apple.com/xcode/)
Descarga desde la Mac App Store (http://itunes.apple.com/us/app/xcode/
id497799835?ls=1&mt=12)
Descarga para desarrolladores (https://developer.apple.com/downloads/
index.action)

31

Captulo 4 Xcode

4.2 Workspace

32

Curso iOS 8

Curso iOS 8

Captulo 4 Xcode

4.2.1 Toolbar / Barra de herramientas

De izquierda a derecha tenemos:


Botones Play / Stop del simulador
Seleccin de esquema y simulador
Ventana de mensajes
Seleccin del tipo de editor: standard, assistant (dos editores emparejados), version
(control de versiones)
Mostrar / Ocultar Navegadores, Depuracin y Utilidades

4.2.2 Editor
El rea de edicin se puede dividir en dos o ms (mediante los botones a la derecha en la
barra de herramientas)
Hay diferentes tipos de editores:
Cdigo
Interfaz builder: Storyboards (interfaz visual)
Previsualizar (aspecto antes de lanzar el simulador)
Modelo de datos (Core Data: entidades, propiedades, relaciones)
Proyecto (propiedades, iconos, frameworks)
Assets grficos y otros
El rea de edicin arriba tiene accesos rpidos a:
Archivos relacionados
Anterior / Siguiente archivo
Cambio rpido de proyecto, carpeta, fichero y declaracin o mtodo
33

Captulo 4 Xcode

Curso iOS 8

El editor de cdigo, a la izquierda, en la columna de los nmeros de lnea:


Indicador de conexiones (outlets)
Puntos de parada (click sobre nmeros de lnea)
Abrir/cerrar bloques de cdigo (puntero encima de la barra a la izquierda de los
nmeros de lnea)

4.2.3 Navegadores

34

Curso iOS 8

Captulo 4 Xcode

Representados por un icono hay 8 formas de navegar por el proyecto:


Proyecto / Proyect: archivos y carpetas
Smbolos / Symbol: clases, propiedares, mtodos
Bsqueda / Find: buscar y reemplazar
Avisos / Issues: errores y problemas en el cdigo
Tests: crear, ejecutar y revisar tests unitarios
Depuracin / Debug: hilos / pila
Puntos de parada / Breakpoints
Registro / Log

4.2.4 Depuracin
Cuando se ejecuta una app abajo tenemos una barra de herramientas:
Puntos de parada
Ejecucin paso a paso
Localizacin y otros
Y dos reas:
Inspector en tiempo de ejecucin (variables, hilos)
Logs y lldb (o gdb) para lanzar comandos de depuracin

35

Captulo 4 Xcode

Curso iOS 8

4.2.5 Utilidades (Inspectores)

En el rea de utilidades cuando editamos un archivo de cdigo hay 2 inspectores:


Archivo
Ayuda rpida
Cuando editamos un interfaz hay 4 inspectores adicionales:
Identidad
Atributos
Tamao
Conexiones (outlets)
Y abajo est la librera con 4 secciones:
Plantillas
36

Curso iOS 8

Captulo 4 Xcode

Fragmentos de cdigo (snippets)


Objetos
Media

4.3 Referencias
iOS Developer Library: Xcode_Overview (https://developer.apple.com/library/ios/
documentation/ToolsLanguages/Conceptual/Xcode_Overview/chapters/
about.html)
PDF: Xcode_Overview (/doc/Xcode_Overview.pdf)

37

Esta pgina se ha dejado vaca a propsito

38

Captulo 5

Trucos de Xcode
5.1 Referencias y videos

http://developer.apple.com/library/mac/#recipes/xcode_help-source_editor

5.2 Atajos de teclado Mac

Igual que en Windows pero Cmd en vez de Ctrl


Cmd+Tab Cambiar aplicacin (Xcode/Simulator)
Cmd+X Cortar
Cmd+C Copiar (Copy)
Cmd+V Pegar
Cmd+S Guardar (Save)
Cmd+W Cerrar ventana (Window)
Cmd+Q Cerrar aplicacin (Quit)

5.2.1 Edicin de texto


Cmd+A Seleccionar todo
Cmd+Flechas Moverse rpidamente
Alt+Flechas Moverse ms lento (palabras)
Ctrl+Flechas Moverse an ms lento (maysculas palabra)
Shift+Flechas Seleccionar texto, tambin con Ctrl y Cmd
39

Captulo 5 Trucos de Xcode

5.3 Atajos de teclado Xcode


5.3.1 Navegadores (izquierda Xcode)
Cmd+0 Mostrar/ocultar navegador
Cmd+1 Navegador proyecto
Cmd+2 Navegador smbolos
Cmd+3 Navegador issues (warnings y errors)
Cmd+4 Navegador debug
Cmd+5 Navegador puntos de parada (breakpoints)
Cmd+6 Navegador notas (log)

5.3.2 Utilidades (derecha Xcode)


Cmd+Alt+0 Mostrar/ocultar utilidades
Cmd+Alt+1 Inspector de archivo
Cmd+Alt+2 Ayuda rpida (Quick Help)
Cmd+Alt+3 Inspector de identidad
Cmd+Alt+4 Inspector de atributos
Cmd+Alt+5 Inspector tamao
Cmd+Alt+6 Inspector de conexiones (outlets)

5.3.3 Editor (centro Xcode)


Cmd+Enter Vista sencilla (cerrar vista doble)
Cmd+Alt+Enter Vista doble
Cmd+J Cambiar de editor con flechas y Enter
Shift+Cmd+J Seleccionar archivo en navegador (izq)
Shift+Cmd+O Abrir rpido (Quick Open) (fuzzy)
Alt+Enter Para abrir en la derecha (p.ej. NSString.h)
Alt+Click Ayuda contextual
Esc Completar
40

Curso iOS 8

Curso iOS 8

Captulo 5 Trucos de Xcode

Ctrl+I Reindentar
Cmd+[ Indentar
Cmd+] Desindentar
Alt+Cmd+Izq Code Folding, plegar
Alt+Cmd+Dch Code Folding, desplegar
Ctrl+1 a Ctrl+6 Acceso a items barra editor, flechas o escribir para moverse, Enter
para cambiar, Esc para cancelar

5.3.4 Simulador
Cmd+R Run
Cmd+. Stop

5.4 Con el ratn


Enfocar en el bloque (scope): Situar el puntero en la barra a la derecha de un bloque
de texto
Seleccionar palabra: Ctrl + Click
Seleccionar definicin: Cmd + Click
Ayuda contextual palabra: Alt + Click
Editar palabra en el bloque (scope): Situar el puntero en la palabra y esperar, aparece
una flecha, desplegar y hacer click en Edit All in Scope

5.5 Plugins
5.5.1 ColorSense
https://github.com/omz/ColorSense-for-Xcode

41

Esta pgina se ha dejado vaca a propsito

42

Captulo 6

App: HolaMundo
6.1 Abrir Xcode

1. Dock
Buscar icono de Xcode (plano y martillo) y hacer click
2. Spotlight
Cmd+Space para abrirlo
43

Captulo 6 App: HolaMundo

Curso iOS 8

Buscar Xcode
Seleccionar Aplicaciones > Xcode y Enter
3. Finder
Cmd+Tab para cambiar de aplicacin
Seleccionar Finder
Ir a Aplicaciones > Xcode.app

6.2 Nuevo proyecto

En la ventana Welcome to Xcode seleccionar Create a new Xcode project

Figura 6.2 Plantillas de proyecto


Como plantilla de proyecto seleccionar iOS > Application > Single View Application:

44

Curso iOS 8

Captulo 6 App: HolaMundo

Figura 6.3 Nuevo proyecto


Product Name y Class Prefix: HolaMundo
Company Identifier: es.cursoios
Devices: Universal
Language: Objective-C
Devices: Universal
Use Core Data: No
Seleccionar carpeta Developer/HolaMundo

6.3 Testear en Simulador

Para ejecutar la aplicacin, en la ventana de Xcode:


Seleccionar Scheme iPhone 6 Simulator
Botn Run o Cmd+R
El simulador es una aplicacin independiente y se puede cerrar sin cerrar Xcode:
Simulador iOS > Cmd+Q
Pero lo correcto es para parar la aplicacin desde Xcode:
45

Captulo 6 App: HolaMundo

Curso iOS 8

Botn Stop o Cmd+.


Como siempre con Cmd+Tab podemos cambiar de aplicacin.
En Simulador iOS podemos cambiar el dispositivo en el men Hardware > Dispositivo y
el tamao en Ventana > Escalar o Cmd+1, Cmd+2 y Cmd+3.

6.4 Crear controles en el Storyboard


En Xcode:

Ir al Navegador de Proyectos (el primer icono, con una carpeta, debajo del botn
Run)
Abrir proyecto HolaMundo (click en el tringulo)
Abrir carpeta HolaMundo
Seleccionar Main.storyboard

Seleccionar los controles UIKit que necesitamos en la librera de objetos, abajo a la derecha, y arrastrar dentro de nuestro View. Se puede buscar utilizando el campo inferior (p.ej.
label).
Crear un Label y a la derecha en las opciones cambiar Text a "Hola Mundo"
Crear un Text Field y colocarlo justo debajo del Label
46

Curso iOS 8

Captulo 6 App: HolaMundo

Crear un Button (Round Rect Button), colocarlo debajo del Text Field y cambiar su
Title a "Hola"
Volver a testear en el Simulador.

Rotacin del dispositivo, comprobar lo que ocurre al girar el dispositivo con Cmd+dch
y Cmd+izq.

47

Captulo 6 App: HolaMundo

Curso iOS 8

6.5 Crear conectores Outlet y Action

Ahora queremos que el campo de texto y el botn hagan algo, al pulsar el botn deber
cambiar el texto de la etiqueta por el que contenga el campo de texto. Para ello necesitamos aprender ms cosas de Xcode y Objective C, el lenguaje que se utiliza para programar.
En Xcode arriba a la derecha pulsamos el segundo botn Show the Assistant editor de manera que veamos a la vez dos editores:
1. El storyboard con nuestro View seleccionado
2. El fichero .h de nuestro ViewController
En el storyboard seleccionamos el control Label y pulsando Ctrl arrastramos hasta el editor de cdigo, entre las palabras clave @interface y @end para crear un Outlet con nombre label.
Un Outlet conecta a un View (control) con la propiedad del ViewController (clase de
cdigo) que utilizaremos para manejarlo.
Hacemos lo mismo con el campo de texto y el botn y los llamaremos texto y boton (sin
acento).
Veremos que crea el siguiente cdigo Objective C en HolaMundoViewController.h:
48

Curso iOS 8

#import <UIKit/UIKit.h>
@interface HolaMundoViewController :
@property (weak, nonatomic) IBOutlet
@property (weak, nonatomic) IBOutlet
@property (weak, nonatomic) IBOutlet
@end

Captulo 6 App: HolaMundo

UIViewController
UILabel *label;
UITextField *texto;
UIButton *boton;

Ahora en el editor de la derecha, justo arriba, cambiamos de archivo y seleccionamos HolaMundoViewController.m y vamos a crear una funcin para recibir el evento de tocar
el botn.
Seleccionamos el botn Hola e igual que antes, pulsamos Ctrl y arrastramos hasta el editor de cdigo, justo bajo la palabras clave @implementation, la nombramos accionHola y
Xcode crear este cdigo:
- (IBAction)accionHola:(id)sender {
}

Esto es un mtodo de Objective C, la primera diferencia con una funcin de C es que el mtodo empieza con un guin (menos) y la segunda es que el parmetro va a continuacin
del nombre separado por dos puntos.
Teniendo en cuenta que:
self es la referencia al objeto de clase HolaMundoViewController creado por el
sistema al visualizar esta pantalla del Storyboard.
label y texto son las referencia a los objetos label y campo de texto creados en el
Storyboard y referenciados mediante el outlet.
text es la propiedad que contiene el texto actual de dichos objetos.
Finalmente aadimos una lnea de cdigo como cuerpo de la funcin.
Podramos hacer esto, como en otros lenguajes orientados a objetos:
- (IBAction)accionHola:(id)sender {
self.label.text = self.texto.text;
}

Y de hecho en Objective C tambin funciona (y se denomina dot notation).


Pero vamos a aprovechar para introducir la sintaxis bsica que ilustra el sistema de paso
de mensajes en el que se basa Objective C:
49

Captulo 6 App: HolaMundo

Curso iOS 8

- (IBAction)accionHola:(id)sender {
[self.label setText:[self.texto text]];
}

Mediante la sintaxis de corchetes [objeto mensaje:parmetro] se enva un mensaje a


un objeto junto con un parmetro.
Enviar un mensaje sera casi equivalente a invocar una funcin, para entenderlo rpidamente, pero con algunas ventajas (p.ej. el objeto puede decidir qu hace con un mensaje
que no entiende, en vez de simplemente cascar el programa).
En este caso al objeto label se le enva el mensaje setText (establece tu texto), y el parmetro es otro mensaje (se pueden anidar) que consiste en decirle al objeto texto que devuelva el valor de su propiedad text.
Esta notacin que usa el punto (dot notation) slo sirve para acceder a propiedades, y
de hecho es un atajo para enviar los mensajes get y set.
En este caso podramos haber puesto:
[self.label setText:self.texto.text];

o
self.label.text = [self.texto text];

y tambin habra sido equivalente.


La razn de que exista la dot notation es doble: por comodidad y porque que se integra muy
bien visualmente con los struct de C (que no son objetos ni pueden recibir mensajes). Objective C tambin es C (se dice que Objective C es un superconjunto estricto de C) y ambos
se integran perfectamente. Por ejemplo se usa C y structs en cdigo que requiere mucha
velocidad (p.ej. Core Animation, para animaciones grficas).
Entonces, ahora HolaMundoViewController.m tendr este cdigo, con la versin ms
sencilla posible:
#import "HolaMundoViewController.h"
@interface HolaMundoViewController ()
@end
@implementation HolaMundoViewController
- (IBAction)accionHola:(id)sender {
self.label.text = self.texto.text;
}
50

Curso iOS 8

Captulo 6 App: HolaMundo

- (void)viewDidLoad
{
[super viewDidLoad];
}
@end

Y finalmente volvemos a testear en el simulador.

6.6 Notas

Por ahora no hay forma de esconder el teclado, para ello hay que explicar ms cosas y lo
haremos como ejercicio un poco ms tarde.

6.7 Ejercicio 1: delegate

Hacer que el teclado se esconda al tocar return.


En el storyboard asignar como delegate del control campo de texto a nuestro ViewController.

Figura 6.7 Asignar delegate


Botn derecho sobre el campo
Arrastrar el Outlet al smbolo que representa al ViewController
Hay que indicar que nuestro ViewController implementa el protocolo UITextFieldDelegate:
51

Captulo 6 App: HolaMundo

Curso iOS 8

@interface HolaMundoViewController : UIViewController


<UITextFieldDelegate>

Hay que implementar el mtodo delegado textFieldShouldReturn: as:


-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[texto resignFirstResponder];
return YES;
}

6.8 Ejercicio 2: nuevo mtodo

Hacer que al tocar return tambin cambie el texto de la etiqueta adems de esconder el
teclado.
-(void)cambiaTexto {
self.label.text = self.texto.text;
}
- (IBAction)accionHola:(id)sender {
[self cambiaTexto];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self cambiaTexto];
[texto resignFirstResponder];
return YES;
}

52

Captulo 7

Objective C
7.1 Introduccin

Objective C (http://en.wikipedia.org/wiki/Objective-C) aade a C una sintaxis basada en


SmallTalk (http://en.wikipedia.org/wiki/Smalltalk) (1972-1980) para el uso de objetos. En
este "sabor" de orientacin a objetos se denomina paso de mensajes a la comunicacin
entre estos (y es similar a la invocacin de un mtodo).
Objective C es un superconjunto estricto de C, es decir que Objective C contiene a C pero
no al contrario. As que cualquier programa C que escribamos tambin es un programa
Objective C vlido, pero no ocurre lo mismo al revs.
C++ (originalmente C con clases y renombrado as en 1983) y Objective C (lanzado tambin
en 1983) fueron los dos caminos independientes que sigui el mundo de C para incluir este
nuevo paradigma de la orientacin a objetos. Inicialmente C++ tuvo mucho ms xito y
posteriormete Java (lanzado en 1995) an ms.
Pero al abandonar Steve Jobs Apple y fundar su nueva empresa NeXT
(http://en.wikipedia.org/wiki/NeXT) (en 1986), Objective C fue seleccionado en 1988 como
base de su sistema operativo, que se llamaba NEXTSTEP (http://en.wikipedia.org/wiki/
NEXTSTEP) y estaba basado en Unix.
Al comprar Apple a NeXT y regresar Steve Jobs, volvi con esta tecnologa y el sistema
operativo acab convirtiendose en la base de Mac OS X. Posteriormente los nuevos productos que sac Apple (iPhone e iPad) utilizaron una versin reducida de OS X que llamamos iOS (aunque originalmente fuera iPhone OS).

53

Captulo 7 Objective C

Curso iOS 8

7.2 Objective C es C
7.2.1 Comentarios // y /* */
// Comentar hasta el final de la lnea
/* Comentar un bloque */

7.2.2 Tipos bsicos int, float y double


int entero = 100;
float flotante = 1.23f;
double doble_precision = 12345.6789;
char letra = 'A';
char texto[] = "Texto"; // String de C y array de char Peligro! Nunca
lo usaremos
char *puntero = texto; // Mucho peligro!

7.2.3 Escribir en la consola: printf


printf("Nmero entero %d\n", entero);
printf("Nmero flotante %f o %g\n", flotante, flotante);
printf("Nmero flotante con doble precisin %f o %g\n", doble_precision,
doble_precision);
printf("Letra %c\n", letra);
printf("Texto %s\n", texto);
printf("Texto referenciado por puntero %s\n", puntero);

7.2.3.1 Especificadores de formato


%d entero (int)
%f flotante o doble precisin (float o double)
%g flotante o doble precisin sin decimales si son 0
%c carcter (char)
%s string de C (es un array de char terminado en 0) Peligro! Nunca lo usaremos

7.3 Objective C aade objetos a C


7.3.1 Primer objeto, String de Objective C, NSString (inmutable)
NSString *nombre = @"Fernando";

7.3.2 Escribir en la consola: NSLog


NSLog(@"Nmero entero %d", entero);
NSLog(@"Nmero flotante %f o %g", flotante, flotante);
NSLog(@"Nmero flotante con doble precisin %f o %g", doble_precision,
54

Curso iOS 8

Captulo 7 Objective C

doble_precision);
NSLog(@"Letra %c", letra);
NSLog(@"String de C %s", texto);
NSLog(@"String de Objective C %@", nombre);

7.3.2.1 Especificadores de formato


Los mismos que printf
%@ Especificador de formato para toda clase de objetos, enva el mensaje
description

7.4 Objective C aade el tipo BOOL

En las condiciones de C cero es falso y todo lo dems es verdad.


Objective C aade el tipo BOOL con los valores YES y NO, que equivalen a 1 y 0.
BOOL verdad = YES;
BOOL falso = NO;
NSLog(@"Booleano %d y %d", verdad, falso);

7.5 Objective C usa las sentencias y operadores de


C
7.5.1 if y else
if(verdad) {
NSLog(@"Verdad");
}
if(falso) {
NSLog(@"Verdad");
} else {
NSLog(@"Falso");
}

7.5.2 Operador ternario ?:


NSLog(@"Verdad = %@", verdad ? @"YES" : @"NO");
NSLog(@"Falso = %@", falso ? @"YES" : @"NO");

7.5.3 Objeto nulo de Objective C: nil


En Objective C cuando se declara una variable de cualquier tipo objeto se inicializa a nil
cuyo valor es exactamente 0. Por ello se puede testear la existencia de un objeto directamente en cualquier condicin, p.ej. con if.

55

Captulo 7 Objective C

Curso iOS 8

NSString *nada; // NSString *nada = nil;


if(nada) {
NSLog(@"Existe nada %@", nada);
} else {
NSLog(@"No existe nada %@", nada);
}
NSLog(@"nada es %d", (int) nada);

Una propiedad interesante del valor nil es que se le puede enviar cualquier mensaje y
siempre devolver nil sin cascar el programa.

7.5.4 switch
int n = 3;
switch(n) {
case 1:
NSLog(@"Uno");
break;
case 2:
NSLog(@"Dos");
break;
case 3:
NSLog(@"Tres");
break;
}

7.5.5 Operadores + - * / % ++ - + suma


- resta
* multiplicacin
/ divisin
% mdulo
++ pre y post incremento
-- pre y post decremento
int a = 4;
int b = 3;
NSLog(@"suma %d", a + b);
NSLog(@"resta %d", a - b);
NSLog(@"multiplicacin %d", a * b);
NSLog(@"divisin %f", (float) a / b);
56

Curso iOS 8

Captulo 7 Objective C

NSLog(@"mdulo %d", a % b);


NSLog(@"pre-incremento %d", ++a);
NSLog(@"post-incremento %d", b++);
NSLog(@"pre-decremento %d", --a);
NSLog(@"post-decremento %d", b--);

7.5.6 while
int j = 10;
while(j--) {
NSLog(@"j es %d", j);
}

7.5.7 for
for(int i = 0; i != 10; ++i) {
NSLog(@"i es %d", i);
}

7.6 Vocabulario bsico de orientacin a objetos


Clase (Class): la descripcin o plantilla usada por un conjunto de objetos (parecido a
un tipo)
Instancia (Instance): un objeto concreto (manifestacin de una clase)
Mensaje (Message): se enva a un objeto para hacerlo actuar (y es la base de
SmallTalk y Objective C)
Mtodo (Method): cdigo invocado por un mensaje (funciones)
Variables de instancia: lugar propio (exclusivo) de un objecto donde almacena sus
datos
Propiedades (Properties): variables de instancia junto con sus funciones get y set
(para conseguir encapsulacin)
Superclase/subclase (superclass/subclass): Herencia simple (es un)
Protocolo (Protocol): mtodos no especficos de una clase (acta como un) (herencia
mltiple)

57

Captulo 7 Objective C

7.7 Creacin de clases en Objective C

Figura 7.1 Xcode > File > New > File...

Figura 7.2 Plantilla nueva clase: Cocoa Touch Class

58

Curso iOS 8

Curso iOS 8

Captulo 7 Objective C

Figura 7.3 Dilogo nueva clase: Subclase de NSObject

Figura 7.4 Nueva clase archivos .h y .m


.h Archivo de cabecera o header: declaracin pblica del interfaz
.m Archivo de implementacin: declaracin privada del interfaz y cdigo con la
implementacin
59

Captulo 7 Objective C

Curso iOS 8

7.7.1 Qu va en cada archivo?


@interface MyClass : MySuperclass ... @end interfaz pblica, solo en
cabecera .h
@interface MyClass() ... @end interfaz privada, solo en implementacin .m
@implementation ... @end cdigo con la implementacin solo en .m
#import solo se pueden importar archivos de cabecera .h

7.8 Propiedades
7.8.1 Declaracin de una propiedad
@property (strong, nonatomic) NSString *nombre;

@property (strong o weak, nonatomic) <tipo que es un puntero a un


objeto> <nombre propiedad>

strong o weak especifica el tipo de puntero para olvidarnos de gestionar la


memoria usando ARC (automatic reference counting)
nonatomic especifica getter y setter no atmicos (ms rpidos pero no son threadsafe), no nos dar problemas y lo usaremos siempre en este curso
Cuando declaramos una propiedad, adems de asignar espacio para la variable de instancia (sintetizar), genera automticamente los mtodos setter y getter bsicos, que nosotros
podramos modificar.
Importante La propiedad todava estara a nil y debera ser inicializada en algn momento, p.ej. al inicializar la clase.

7.8.2 propiedad o @property = @synthesize + setter y getter


En caso de implementar ambos setter y getter es necesario sintetizar la variable de instancia, no lo hace automticamente ya que podramos querer una propiedad calculada.
Habitualmente a la variable de instancia se le asigna un nombre igual que a la propiedad
pero empezando por _:
@synthesize <nombre propiedad> = _<nombre propiedad>;
// Sintetizar variable de instancia, solo si definimos setter y getter
@synthesize nombre = _nombre;
// Setter
60

Curso iOS 8

Captulo 7 Objective C

- (void)setNombre:(NSString *)nombre
{
_nombre = nombre;
}
// Getter
- (NSString *)nombre
{
return _nombre;
}

Mejor que variables de instancia solas (lazy instantiation, chequear consistencia,


actualizar UI, etc)

7.8.3 Instanciacin lazy


// Getter que asigna valor cuando no existe
- (NSString *)nombre
{
if (!_nombre) _nombre = @"Mi nombre";
return _nombre;
}

@property (getter=<getter name>) ... renombrar el getter


@property (readonly) ... en interfaz pblico y @property (readwrite)
... en interfaz privado: declarar una propiedad protegida externamente contra
escritura
Invocar setter y getter usando dot notation, p.ej. self.cards = ... o if (rank >
self.rank) ...

7.9 Tipos y memoria


Tipos: MyClass *, BOOL (YES o NO), int, NSUInteger, etc. (id pendiente explicar)
Todos los objetos viven en el heap (montn) (solo tenemos punteros hacia ellos)
El almacenamineto de objectos en el heap se gestiona automticamente (mediante
ARC y declaraciones strong y weak)
Lazy instantiation (usar el getter de una @property para hacer alloc init del objeto
"bajo demanda", no lo hacemos siempre)
Si un puntero tiene el valor nil (p.ej. 0), significa que el puntero no apunta a nada

61

Captulo 7 Objective C

Curso iOS 8

7.10 Creacin de objetos en Objective C


7.10.1 Inicializacin mediante alloc e init
NSString *algo; // Declaracin de algo. Ahora es nil
algo = [[NSString alloc] initWithFormat:@"%@", @"Algo"]; // Inicializado
if(algo) {
NSLog(@"Existe algo = %@", algo);
} else {
NSLog(@"No existe algo = %@", algo);
}

7.10.2 Inicializacin mediante mtodo factora


NSString *otro; // Declaracin de otro. Ahora es nil
otro = [NSString stringWithFormat:@"%@", @"Otro"]; // Inicializado
if(otro) {
NSLog(@"Existe otro = %@", otro);
} else {
NSLog(@"No existe otro = %@", otro);
}

7.11 Mtodos

Se trata de funciones que pertenecen a un objeto (o clase).


Los mtodos de instancia pueden acceder:
A sus propiedades: mediante self.propiedad que ejecuta el getter
A sus variables de instancia: mediante _propiedad que no ejecuta el getter
Existen mtodos de instancia y de clase:
Si son de instancia comienzan por Si son de clase comienzan por +
Los mtodos se declaran en el interfaz (pblico o privado) y se implementan en el archivo
.m:
@interface MyClass : NSObject
// Declaracin
- (void)miMetodoDeInstancia;
+ (void)miMetodoDeClase;
@end
62

Curso iOS 8

Captulo 7 Objective C

@implementation MyClass
- (void)miMetodoDeInstancia
{
// Cdigo
}
+ (void)miMetodoDeClase
{
// Cdigo
}
@end

Declarar y definir mtodos de instancia - (int)comparar:(NSArray


*)otrasCartas

Declarar y definir mtodos de clase + (NSArray *)palosValidos

7.11.1 Parmetros
En Objective C los parmetros tienen nombre y se intercalan en la declaracin:
// Sin parmetros
- (void)miMetodoSinParametros
{
// Cdigo
}

El nombre del mtodo (o selector) es miMetodoSinParametros


// Con un parmetro
- (void)miMetodoConNombre:(NSString *)nombre
{
// Hacer algo con nombre
}

El nombre del mtodo (o selector) es miMetodoConNombre:, incluye los dos puntos


// Con dos parmetros
- (void)miMetodoConNombre:(NSString *)nombre yApellido:(NSString
*)apellido
{
// Hacer algo con nombre y apellido
}

El nombre del mtodo (o selector) es miMetodoConNombre:yApellido:

63

Captulo 7 Objective C

Curso iOS 8

// Con tres parmetros


- (void)miMetodoConNombre:(NSString *)nombre primerApellido:(NSString
*)apellido1 segundoApellido:(NSString *)apellido2
{
// Hacer algo con nombre, apellido1 y apellido2
}

El

nombre

del

mtodo

(o

selector)

es

miMetodoConNom-

bre:primerApellido:segundoApellido:

7.12 Mensajes

Se denomina mensaje a la invocacin de un mtodo. Ejemplos:


Invocar mtodos de instancia, mediante un mensaje: [miArray
addObject:unObjeto]

Invocar mtodos de clase, mediante un mensaje: unsigned int rank =


[PlayingCard maxRank]

El nombre del mtodo y sus parametros se intercalan [deck addCard:aCard


atTop:YES]

La sintaxis bsica para enviar un mensaje es:


[object method];
[object methodWithInput:input];

Los mensajes pueden devolver un valor:


output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];

Tambin se puede enviar mensajes a una clase, que es una forma habitual de crear objetos.
El siguiente ejemplo enva el mensaje string a la clase NSString, que devuelve un nuevo
objeto NSString:
id myObject = [NSString string];

El tipo id indica que la variable myObject puede hacer referencia a cualquier tipo de objeto, de forma que la clase real y los mtodos que implementa no se conocen cuando se compila la aplicacin.
En este ejemplo est claro que el tipo del objeto ser NSString, as que podemos cambiarlo:

64

Curso iOS 8

Captulo 7 Objective C

NSString* myString = [NSString string];

Ahora es una variable NSString, de forma que el compilador nos avisar si intentamos
usar mtodos que NSString no implementa.
Observa que el tipo es realmente NSString* (con asterisco). En Objective C todas las variables que referencian objetos son punteros. El tipo id est predefinido como un tipo puntero, as que no lleva asterisco.

7.12.1 Mensajes anidados


En muchos lenguajes se pueden anidar llamadas a funciones as:
funcion1(funcion2());

El resultado de llamar a funcion2 se pasa como parmetro a funcion1. En Objective C se


anidan mensajes as:
[NSString stringWithFormat:[prefs format]];

No se recomienda anidar ms de dos mensajes en una sola lnea, o pronto el cdigo se volver difcil de seguir.

7.12.2 Mtodos con varios parmetros


Muchos mtodos requieren varios parmetros. En Objective C, al definir un mtodo el
nombre se divide en varios segmentos as:
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;

Se llamar a este mtodo por ejemplo as:


BOOL result = [myData writeToFile:@"/tmp/log.txt" atomically:NO];

Esto no son solo parmetros con nombre. El nombre del mtodo es realmente writeToFile:atomically:.

7.13 Referencias
http://cocoadevcentral.com/d/learn_objectivec/
Apple: Programming with Objective-C (https://developer.apple.com/library/ios/
documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/
Introduction.html)

65

Esta pgina se ha dejado vaca a propsito

66

Captulo 8

App: Cuestionario
Crear una app Cuestionario que mostrar una pregunta y la respuesta vaca.
Al pulsar sobre Ver Respuesta mostrar la respuesta.
Al pulsar sobre Siguiente Pregunta mostrar la siguiente pregunta (y la respuesta
vaca).
Preguntas:
Qu es iOS?
Qu es MVC?
Qu es Objective C?
Respuestas (atencin estn desordenadas):
Model-View-Controller Modelo-Vista-Controlador
Un superconjunto estricto de C
El Sistema Operativo de iPhone e iPad

67

Captulo 8 App: Cuestionario

8.1 Simulador

68

Curso iOS 8

Curso iOS 8

Captulo 8 App: Cuestionario

8.2 Storyboard

8.3 Cdigo de ayuda


#import "ViewController.h"
@interface ViewController ()
@property NSUInteger indice;
@property (nonatomic, strong) NSArray *preguntas;
@property (nonatomic, strong) NSArray *respuestas;
@end
self.preguntas = @[
@"Qu es iOS?",
@"Qu es MVC?",
@"Qu es Objective C?"
];
self.respuestas = @[
@"El Sistema Operativo de iPhone e iPad",
@"Model-View-Controller\nModelo-Vista-Controlador",
@"Un superconjunto estricto de C"
];
self.indice = 2;
self.respuesta.text = self.preguntas[self.indice];
//self.respuesta.text = [self.preguntas objectAtIndex:self.indice];

69

Captulo 8 App: Cuestionario

8.4 Tarea 1: Proyecto

Curso iOS 8

Crear un nuevo proyecto en Xcode con iOS y Objective C llamado Cuestionario.

8.5 Tarea 2: Storyboard

Crear un Storyboard con los siguientes elementos:


label Pregunta
botn Ver Respuesta
label Respuesta
botn Siguiente Pregunta

8.6 Tarea 3: Outlets y Actions

Crear un outlet independiente para cada label y una action para cada botn

8.7 Tarea 4: Arrays

Crear dos arrays: preguntas y respuestas


Preguntas:
Qu es iOS?
Qu es MVC?
70

Curso iOS 8

Captulo 8 App: Cuestionario

Qu es Objective C?
Respuestas (atencin estn desordenadas):
Model-View-Controller Modelo-Vista-Controlador
Un superconjunto estricto de C
El Sistema Operativo de iPhone e iPad

8.8 Tarea 5: Propiedad indice

Crear una propiedad indice de tipo NSInteger e inicializarla a cero.

8.9 Tarea 6: Inicializacin

Al arrancar la aplicacin mostrar la primera pregunta y la respuesta vaca.

8.10 Tarea 7: Ver Respuesta

Al pulsar sobre Ver Respuesta mostrar la respuesta.

8.11 Tarea 8: Siguiente Pregunta


Al pulsar sobre Siguiente Pregunta mostrar la siguiente pregunta (y la respuesta
vaca o con una ?).
Si pulsamos sobre Siguiente Pregunta y estamos en la ltima pregunta
pasaremos a la primera.

8.12 Tarea extra: Ms preguntas

Cambiar los arrays de preguntas y respuestas para aadir ms.


Preguntas:
Qu es iOS?
Qu es Xcode?
Qu es Swift?
Qu es Objective C?
Qu es MVC?
Qu es un Framework?
Qu es UIKit?
Qu es un Storyboard?
71

Captulo 8 App: Cuestionario

Curso iOS 8

Qu es un Outlet?
Qu es un Target-Action?
Respuestas (atencin estn desordenadas):
Una propiedad del controlador que referencia a un objeto vista del Storyboard
El lenguaje tradicional de desarrollo de Apple
El IDE de desarrollo de Apple
El Kit de Interfaz de Usuario (User Interface Kit)
Un mecanismo por el que el controlador puede recibir eventos de las vistas del
Storyboard
El nuevo lenguaje de desarrollo de Apple
El patrn de diseo Modelo-Vista-Controlador (Model-View-Controller)
El Sistema Operativo de iPhone e iPad
Un paquete que agrupa componentes de iOS
Una herramienta para crear interfaces de usuario completas, incluyendo
navegacin

8.13 Tarea extra: Anterior Pregunta


Aadir un botn Anterior Pregunta
Al pulsar sobre Anterior Pregunta mostrar la anterior pregunta (y la respuesta
vaca o con una ?).
Si pulsamos sobre Anterior Pregunta y estamos en la primera pregunta
pasaremos a la ltima.

72

Captulo 9

Gestin de la memoria
9.1 ARC

En un escenario con ARC marcamos las propiedades como:


strong
weak

9.1.1 Strong
El sistema se encarga de:
Liberar la memoria cuando los contadores de punteros strong llegan a 0
Adems, cualquier puntero weak automticamente se cambia a nil para evitar el
cuelgue de nuestro programa al acceder a un lugar de la memoria que ya no apunta
a un objeto.
Los punteros strong indican la propiedad del objeto:
Cuando voy a crear un objeto pienso: "este objeto es mo entonces es strong".
En caso de duda usar siempre strong.
Muchsimo cuidado con crear un objeto que solo te pertenece a ti como weak. Tras
crearlo instantaneamente desaparecer de la memoria y el puntero ser nil.
Un objeto puede pertenecer a varios otros objetos a la vez, no hay problema.

73

Captulo 9 Gestin de la memoria

Curso iOS 8

Salvo este: Dos objetos no pueden pertenecerse a s mismos a la vez, esto creara un ciclo de
punteros strong y nunca podran liberarse de la memoria. Habramos causado un Leak.
Si llenamos imprudentemente la memoria con objetos que no se pueden liberar, tarde o
temprano nuestra aplicacin (y el sistema) cada vez tendr menos memoria para trabajar
y nuestra aplicacin ser terminada por el sistema.

9.1.2 Weak
Para prevenir este problema cuando un objeto no nos pertenece y sabemos que vamos a
crear un ciclo utilizamos un puntero weak.
Cuando el objeto desaparezca de la memoria nuestro puntero weak ser puesto a nil y cualquier mensaje enviado a nil devuelve 0, lo cual no causar problemas catastrficos.
Cosa que s ocurrira si enviamos un mensaje a un objeto utilizando un puntero que ya no
apunta a un objeto de ese tipo (la memoria ha sido liberada y posiblemente reutilizada para otros objetos). Nuestro programa ser terminado con una excepcin de violacin de acceso de memoria... o algo peor.

9.2 Sin ARC

Al crear propiedades sin ARC las marcamos como:


retain
assign

9.2.1 Retain
retain es similar a strong, pero hay que liberar la memoria manualmente.

Para hacerlo hay dos formas:


mensaje explcito release que libera la memoria en ese momento.
mensaje autorelease que aade el objeto a un AutoReleasePool y se liberarn de
la memoria cuando termine su contexto (si no lo han sido antes).
9.2.1.1 Ejemplo @autoreleasepool
En el archivo main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
74

Curso iOS 8

Captulo 9 Gestin de la memoria

@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}

9.2.2 Assign
assign es como weak, pero peor... el puntero no se establecer automticamente a nil al li-

berar la memoria. Esto puede causar un crash si despus intentamos enviar un mensaje a
ese puntero.

75

Esta pgina se ha dejado vaca a propsito

76

Captulo 10

MVC

MVC es una estrategia para disear aplicaciones orientadas a objetos.1


(http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)
La idea principal es dividir todos los objetos de nuestra aplicacin en tres categoras o
"campos": Model, View y Controller.
La intecin es separar las responsabilidades de los objetos para facilitar la comprensin de
la aplicacin y tambin la capacidad de reusar componentes.
77

Captulo 10 MVC

Curso iOS 8

10.1 Model

Model o Modelo: Lo que tu aplicacin es o hace (pero no cmo se visualiza)


Su responsabilidad es contener la informacin de nuestra aplicacin (sus datos) y las reglas que los afectan (a veces llamadas bussiness rules o lgica de negocio).
Una ventaja de separar el modelo de la visualizacin es que podemos tener visualizaciones
diferentes para un mismo modelo, por ejemplo para iPhone e iPad.

10.2 Controller

Controller o Controlador: Cmo tu modelo es presentado al usuario (lgica UI)


Digamos que el trabajo del controlador es poner el modelo en la pantalla.
El controlador pregunta al modelo los datos que debe representar y enva ordenes a la vista (donde residen sus "esclavos") para hacerlo.

10.3 View

View o Vista: Los objetos (controles) que presentan la informacin (botones, texto, imgenes...) utilizados por el controlador para representar el modelo.
Estos objetos sern tan genricos como sea posible. Muchas veces utilizaremos los que Apple proporciona tal cual y sin cambiar nada: UIButton, UILabel, UIImageView...
Cuando estudiemos los frameworks de iOS (como UIKit o MapKit) estaremos estudiando
estos objetos y cmo se utilizan. Por ejemplo UIView, el objeto ms genrico de todos, sera
algo tan sencillo como como un rectngulo en el que dibujar y que puede contener otros.
Una vista puede contener a otras, por ejemplo UITableView es un UIScrollView que contiene celdas de tipo UITableViewCell que a su vez podrn tener texto e imgenes.

10.4 Comunicacin

Una vez que los objetos estn divididos en sus tres categoras, lo importante es definir cmo se comunican entre ellos (y cmo no deben hacerlo).
Reglas:
1. El controlador se comunica siempre con su modelo y su vista para hacer su trabajo
(atencin, esta comunicacin no es bidireccional)
Outlet: es una propiedad en el controlador que ste utiliza para comunicarse con su
vista
78

Curso iOS 8

Captulo 10 MVC

2. El modelo y la vista nunca se comunican entre ellos (totalmente prohibido)


Los componentes utilizados para construir la vista no seran completamente reutilizables.
3. Se comunica la vista con el controlador? No libremente, lo hace de forma estructurada.
Target-Action: Cuando ocurra una accin (p.ej. se pulse un botn) se establece una
funcin (target) al que enviar un mensaje con los datos
Delegation: Para otros eventos (p.ej. viewWillAppear, viewDidAppear, shouldAllow) el controlador se establece a s mismo como el delegado (delegate) de esa vista
y recibir todos los mensajes que implemente. A esto se denomina implementar un
protocolo (protocol)
Datasource: Ya que las vistas no poseen los datos que visualizan necesitan que alguien
implemente un protocolo para obtenerlos (p.je. dataAt, count). Casi siempre ser su
controlador y nunca el modelo. El controlador interpreta y formatea los datos del
modelo para representarlos en la vista.
4. Se comunica el modelo con el controlador? No, porque es (debera ser) independiente del interfaz.
Entonces qu ocurre cuando se actualiza la informacin? Se lanzan notificaciones a
las que el controlador debe suscribirse cuando le interesan. KVO (Key Value Observing)
5. Cmo se organiza una aplicacin complicada? Mediante un rbol de MVCs donde
tambin hay lmites a la comunicacin.
A veces la vista de un controlador es otro MVC. Se ve claramente en iPhone al poseer
una pantalla ms pequea que iPad o Mac. Lo que en estos hubiera sido un control
de fecha en iPhone puede ser una nueva pantalla. Pero la comunicacin entre componentes sigue unos lmites predecibles (no se comunican todos con todos).

79

Esta pgina se ha dejado vaca a propsito

80

Captulo 11

App: Calculadora
Crear una app Calculadora como la siguiente:

81

Captulo 11 App: Calculadora

Curso iOS 8

11.1 Ayuda
11.1.1 Cmo se obtiene el ttulo de un botn
Como sabemos que el control es un UIButton * lo mejor es cambiar la declaracin para
poder acceder a sus propiedades
- (IBAction)pressDigito:(id)sender
- (IBAction)pressDigito:(UIButton *)sender
{
NSString *digito = sender.currentTitle;
}

82

Curso iOS 8

Captulo 11 App: Calculadora

11.1.2 Convertir un string a un valor double


NSString *miValor = @"222";
double miNumero = [miValor doubleValue];

11.1.3 Comparar dos strings por igualdad


NSString *a = @"a";
NSString *b = @"b";
if([a isEqualToString:b]) {
// ...
}

11.1.4 NSMutableString
Cmo se declara un string mutable?
@property (strong, nonatomic) NSMutableString *display;

Cmo se inicializa?
self.display = [NSMutableString stringWithCapacity:20];

Cmo se aade un string detrs de uno mutable?


[self.display appendString:digito];

11.2 Tarea 1: Proyecto

Crear un nuevo proyecto en Xcode con iOS y Objective C llamado Calculadora.

11.3 Tarea 2: Storyboard

Crear un Storyboard con los siguientes elementos:


label display
botones numricos 1 2 3 4 5 6 7 8 0
botn de punto decimal .
botones de operaciones + - * / %
botn igual =
botn borrar C

11.4 Tarea 3: Modelo

Crear una clase Calculadora y aadirla al proyecto.


83

Captulo 11 App: Calculadora

11.5 Tarea 4: Propiedades del modelo


Definir en el modelo estas propiedades:
display
operador
operando1
ultimaEntradaEsOperador
Realizar la declaracin de las propiedades con sus tipos adecuados.

11.6 Tarea 5: Mtodos del modelo


Definir en el modelo estos mtodos:
inputDigito
inputOperador
inputIgual
inputBorrar
displayValor
Este debera ser el interfaz pblico de dicha clase:
-

(NSString *)displayValor;
(void) inputDigito:(NSString *)digito;
(void) inputOperador:(NSString *)operador;
(void) inputIgual;
(void) inputBorrar;

11.7 Tarea 6: Controlador


El controlador debe:

Recibir las pulsaciones de teclas y enviarlas al modelo.


Visualizar en el display el valor que devuelva el modelo.
Estas deberan ser las acciones a las que responde el controlador:
84

(IBAction)pulsarDigito:(UIButton *)sender { ... }


(IBAction)pulsarOperador:(UIButton *)sender { ... }
(IBAction)pulsarIgual:(UIButton *)sender { ... }
(IBAction)pulsarBorrar:(UIButton *)sender { ... }

Curso iOS 8

Curso iOS 8

Captulo 11 App: Calculadora

11.8 Tarea 7: Conectar outlets y acciones

Realizar las conexiones necesarias entre la pantalla del StoryBoard y el archivo ViewController.

11.9 Tarea 8: Conectar el controlador con el modelo


El controlador necesita un objeto Calculadora para poder comunicarse con l.
Crear una variable calculadora de tipo Calculadora.

11.10 Tarea 9: Implementar el modelo

Implementar las funciones del modelo que ahora estn vacas para poder gestionar:
El nmero que debe aparecer en el display y la funcin para devolverlo
Las diferentes operaciones de entrada de datos

85

Esta pgina se ha dejado vaca a propsito

86

Captulo 12

Documentacin
12.1 Xcode
12.1.1 Quick Help
Situar el cursor sobre una palabra con el panel Quick Help seleccionado

Figura 12.1 Quick Help

12.1.2 Ayuda contextual


Con la tecla Option pulsada pasar el ratn por una palabra y hacer click

87

Captulo 12 Documentacin

Curso iOS 8

Figura 12.2 Ayuda contextual

12.1.3 Documentacin en el Organizer


Toda la documentacin est disponible desde el Organizer, en la pestaa Documentacin.

Figura 12.3 Documentacin en Organizer

12.2 Internet

Tambin en Internet en la iOS Developer Library de Apple:


https://developer.apple.com/library/ios/navigation/

88

Captulo 13

Debugger
13.1 All exceptions breakpoint

Aadir breakpoint cada vez que se produzca una excepcin


En el panel izquierdo, abrir item Breakpoints.
En la esquina inferior izquierda del panel pulsar +.
Add Exception Breakpoint: All, On Throw.

13.2 Visualizar valores


Mouseover
Llamar a getter en GBD:
(lldb) print [self nombrePropiedad]

Cuidado porque no se puede utilizar dot notation en el depurador, hay que utilizar el mensaje get.
Print object description
(lldb) po [self nombrePropiedad]

Aqu tambin hay que utilizar el mensaje get.

89

Captulo 13 Debugger

13.3 Condicional breakpoint


Edit breakpoint
Condition: result == 0

90

Curso iOS 8

Captulo 14

App: Cartas
14.1 Storyboard

91

Captulo 14 App: Cartas

Curso iOS 8

14.2 Recursos grficos

14.2.1 Imgenes de figuras


Cartas grficas (/descargas/Cartas.zip)

14.3 Modelo
14.3.1 Tarea 1
Copiar las clases de las Lecture 1 y 2 de Stanford:
Card
Deck
PlayingCard
PlayingCardDeck

14.4 Controlador
14.4.1 Tarea 2
Usando los recursos grficos crear un botn que simula una carta.

14.4.2 Tarea 3
Tocando la carta alternar entre la parte anterior y posterior.

14.4.3 Tarea 4
Crear una propiedad deck de tipo Deck *
Inicializarla con una baraja completa PlayingCardDeck
Tocando la carta pasar por todas las cartas de la baraja (sin repetir ninguna)
92

Curso iOS 8

Captulo 14 App: Cartas

14.4.4 Tarea 5
Desarrollar el juego de cartas de la Lecture 3 de Stanford:
Situar 12 cartas en el storyboard
Copiar la clase CardMatchingGame y modificar el controlador

14.4.5 Tarea 6
Modificar el juego para:
16 cartas
Solo cartas A, J, Q y K
Solo emparejar por mismo color y figura

93

Captulo 14 App: Cartas

Curso iOS 8

14.4.6 Tarea 7
Modificar el juego con un botn nuevo que reinicia la puntuacin a 0 y reparte nuevas
cartas.

14.4.7 Tarea 8
Aadir un label que indique:
El valor de las cartas: A de corazones y K de corazones
El resultado de la ltima correspondencia: Coincidencia de palo
Los puntos otorgados: 4 puntos o 2 puntos de penalizacin

14.4.8 Tarea 9
Modificar el juego para emparejar todos los A, J, Q o K a la vez (los cuatro palos).

14.5 Ayuda
@property (strong, nonatomic) Deck *deck;
- (Deck *)deck
{
if (!_deck) _deck = [self createDeck];
return _deck;
}
- (Deck *)createDeck
{
return [[PlayingCardDeck alloc] init];
}

94

Captulo 15

Paths y URLs
15.1 Path

Un path es simplemente un NSString que representa una ruta en el sistema de ficheros


hasta un fichero o directorio.

15.1.1 iOS es Unix


El sistema de ficheros de iOS funciona como el de Unix:
Se trata de un rbol de directorios y ficheros cuyo nodo raz se denomina root y se
representa con /.
El directorio actual se representa con un punto: .
El directorio padre del actual se representa con dos puntos seguidos: ..
Es multiusuario y con permisos separados para: el propietario, su grupo y el resto
del universo en cada directorio y fichero.
Estos permisos son bsicamente de: escritura, lectura y ejecucin (aunque hay ms)
El directorio del usuario actual se representa con la tilde: ~
En un path los componentes de la ruta se separan tambin mediante /, por ejemplo:
/directorio1/directorio2/fichero1

Si deseamos entrar al sistema de ficheros del Simulador de iOS deberemos imprimir en la


consola un path desde una de nuestras aplicaciones, p.ej.:
95

Captulo 15 Paths y URLs

Curso iOS 8

NSString *cachePath =
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES) lastObject];
NSLog(@"path: %@", cachePath);

Y luego entrar en la aplicacin de Mac OS X Terminal que da acceso al terminal de Unix.


Podemos abrirla usando Cmd+Space y escribiendo Terminal.

15.1.2 Comandos bsicos de Unix


Una vez dentro del terminal de Unix los comndos bsicos para navegar por el sistema de
ficheros seran:
pwd (Print Working Directory): Para imprimir el directorio en el que nos
encontramos
cd + path (Change Directory): Para cambiar al directorio indicado
ls o ls -l (List): Para imprimir la lista de directorios y ficheros del directorio en el
que nos encontramos
cat + path (Catalogue): Para imprimir el contenido de un fichero si est formato
texto (si el formato es binario no funcionar)
rm + path (Remove): Para eliminar un fichero

15.2 URLs

URL (http://en.wikipedia.org/wiki/Url) quiere decir: localizador de recurso uniforme


y sirve exactamente igual para direciones o rutas en Internet o en el sistema de ficheros
local.
De forma que tambin se puede utilizar una URL para representar un path, que a veces en
iOS se denominan FileURL. La tendencia actual en iOS es que cada vez se utilizan ms FileURL y menos Paths.

15.2.1 Conversiones entre Path y FileURLs


Para crear un FileURL a partir de un path utilizamos el mensaje fileURLWithPath:
NSURL *cache = [NSURL fileURLWithPath:cachePath];

Para convertir un FileURL de nuevo a un path utilizamos el mensaje path:


NSString *cachePath = [cache path];

96

Curso iOS 8

Captulo 15 Paths y URLs

15.2.2 Uso de componentes con FileURLs


Para separar un FileURL por componentes utilizamos el mensaje pathComponents que
devuelve un NSArray:
NSString *cachePath =
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES) lastObject];
NSURL *cache = [NSURL fileURLWithPath:cachePath];
NSArray *components = [cache pathComponents];
NSLog(@"pathComponents %@", components);

Para aadir un componente a un FileURL utilizamos el mensaje URLByAppendingPathComponent sobre otro FileURL:
NSURL *cacheMini = [cache URLByAppendingPathComponent:@"mini"
isDirectory:YES];

Para aadir un componente a un path utilizamos el mensaje stringByAppendingPathComponent sobre otro path (de tipo NSString):
NSString *cachePathMini = [cachePath
stringByAppendingPathComponent:@"mini"];

Para recomponer una URL usando algunos de los componentes de otra podemos utilizar
el mensaje stringWithFormat:
NSArray *components = [foto pathComponents];
NSString *fotoGrandeFilename = [NSString stringWithFormat:@"%@_%@_%@",
components[1], components[2], @"4.jpg";

15.2.3 Operaciones sobre el sistema de ficheros


Para realizar operaciones sobre el sistema de ficheros necesitamos crear un objeto NSFileManager:
NSFileManager *fileManager = [NSFileManager defaultManager];

Para comprobar si existe un fichero o directorio utilizamos el mensaje fileExistsAtPath que requiere un path:
if([[NSFileManager defaultManager] fileExistsAtPath:[cache path]]) {
// cdigo si existe el directorio o fichero
}

Para crear un directorio y todos sus directorios superiores si no existen:


97

Captulo 15 Paths y URLs

Curso iOS 8

if(![[NSFileManager defaultManager] fileExistsAtPath:[cache path]]) {


NSError *error;
[fileManager createDirectoryAtURL:cache
withIntermediateDirectories:YES attributes:nil error:&error];
if(error) NSLog(@"%@", error);
}

Para crear un directorio dentro del directorio de aplicacin Caches:


-(void)crearDirectorioCache:(NSString *)dir
{
NSString *cachePath =
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES) lastObject];
NSURL *cache = [NSURL fileURLWithPath:cachePath];
NSURL *cacheDir = [cache URLByAppendingPathComponent:dir
isDirectory:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:[cacheDir path]]) {
NSError *error;
[fileManager createDirectoryAtURL:cacheDir
withIntermediateDirectories:YES attributes:nil error:&error];
if(error) NSLog(@"%@", error);
}
}

Para guardar los datos de un objeto NSData en un FileURL:


-(void)guardarDatos:(NSData *)datos enFileURL:(NSURL *)fileUrl
{
[datos writeToURL:fileUrl atomically:YES];
}

98

Captulo 16

Protocolos
16.1 Ayuda

Para crear un protocolo seguiremos estos pasos:

16.1.1 En la clase que enviar el mensaje


1 Definir un protocolo en nuestro archivo de cabecera .h
Pero fuera de las directivas @interface ... @end
@protocol EditarViewControllerDelegate <NSObject>
-(void)guardarCerveza:(Cerveza *)cerveza;
@end

2 Crear una propiedad para recibir un delegate que cumpla nuestro protocolo
@property (weak, nonatomic) id <EditarViewControllerDelegate> delegate;

3 Usar el delegate para enviar el mensaje acordado en el protocolo


- (IBAction)pulsarGuardar:(UIBarButtonItem *)sender {
// ...
[self.delegate guardarCerveza:self.cerveza];
}

16.1.2 En la clase que recibir el mensaje


1 Importar la cabecera .h con el protocolo e indicar que lo implemento

99

Captulo 16 Protocolos

Curso iOS 8

#import "EditarViewController.h"
@interface ListadoViewController : UITableViewController
<EditarViewControllerDelegate>
@end

2 Implementar el protocolo
-(void)guardarCerveza:(Cerveza *)cerveza
{
[self.cervezas guardarCerveza:cerveza];
[self.navigationController popToRootViewControllerAnimated:YES];
[self.tableView reloadData];
}

3 Establecerse como delegate de la otra clase


-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:@"TransicionEditar"]) {
UITableViewCell *celda = sender;
Cerveza *cerveza = [self.cervezas
cervezaConIdentificador:celda.tag];
EditarViewController *editar = segue.destinationViewController;
editar.cerveza = cerveza;
editar.delegate = self;
}
}

100

Captulo 17

App: Cervezas
17.1 Objetivo

Desarrollaremos una app para iPhone para comprobar nuestros conocimientos actuales
sobre desarrollo para iOS.
Los recursos necesarios estn en Cervezas.zip (/descargas/Cervezas.zip)
Versiones del profesor:
Cervezas1.zip (/descargas/Cervezas/Cervezas1.zip)
Cervezas2.zip (/descargas/Cervezas/Cervezas2.zip)

101

Captulo 17 App: Cervezas

Curso iOS 8

17.2 Storyboard

17.3 Modelo

Crearemos una clase Cervezas encargada de leer los datos de la property list
beers.plist y aadirlos a un array.
Crearemos otra clase Cerveza para encapsular los datos de una cerveza adems de un
identificador que ser la posicin en el array.
Esta clase deber tener un inicializador que reciba: id, nombre, tipo y foto.

17.4 Listado

Mostraremos un listado de cervezas con nombre, tipo y foto dentro de un TableView.


102

Curso iOS 8

Captulo 17 App: Cervezas

17.5 Detalle

Al tocar en una fila mostraremos una pantalla de detalle, con los mismos datos.
El nico parmetro que pasaremos al detalle ser un objeto de tipo Cerveza.

103

Captulo 17 App: Cervezas

17.6 Edicin

Crearemos otra pantalla para edicin del nombre y tipo.

104

Curso iOS 8

Curso iOS 8

Captulo 17 App: Cervezas

Pondremos dos botones en la pantalla Listado Aadir y Editar que irn a la pantalla de
Edicin mediante dos Segues.
La tabla tendr dos modos: normal y edicin que se cambiar pulsando el botn Edicin.
Pista:
self.navigationItem.leftBarButtonItem = self.editButtonItem;

Y las celdas estarn preconfiguradas para mostrar o no el botn azul de edicin segn el
modo. Pista:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.editingAccessoryType =
UITableViewCellAccessoryDetailDisclosureButton;
105

Captulo 17 App: Cervezas

Curso iOS 8

El nico parmetro que pasaremos al detalle ser un objeto de tipo Cerveza (existente o
bien nuevo pero ya con su futuro id).
Deberemos crear un protocolo en la pantalla de Edicin que ser implementado por la
pantalla Listado para ser avisada de la modificacin de los datos de una Cerveza.

17.7 Protocolos

Para crear un protocolo seguiremos estos pasos:

17.7.1 En la clase que enviar el mensaje


1 Definir un protocolo en nuestro archivo de cabecera .h
Pero fuera de las directivas @interface ... @end
106

Curso iOS 8

Captulo 17 App: Cervezas

@protocol EditarViewControllerDelegate <NSObject>


-(void)guardarCerveza:(Cerveza *)cerveza;
@end

2 Crear una propiedad para recibir un delegate que cumpla nuestro protocolo
@property (weak, nonatomic) id <EditarViewControllerDelegate> delegate;

3 Usar el delegate para enviar el mensaje acordado en el protocolo


- (IBAction)pulsarGuardar:(UIBarButtonItem *)sender {
// ...
[self.delegate guardarCerveza:self.cerveza];
}

17.7.2 En la clase que recibir el mensaje


1 Importar la cabecera .h con el protocolo e indicar que lo implemento
#import "EditarViewController.h"
@interface ListadoViewController : UITableViewController
<EditarViewControllerDelegate>
@end

2 Implementar el protocolo
-(void)guardarCerveza:(Cerveza *)cerveza
{
[self.cervezas guardarCerveza:cerveza];
[self.navigationController popToRootViewControllerAnimated:YES];
[self.tableView reloadData];
}

3 Establecerse como delegate de la otra clase


-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:@"TransicionEditar"]) {
UITableViewCell *celda = sender;
Cerveza *cerveza = [self.cervezas
cervezaConIdentificador:celda.tag];
EditarViewController *editar = segue.destinationViewController;
editar.cerveza = cerveza;
editar.delegate = self;
}
}
107

Captulo 17 App: Cervezas

Curso iOS 8

17.8 Persistencia

Cada vez que se modifique una Cerveza, la clase Cervezas se encargar de guardarla en
el sistema de ficheros.

17.9 Custom Picker (nuevo control)

Aprenderemos a utilizar un Picker para poder seleccionar una foto entre todas las disponibles.

Crearemos una nueva pantalla con un picker con la lista de imgenes diponibles, una imagen para ver la actualmente seleccionada y dos botones Aceptar y Cancelar.
Deberemos crear un protocolo en la pantalla de Seleccin de Foto que ser implementado
por la pantalla Edicin para ser avisada de la seleccin (o no) de una nueva foto.
108

Curso iOS 8

Captulo 17 App: Cervezas

17.10 Ayuda
17.10.1 Cervezas.h
#import <Foundation/Foundation.h>
#import "Cerveza.h"
@interface Cervezas : NSObject
@property (strong, nonatomic) NSString *path;
@property (strong, nonatomic) NSMutableDictionary *cervezas;
@property (strong, nonatomic) NSMutableArray *fotos;
+ (Cervezas *)sharedInstance;
- (Cerveza *)cervezaConIdentificador:(NSInteger)identificador;
- (Cerveza *)cervezaConIndex:(NSInteger)index;
- (void)guardarCerveza:(Cerveza *)cerveza;
- (void)borrarCervezaConIdentificador:(NSInteger)identificador;
@end

17.10.2 Cervezas.m
#import "Cervezas.h"
@implementation Cervezas
+ (Cervezas *)sharedInstance
{
static Cervezas *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[Cervezas alloc] init];
});
return sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
// Obtener la lista de directorios que corresponden a mi bsqueda
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
// El path a Documentos es el primero (solo habr un elemento en
el array)
NSString *docsDir = [paths objectAtIndex:0];
109

Captulo 17 App: Cervezas

Curso iOS 8

// Y ahora aadir mi nombre de archivo al path de Documentos


_path = [docsDir
stringByAppendingPathComponent:@"Cervezas.list"];
// Comprobar si existe un archivo en ese path
if([[NSFileManager defaultManager] fileExistsAtPath:_path]) {
// Si existe, desarchivar
_cervezas = [NSKeyedUnarchiver
unarchiveObjectWithFile:_path];
} else {
// Si no existe, leer del bundle
NSString *bundlePath = [[NSBundle mainBundle]
pathForResource:@"beers"
ofType:@"plist"];
NSArray *cervezas = [NSArray
arrayWithContentsOfFile:bundlePath];
_cervezas = [[NSMutableDictionary alloc] init];
NSUInteger identificador = 0;
for(NSDictionary *datos in cervezas) {
Cerveza *cerveza =
[[Cerveza alloc]
initWithIdentificador:identificador
nombre:[datos valueForKey:@"name"]
tipo:[datos valueForKey:@"type"]
foto:[datos valueForKey:@"image"]];
[_cervezas setObject:cerveza forKey:[NSString
stringWithFormat:@"%i", identificador]];
identificador += 1;
}
// Y archivar los datos para la prxima vez
[self archivarDatos];
}
// Por ltimo, reconstruir el array de fotos a partir de las
cervezas
_fotos = [[NSMutableArray alloc] init];
for(NSString *clave in _cervezas) {
Cerveza *cerveza = [_cervezas valueForKey:clave];
[_fotos addObject:cerveza.foto];
if(![_fotos containsObject:cerveza.foto]) {
[_fotos addObject:cerveza.foto];
}
}
}
return self;
110

Curso iOS 8

Captulo 17 App: Cervezas

}
- (void)archivarDatos
{
//[_cervezas writeToFile:_path atomically:YES];
[NSKeyedArchiver archiveRootObject:_cervezas toFile:_path];
}
-(Cerveza *)cervezaConIdentificador:(NSInteger)identificador
{
return [self.cervezas valueForKey:[NSString stringWithFormat:@"%i",
identificador]];
}
-(Cerveza *)cervezaConIndex:(NSInteger)index
{
NSArray *claves = [self.cervezas allKeys];
/*NSArray *claves = [[self.cervezas allKeys]
sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];*/
/*NSArray *claves = [[self.cervezas allKeys]
sortedArrayUsingComparator:^(NSString *claveA, NSString *claveB) {
Cerveza *cervezaA = [self.cervezas valueForKey:claveA];
Cerveza *cervezaB = [self.cervezas valueForKey:claveB];
return [cervezaA.nombre caseInsensitiveCompare:cervezaB.nombre];
}];*/
NSString *clave = [claves objectAtIndex:index];
return [self.cervezas objectForKey:clave];
}
-(void)guardarCerveza:(Cerveza *)cerveza
{
[self.cervezas setValue:cerveza forKey:[NSString
stringWithFormat:@"%i", cerveza.identificador]];
[self archivarDatos];
}
-(void)borrarCervezaConIdentificador:(NSInteger)identificador
{
[self.cervezas removeObjectForKey:[NSString stringWithFormat:@"%i",
identificador]];
[self archivarDatos];
}
@end

17.10.3 Cerveza.h
#import <Foundation/Foundation.h>
@interface Cerveza : NSObject <NSCoding>
@property (nonatomic) NSUInteger identificador;
@property (strong, nonatomic) NSString *nombre;
111

Captulo 17 App: Cervezas

Curso iOS 8

@property (strong, nonatomic) NSString *tipo;


@property (strong, nonatomic) NSString *foto;
-(Cerveza *)initWithIdentificador:(NSUInteger)identificador
nombre:(NSString *)nombre tipo:(NSString *)tipo foto:(NSString *)foto;
-(NSString *)description;
@end

17.10.3.1 Cerveza.m
#import "Cerveza.h"
@implementation Cerveza
-(Cerveza *)initWithIdentificador:(NSUInteger)identificador
nombre:(NSString *)nombre
tipo:(NSString *)tipo
foto:(NSString *)foto
{
self = [super init];
if (self) {
_identificador = identificador;
_nombre = nombre;
_tipo = tipo;
_foto = foto;
}
return self;
}
-(NSString *)description
{
return [NSString stringWithFormat:@"%i %@", self.identificador,
self.nombre];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
_identificador = [aDecoder decodeIntegerForKey:@"identificador"];
_nombre = [aDecoder decodeObjectForKey:@"nombre"];
_tipo = [aDecoder decodeObjectForKey:@"tipo"];
_foto = [aDecoder decodeObjectForKey:@"foto"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeInteger:self.identificador forKey:@"identificador"];
[aCoder encodeObject:self.nombre forKey:@"nombre"];
[aCoder encodeObject:self.tipo forKey:@"tipo"];
112

Curso iOS 8

Captulo 17 App: Cervezas

[aCoder encodeObject:self.foto forKey:@"foto"];


}
@end

113

Esta pgina se ha dejado vaca a propsito

114

Captulo 18

Persistencia
Cmo guardar informacin entre lanzamientos de la aplicacin?

18.1 NSUserDefaults

El primer mecanismo ya lo conocemos: NSUserDefaults, pero se debe usar solo para pequeas piezas de informacin

18.2 Property Lists

Usar writeToURL:atomically: e initWithContentsOfURL: en un NSArray o NSDictionary. O bien NSUserDefaults si es apropiado.


Tambin NSPropertyListSerialization convierte Property Lists en NSData o viceversa.

18.3 Archivado

Es el mecanismo para hacer cualquier rbol de objetos persistente.


No obligatoriamente NSArray o NSDictionary, etc.
Requiere que todos los objetos del rbol implementen el protocolo NSCoding:
- (void)encodeWithCoder:(NSCoder *)coder;
- initWithCoder:(NSCoder *)coder;

El rbol de objetos se guarda enviando a todos los objetos encodeWithCoder:


- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
115

Captulo 18 Persistencia

Curso iOS 8

[coder encodeFloat:scale forKey:@"scale"];


[coder encodeCGPoint:origin forKey:@"origin"];
[coder encodeObject:expression forKey:@"expression"];
}

Recordar siempre llamar al mtodo super.


El rbol de objetos se lee de nuevo con alloc/initWithCoder:
- initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
scale = [coder decodeFloatForKey:@"scale"];
expression = [coder decodeObjectForKey:@"expression"];
origin = [coder decodeCGPointForKey:@"origin"]; // el orden no
importa
}

18.4 NSKeyed[Un]Archiver

Estas clases se usan para guardar/recuperar el rbol. Se realiza contra objetos NSData.
NSKeyedArchiver guarda el objeto en un NSData:
+ (NSData *)archivedDataWithRootObject:(id <NSCoder>)rootObject;

NSKeyedUnarchiver recupera el objeto de un NSData:


+ (id <NSCoder>)unarchiveObjectWithData:(NSData *)data;

18.4.1 Qu hace este cdigo?


id <NSCoder> object = ...;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object];
id <NSCoder> dup = [NSKeyedArchiver unarchiveObjectWithData:data];

Hacer una copia completa del objeto


Cuidado, porque la jerarqua de objetos puede ser muy complicada.

18.5 File System

Nuestras aplicaciones den el sistema de archivos de iOS como uno de Unix. Empieza en /
(raiz/root)
Hay permisos de archivos, igual que en Unix, as que no es posible ver todo.
Solo podemos escribir dentro del sandbox
116

Curso iOS 8

Captulo 18 Persistencia

18.5.1 Por qu?


Seguridad (para que nadie pueda daar tu aplicacin)
Privacidad (para que otras apps no puedan ver nuestros datos o los del usuario)
Limpieza (cuando borramos una app todo lo que haya escrito desaparece con ella)

18.5.2 Qu hay en el sandbox?


Directorio Bundle: cdigo, .stoyboards, .jpgs, etc. No se puede escribir en l.
Directorio Documents: Donde se guardan el contenido permanente del usuario.
Directorio Caches: Donde se guardan archivos temporales (iTunes no hace backup).
Otros (ver documentacin de NSSearchPathDirectory.

18.5.3 Cmo podemos escribir en un archivo que viene


con nuestra app?
Se copia desde el Bundle a Documents u otro directorio para poder escribir sobre l.
Cmo se obtienen los paths a estos directorios especiales del sandbox?
Mediante el mtodo de NSFileManager:
- (NSArray *)URLsForDirectory:(NSSearchPathDirectory)directory // see
below
inDomains:(NSSearchPathDomainMask)domainMask; //NSUserDomainMask

Devuelve un NSArray de paths. Normalmente solo hay un path en el array en iOS. Porque
no hay directorio home, compartidos del sistema, etc.
Seguramente usaremos lastObject (por simplicidad).
Ejemplos de valores de NSSearchPathDirectory: NSDocumentsDirectory, NSCachesDirectory, NSAutosavedInformationDirectory, etc.

18.6 NSFileManager

Proporciona operaciones auxiliares sobre el sistema de archivos (porque la lectura y escritura se hace con NSData y otros):
Chequear si un archivo existe
Crear y enumerar directorios
Mover, copiar y borrar archivos
117

Captulo 18 Persistencia

Curso iOS 8

Se crea (alloc/init) una instancia y se solicitan operaciones.


Concurrencia segura (thread safe) siempre que una instancia solo se use en un nico hilo
(thread).
NSFileManager *manager = [[NSFileManager alloc] init];
- (BOOL)createDirectoryAtPath:(NSString *)path
withIntermediateDirectories:(BOOL)createIntermediates
attributes:(NSDictionary *)attributes
error:(NSError **)error;
- (BOOL)isReadableFileAtPath:(NSString *)path;
// permissions, etc.
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError
**)error;

Tiene un protocolo para enviar a su delegate mtodos should... para consultas y recuperacin de errores. Ver documentacin.

18.7 NSString

Utilidades para construccin de paths y lectura/escritura a archivos.


Ejemplos:
- (NSString *)stringByAppendingPathComponent:(NSString *)component;
- (NSString *)stringByDeletingLastPathComponent;
- (BOOL)writeToFile:(NSString *)path
atomically:(BOOL)flag
encoding:(NSStringEncoding)encoding // e.g. ASCII, ISOLatin1,
etc.
error:(NSError **)error;
- (NSString *)stringWithContentsOfFile:(NSString *)path
usedEncoding:(NSStringEncoding *)encoding
error:(NSError **)error;

18.8 SQLite

Se trata de una librera Open Source que viene incluida en iOS.


SQL en un archivo. Rpida, poca memoria, muy segura.
Pero no debera usarse para todo (p.ej. no para guardar videos, sonidos o imgenes)
No est basada en arquitectura cliente-servidor, como MySQL u otras.

118

Curso iOS 8

Captulo 18 Persistencia

18.8.1 API
int sqlite3_open(const char *filename, sqlite3 **db); // get a database
into db
int sqlite3_exec(sqlite3 *db, // execute SQL statements
const char *sql,
int (*callback)(void *, int, char **, char **),
void *context,
char **error);
int mycallback(void *context, int count, char **values, char **cols); //
data returned
int sqlite3_close(sqlite3 *db); // close the database

18.9 Core Data

Se trata del mecansmo ms avanzado. Una capa de orientacin a objetos por encima de
SQLite (y otras posibilidades de persistencia).
Nos permite definir las clases y propiedades, gestionar las relaciones y persistir un rbol
de objetos.
Y lo veremos un poco ms adelante.

119

Esta pgina se ha dejado vaca a propsito

120

Captulo 19

App: Libros
En este proyecto deberis crear una aplicacin que permita guardar informacin sobre libros.

19.1 Tarea 1: Proyecto

Crear un nuevo proyecto en Xcode con iOS y Objective C llamado Libros.

19.2 Tarea 2: Importar recursos


Descargar estos recursos y aadirlos al proyecto:

Portadas e ISBNs Libros.zip (/descargas/Libros.zip)


Property list Libros.plist (/descargas/Libros.plist)

19.3 Tarea 3: Modelo Libro

Crear una clase Libro para guardar los datos de cada libro:
Ttulo
Autor
Foto
La clase Libro deber tener un mtodo init (inicializador) que acepte los tres datos como
parmetros:
- initConTitulo:Autor:Foto:

121

Captulo 19 App: Libros

Curso iOS 8

19.4 Tarea 4: Modelo Libros

Crear una clase Libros con una propiedad array o diccionario para almacenar todos los
libros.
La clase Libros deber tener un mtodo init (inicializador) que lea el archivo libros.plist y
aada cada libro como un objeto de clase Libro.

19.5 Tarea 5: Pantalla Listado

Crear una pantalla de tipo UITableViewController para mostrar el listado de libros con
los siguientes datos:
Ttulo
Autor
Foto
Implementar los mtodos necesarios del protocolo datasource para visualizar el listado de
libros.

19.6 Tarea 6: Controlador de navegacin

Embeber la pantalla de listado dentro de un controlador de navegacin o UINavigationController.

19.7 Tarea 7: Botones Nuevo y Editar


Aadir los botones Nuevo y Editar en la pantalla del listado.

19.8 Tarea 8: Pantalla Detalle

Crear una pantalla para mostrar el detalle de un libro con:


label ttulo
label autor
imageView foto

19.9 Tarea 9: Transicin Detalle

Crear una transicin show desde la pantalla del listado hasta la pantalla de detalle.
Implementar el mtodo prepareForSegue y enviar desde la pantalla del listado a la pantalla de detalle el objeto libro seleccionado.

122

Curso iOS 8

Captulo 19 App: Libros

Deber ser posible regresar a la pantalla del listado utilizando el botn back del controlador de navegacin.

19.10 Tarea 10: Pantalla Editar/Nuevo

Crear una pantalla para editar o aadir los datos de un libro con campos de texto para:
Ttulo
Autor
Foto
Adems de un botn guardar.

19.11 Tarea 11: Transiciones Editar y Nuevo

Crear dos transiciones show desde la pantalla del listado hasta la pantalla de detalle:
Transicin Editar desde la celda de la tabla
Transicin Nuevo desde el botn Nuevo
Implementar el mtodo prepareForSegue y enviar desde la pantalla del listado a la pantalla de detalle el objeto libro seleccionado o uno vaco en caso del botn Nuevo.

19.12 Tarea 12: Protocolo y delegate en Editar/Nuevo


En la pantalla de edicin:

Definir un protocolo que requiera el mtodo guardarLibro:


Definir una propiedad delegate que requiera un objeto que implemente dicho
protocolo
Utilizar el mensaje [self.delegate guardarLibro:...] en el mtodo guardar
de sta pantalla

19.13 Tarea 13: Protocolo y delegate en Listado


En la pantalla del listado:

Importar el protocolo e indicar que el controlador de la pantalla listado


implementa dicho protocolo
Implementar los mtodos requeridos por el protocolo
Asegurarse que en el mtodo prepareForSegue y en las transiciones Editar y
Nuevo establecemos al controlador de la pantalla del listado como delegate de la
pantalla de edicin.
123

Captulo 19 App: Libros

Curso iOS 8

19.14 Tarea 14: Guardar cambios de edicin, nuevo y


borrar

Implementar en la clase libro los mtodos guardarLibro: y borrarLibro: y asegurarse


que:
Una vez modificado un libro en la pantalla de edicin los cambios aparecen en el
listado.
Cuando se aade un libro nuevo ste tambin aparece en el listado.
Cuando se elimina un libro ste desaparece realmente del listado.

19.15 Tarea 15: Clase Libro archivable

Hacer que la clase libro sea archivable implementando el protocolo NSCoding y los mtodos:
initWithCoder
encodeWithCoder

19.16 Tarea 16: Ruta al Sandbox

Obtener una ruta al sandbox para poder archivar los datos de los libros.

19.17 Tarea 17: Persistencia mediante archivado

Archivar lista de libros de la clase Libros utilizando NSKeyedArchiver en un fichero


dentro del sandbox

19.18 Tarea 18: Archivado y desarchivado en clase


Libros
Modificar el mtodo init de la clase Libros para que:

Si existe el fichero con los datos archivados leer de ah los datos de los libros
Si no existe el fichero con los datos archivados leer los datos del property list y
despus archivarlos ah

124

Captulo 20

Blocks
20.1 Referencias

Gua de Apple Blocks (http://developer.apple.com/library/ios/documentation/cocoa/


Conceptual/Blocks/Blocks.pdf)

20.2 Qu es un block?

Un bloque de cdigo, una secuencia de sentencias dentro de ^{}.


Normalmente se incluye dentro de un mtodo y puede acceder a las variables de este, pero
inicialmente solo lectura.
Para poder cambiar una variable dentro de un bloque hay que marcarla como __block
as:
__block BOOL existe = NO;

20.3 Guardar un bloque en una variable


double (^function_cuadrado)(double x) = ^(double x) { return x * x; };
double function_cuadrado(double x) { return x * x; }
NSLog(@"%g", funcion_cuadrado(2.0));

20.4 Definir un tipo para varios bloques


typedef double (^funcion_unaria)(double x);
funcion_unaria funcion_cuadrado;
function_cuadrado = ^(double x){
return x * x;
};
125

Captulo 20 Blocks

Curso iOS 8

20.5 Enumerar
-(void)buscarCervezaPorNombre:(NSString *)nombre
{
__block BOOL existe = NO;
[self.cervezas enumerateObjectsUsingBlock:
^(NSDictionary *cerveza, NSUInteger idx, BOOL *stop) {
NSString *nombreCerveza =
[cerveza valueForKey:@"name"];
NSLog(@"Cerveza %i: %@", idx, nombreCerveza);
if ([nombreCerveza isEqualToString:nombre]) {
existe = YES;
*stop = YES;
}
}
];
if(existe) NSLog(@"Existe %@", nombre);
else NSLog(@"No existe %@", nombre);
}

20.6 Ordenar
[self.cervezas sortUsingComparator:
^(NSDictionary *cerveza1, NSDictionary *cerveza2) {
NSString *nombreCerveza1 = [cerveza1 valueForKey:@"name"];
NSString *nombreCerveza2 = [cerveza2 valueForKey:@"name"];
return [nombreCerveza1 compare:nombreCerveza2
options:NSCaseInsensitiveSearch];
}
];

20.7 Animar
-(void)animacion
{
self.tableView.alpha = 0.0;
[UIView animateWithDuration:2.0 animations:^{
self.tableView.alpha = 1.0;
}];
}

20.8 Accin al completar


-(void)animacionConCompletion
{
self.tableView.alpha = 0.0;
[UIView animateWithDuration:2.0 animations:^{
self.tableView.alpha = 1.0;
126

Curso iOS 8

Captulo 20 Blocks

} completion:^(BOOL finished) {
if(finished) {
UIAlertView *alerta =
[[UIAlertView alloc]
initWithTitle:@"Animacin"
message:@"Completada"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alerta show];
}
}];
}

127

Esta pgina se ha dejado vaca a propsito

128

Captulo 21

Grand Central Dispatch


21.1 Referencias

Gua de Apple Concurrency Programming Guide (https://developer.apple.com/library/


ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ConcurrencyProgrammingGuide.pdf)

21.2 Ejecutar un bloque en una de las colas globales

Todas las tareas que consuman demasiado tiempo (descargar datos de Internet) deberamos pasarlos segn su prioridad a una de las colas globales para liberar la cola principal
(main_queue), responsable de todas las tareas del UI (Interfaz de Usuario).
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^{
// cdigo...
}
);

Las posibles prioridades por orden son:


DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND

129

Captulo 21 Grand Central Dispatch

Curso iOS 8

21.3 Ejecutar un bloque en la cola principal (main


queue)
Todo cdigo nuestro que toque el inferfaz de usuario deber ir en esta cola
dispatch_async(
dispatch_get_main_queue(),
^{
// cdigo...
}
);

21.4 Anidar dos dispatch_async para prevenir problemas


dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^{
// cdigo...
// Revertir a la cola principal todo el cdigo que toca UI
dispatch_async(
dispatch_get_main_queue(),
^{
// cdigo...
}
);
}
);

21.5 Cmo declarar nuestros propios tipos completion


// Declarar un tipo de bloque especfico para ejecutar al terminar la
descarga
typedef void(^descargarFotoCompletion)(NSData *);
- (void)descargarFoto:(NSString *)url
completion:(descargarFotoCompletion)completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,
0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL
URLWithString:url]];
dispatch_async(dispatch_get_main_queue(), ^{
// Llamar al bloque completion con su parmetro necesario
130

Curso iOS 8

Captulo 21 Grand Central Dispatch

data
completion(data);
});
});
}

131

Esta pgina se ha dejado vaca a propsito

132

Captulo 22

Core Data: Introduccin


Core Data es un framework de iOS y OS X que simplifica la gestin de modelo de datos de
nuestras aplicaciones. Podramos denominarlo como el Storyboard del modelo.
Tambin suele decirse que Core Data es un rbol de objetos que puede guardarse en una base de datos.
Core Data suele persistirse en una base de datos sqlite de manera transparente para nosotros los desarrolladores, es decir, no tendremos que escribir sentencias SQL.

22.1 Creacin del esquema

La primera tarea sera definir qu Entidades, Atributos y Relaciones tenemos entre las
Clases que formarn nuestro rbol de objetos.
Para ello crearemos una carpeta Modelo en la que guardaremos todos los archivos que lo
componen.

Figura 22.1 Creacin del esquema o Data Model

133

Captulo 22 Core Data: Introduccin

Curso iOS 8

Figura 22.2 Nuestro primier xcdatamodeld


Para crear el esquema disponemos de dos vistas: en forma de tabla o en forma de rbol grfico.

134

Curso iOS 8

Captulo 22 Core Data: Introduccin

Figura 22.3 Representacin en forma de rbol

Figura 22.4 Entidad Foto y sus Atributos

135

Captulo 22 Core Data: Introduccin

Curso iOS 8

Figura 22.5 Entidad Fotgrafo

Figura 22.6 Relaciones

22.2 La pila de Core Data

Se denomina pila o stack de Core Data a los todos objetos que tenemos que crear y configurar para que Core Data pueda funcionar normalmente.

136

Curso iOS 8

Captulo 22 Core Data: Introduccin

Esta es la parte complicada de aprender Core Data ya que son necesarios varios objetos
nuevos que tenemos que ir desgranando y cada uno tiene sus propias responsabilidades
que tenemos que aprender.

Figura 22.7 Core Data Stack

22.3 Incluir Framework Core Data

Una vez hemos decidido utilizar Core Data para gestionar nuestro modelo debemos incluir su Framework en nuestro proyecto de Xcode.

Figura 22.8 Incluir Framework Core Data

137

Captulo 22 Core Data: Introduccin

Curso iOS 8

22.4 La clase que representa al esquema: NSManagedObjectModel

Al compilar nuestro proyecto, el esquema grfico ser compilado en un objeto de tipo NSManagedObjectModel que lo soportar mediante un cdigo del que no nos tendremos que
preocupar.

22.5 Generacin de las Clases del modelo: NSManagedObject

Las clases de nuestro modelo siempre heredan de NSManagedObject, que es equivalente a


un NSObject pero cuya persistencia estar gestionada por Core Data.
Estas clases las genera Xcode por nosotros y sern sobreescritas por Xcode cada vez que
cambiemos y regeneremos el modelo de Core Data.
Por ello hay que utilizar algn sistema para permitir la separacin entre el cdigo generado automticamente y nuestro propio cdigo.

22.6 Categoras de Objective C

Figura 22.9 Crear una Categora

138

Curso iOS 8

Captulo 22 Core Data: Introduccin

Figura 22.10 Nombrar una Categora

Figura 22.11 Foto+Metodos

Figura 22.12 Fotografo+Metodos

139

Captulo 22 Core Data: Introduccin

Curso iOS 8

22.7 Contexto de Core Data: NSManagedObjectContext

Para realizar operaciones de lectura o escritura debemos utilizar un objeto NSManagedObjectContext.


Este objeto no es seguro para multitarea (o thread-safe), esto nos obliga a utilizarlo nica y
exclusivamente en el hilo en el que lo creemos, generalmente el hilo main. As que funcionaremos exactamente igual que con todo el cdigo que toca el interfaz de usuario.
Una forma sencilla de obtener este contexto es utilizar otro objeto que representa los documentos de nuestra aplicacin.
Otra forma sencilla es utilizar una plantilla de proyecto Xcode que soporte Core Data y seleccionar esta opcin durante la creacin del nuevo proyecto. El cdigo para crear la pila o
stack de Core Data estar en el AppDelegate. An as esta forma es ms complicada.

22.8 Documentos de nuestra aplicacin: UIManagedDocument

Tanto si nuestra aplicacin soporta documentos de usuario como si no, podemos crear un
UIManagedDocument para facilitarnos la vida y trabajar con Core Data.
Crear un UIManagedDocument:
UIManagedDocument *document = [[UIManagedDocument alloc]
initWithFileURL:(URL *)url];

Para usar un UIManagedDocument antes debemos abrirlo


Comprobar si existe:
[[NSFileManager defaultManager] fileExistsAtPath:[url path]]

Si existe abrirlo:
- (void)openWithCompletionHandler:(void (^)(BOOL
success))completionHandler;

Si no existe crearlo:
- (void)saveToURL:(NSURL *)url
forSaveOperation:(UIDocumentSaveOperation)operation
competionHandler:(void (^)(BOOL success))completionHandler;

140

Curso iOS 8

Captulo 22 Core Data: Introduccin

Superimportante! Se trata de una operacin asncrona que requiere un completion.


Ejemplo:
self.document = [[UIManagedDocument alloc] initWithFileURL:(URL *)url];
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
[document openWithCompletionHandler:^(BOOL success) {
if (success) [self documentIsReady];
if (!success) NSLog(@"couldnt open document at %@", url);
}]; } else {
[document saveToURL:url forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) {
if (success) [self documentIsReady];
if (!success) NSLog(@"couldnt create document at %@", url);
}];
}
// Aqu an no est abierto

Una vez abierto podemos usarlo, pero est bien comprobar su documentState:
- (void)documentIsReady
{
if (self.document.documentState == UIDocumentStateNormal) {
NSManagedObjectContext *context =
self.document.managedObjectContext;
// Seguir operando con el contexto de Core Data
}
}

Otros documentStates:
UIDocumentStateClosed: cerrado o no existe
UIDocumentStateSavingError: xito == NO
UIDocumentStateEditingDisabled: temporalmente deshabilitado
UIDocumentStateInConflict: con conflicto, p.ej. modificado desde iCloud
Guardar un documento, como abrirlo o crearlo, tambin se hace asncronamente.
Los documentos se guardan automticamente pero est bien guardarlos manualmente.
Para hacerlo se usa el msmo mtodo que en la creacin pero con diferente forSaveOperation:
141

Captulo 22 Core Data: Introduccin

Curso iOS 8

[self.document saveToURL:self.document.fileURL
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success) {
if (!success) {
NSLog(@"failed to save document %@",
self.document.localizedName);
}
}
}];
// Aqu todava no se ha guardado, usar completion

Propiedades de UIManagedDocument:
@property (nonatomic, strong) NSURL *fileURL; // usada en initWithFileURL
@property (readonly) NSString *localizedName; // solo vlido si est
asociado a un fichero

Cerrar un documento tambin es una operacin asncrona. Aunque el documento tambin se cerrar si no hay punteros strong hacia ste.
Para cerrarlo manualmente:
[self.document closeWithCompletionHandler:^(BOOL success) {
if (!success) NSLog(@"failed to close document %@",
self.document.localizedName);
}];
// the document is not closed at this point in the code (only once the
block above executes)

Crear objetos nuevos en la DB:


[insertNewObjectForEntityForName: inManagedObjectContext: ]

Establecer propiedades con valueForKey y setValueForKey o @property en nuestra


subclase.
Borrar objectos:
[NSManagedObjectContext deleteObject:]

22.9 Consultas

Ejecutar una NSFetchRequest en nuestro NSManagedObjectContext


Crear un NSFetchRequest:
142

Curso iOS 8

Captulo 22 Core Data: Introduccin

Qu Entidad/clase? Obligatorio
Qu Entidades/objetos? NSPredicate predicado que indica qu entidades obtener
y cules no. Opcional, por defecto todas.
En qu orden? NSSortDescriptors: objeto que indica el orden
Cuntos objetos cada vez y/o mximo nmero? Opcional
Ejemplo:
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Foto"];
request.fetchBatchSize = 20;
request.fetchLimit = 100;
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
request.predicate = ...;

22.9.1 NSPredicate
Formatos:
NSString *serverName = @"flickr-5";
NSPredicate *predicate =
[NSPredicate predicateWithFormat:@"thumbnailURL contains %@",
serverName];

Ejemplos:
@"id = %@", [flickrInfo objectForKey:@"id"] // identificador = algo que
le pasemos
@"visto > %@", (NSDate *) // visto es una fecha
@"autor.nombre = %@", (NSString *) // Bsca fotos por nombre de autor
(devuelve fotos)
@"any fotos.descripcion contains %@", (NSString *) // Busca fotgrafo
cuyas fotos contienen texto (LIKE)

22.9.2 NSSortDescriptor
Al hacer una consulta retornar un NSArray de NSManagedObjects. El NSArray estar
ordenado, lo indicamos nosotros
NSSortDescriptor *sortDescriptor =
[NSSortDescriptor sortDescriptorWithKey:@"url_grande"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)];

143

Captulo 22 Core Data: Introduccin

Curso iOS 8

22.9.3 Ejecutar una consulta


NSManagedObjectContext *moc = self.document.managedObjectContext;
NSError *error;
NSArray *fotografos = [moc executeFetchRequest:request error:&error];

22.9.4 Faulting
Los objetos managed se van a buscar a la base de datos cuando se solicitan:
for (Fotografo *fotografo in fotografos) {
NSLog(@fetched fotografo %@, fotografo);
}
for (Fotografo *fotografo in fotografos) {
NSLog(@fetched fotografo nombre %@, fotografo.name);
}

22.9.5 Ejemplo de creacin de UIManagedDocument


@property (nonatomic, strong) UIManagedDocument *FotoDB;
- (void)setup
{
if (!self.FotoDB) {
NSURL *url = [[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]
lastObject];
url = [url URLByAppendingPathComponent:@"FotoDB"];
self.FotoDB = [[UIManagedDocument alloc] initWithFileURL:url];
}
}
- (void)setFotoDB:(UIManagedDocument *)FotoDB
{
if (_FotoDB != FotoDB) {
_FotoDB = FotoDB;
[self usarDocumento];
}
}
- (void)usarDocumento
{
if (![[NSFileManager defaultManager]
fileExistsAtPath:[self.FotoDB.fileURL path]]) {
[self.FotoDB saveToURL:self.FotoDB.fileURL
forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL
success) {
144

Curso iOS 8

Captulo 22 Core Data: Introduccin

// Cargar datos en FotoDB...


}];
} else if (self.FotoDB.documentState == UIDocumentStateClosed) {
// Existe y hay que abrirlo
[self.FotoDB openWithCompletionHandler:^(BOOL success) {
// El documento est abierto, hacer consultas...
}];
} else if (self.FotoDB.documentState == UIDocumentStateNormal) {
// El documento ya est abierto, hacer consultas...
}
}

22.9.6 Ejemplo de mtodos para aadir a nuestras clases


+ (Fotografo *)fotografoConDatos:(NSDictionary *)datos
contexto:(NSManagedObjectContext *)contexto
{
Fotografo *fotografo = nil;
NSString *nombre = [datos valueForKey:@"name"];
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Fotografo"];
request.predicate = [NSPredicate predicateWithFormat:@"nombre = %@",
nombre];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor
sortDescriptorWithKey:@"nombre" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *fotografos = [contexto executeFetchRequest:request
error:&error];
if (fotografos == nil) {
// error, el array fotografos es nil
} else if ([fotografos count] > 1) {
// error, solo debera haber un resultado
// y nombre no es un identificador nico
} else if([fotografos count] == 0) {
// si el array est vaco, el fotografo no est en la BD y hay
que meterlo
fotografo = [NSEntityDescription
insertNewObjectForEntityForName:@"Fotografo"
inManagedObjectContext:contexto];
fotografo.nombre = nombre;
145

Captulo 22 Core Data: Introduccin

Curso iOS 8

} else if([fotografos count] == 1) {


// si el array tiene un elemento, devolvemos ese fotgrafo
// aqu podramos decidir cambiar algn dato
fotografo = [fotografos lastObject];
}
return fotografo;
}

22.9.7 Ejemplo de consulta sencilla


Obtener todos los fotgrafos de nuestra DB:
NSFetchRequest *request =
[NSFetchRequest fetchRequestWithEntityName:@"Fotografo"];
request.sortDescriptors =
[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:@"nombre"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]];
// No hay predicado, queremos todos los fotgrafos

22.9.8 Tareas App de ejemplo


Guardar y abrir FotoDB y comprobar con Terminal que guarda un fichero
Crear Fotos y Fotografos y relacionarlos
Hacer consultas e imprimirlas con NSLog

146

Captulo 23

App: Ejemplo Core Data


23.1 Activar CoreData SQLDebug

Para comprobar las consultas SQL que se estn ejecutando es interesante activar la depuracin CoreData SQLDebug
Ir al la barra de Xcode y a la derecha del Stop, pinchar en nombre app (en este caso Core
Data) para editar el esquema: Product > Edit Scheme

Figura 23.1 Editar esquema

147

Captulo 23 App: Ejemplo Core Data

Curso iOS 8

Figura 23.2 Activar CoreData SQLDebug


Y aadir este flag en el equema: Run CoreData.app (debug)
-com.apple.CoreData.SQLDebug 1

23.2 ViewController.h
#import <UIKit/UIKit.h>
#import "Foto+Metodos.h"
#import "Fotografo+Metodos.h"
@interface ViewController : UIViewController <UITableViewDataSource,
UITableViewDelegate, NSFetchedResultsControllerDelegate>
@property (strong, nonatomic) UIManagedDocument *FotoDB;
@property (strong, nonatomic) NSFetchedResultsController
*fetchedResultsController;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end

23.3 ViewController.m
#import "ViewController.h"
@implementation ViewController
148

Curso iOS 8

Captulo 23 App: Ejemplo Core Data

- (void)setup
{
if (!self.FotoDB) {
NSURL *url = [[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]
lastObject];
url = [url URLByAppendingPathComponent:@"FotoDB"];
self.FotoDB = [[UIManagedDocument alloc] initWithFileURL:url];
}
}
- (void)setFotoDB:(UIManagedDocument *)FotoDB
{
if (_FotoDB != FotoDB) {
_FotoDB = FotoDB;
[self usarDocumento];
}
}
- (void)usarDocumento
{
if (![[NSFileManager defaultManager]
fileExistsAtPath:[self.FotoDB.fileURL path]]) {
[self.FotoDB saveToURL:self.FotoDB.fileURL
forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL
success) {
// Cargar datos en FotoDB...
NSLog(@"Cargar datos en FotoDB...");
[self cargarDatosEnFotoDB];
[self consultarDatosEnFotoDB];
}];
} else if (self.FotoDB.documentState == UIDocumentStateClosed) {
// Existe y hay que abrirlo
[self.FotoDB openWithCompletionHandler:^(BOOL success) {
// El documento est abierto, hacer consultas...
NSLog(@"El documento est abierto, hacer consultas...");
[self cargarDatosEnFotoDB];
[self consultarDatosEnFotoDB];
}];
} else if (self.FotoDB.documentState == UIDocumentStateNormal) {
// El documento ya est abierto, hacer consultas...
NSLog(@"El documento ya est abierto, hacer consultas...");
}
}

149

Captulo 23 App: Ejemplo Core Data

Curso iOS 8

- (void)cargarDatosEnFotoDB
{
NSManagedObjectContext *contexto = self.FotoDB.managedObjectContext;
Fotografo *fotografo1 = [Fotografo crearFotografoConDatos:@{
@"nombre" : @"Fotografo1" } contexto:contexto];
Foto *foto1 = [Foto crearFotoConDatos:@{ @"descripcion" : @"Foto1" }
contexto:contexto];
Foto *foto2 = [Foto crearFotoConDatos:@{ @"descripcion" : @"Foto2" }
contexto:contexto];
Foto *foto3 = [Foto crearFotoConDatos:@{ @"descripcion" : @"Foto3" }
contexto:contexto];
NSSet *fotos = [NSSet setWithArray:@[foto1, foto2, foto3]];
[fotografo1 addFotos:fotos];
Fotografo *fotografo2 = [Fotografo crearFotografoConDatos:@{
@"nombre" : @"Fotografo2" } contexto:contexto];
Foto *foto21 = [Foto crearFotoConDatos:@{ @"descripcion" : @"Foto21"
} contexto:contexto];
foto21.autor = fotografo2;
}
- (void)consultarDatosEnFotoDB
{
[self consultarTodasLasFotos];
[self consultarTodosLosFotografos];
}
- (void)consultarTodasLasFotos
{
NSManagedObjectContext *contexto = self.FotoDB.managedObjectContext;
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Foto"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor
sortDescriptorWithKey:@"descripcion" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *fotos = [contexto executeFetchRequest:request error:&error];
NSLog(@"Todas las fotos: %@", fotos);
}

150

Curso iOS 8

Captulo 23 App: Ejemplo Core Data

- (void)consultarTodosLosFotografos
{
NSManagedObjectContext *contexto = self.FotoDB.managedObjectContext;
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Fotografo"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor
sortDescriptorWithKey:@"nombre" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *fotografos = [contexto executeFetchRequest:request
error:&error];
NSLog(@"Todos los fotografos: %@", fotografos);
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setup];
}
@end

23.4 Foto+Metodos.h
#import "Foto.h"
@interface Foto (Metodos)
+ (Foto *)crearFotoConDatos:(NSDictionary *)datos
contexto:(NSManagedObjectContext *)contexto;
@end

23.5 Foto+Metodos.m
#import "Foto+Metodos.h"
@implementation Foto (Metodos)
+ (Foto *)crearFotoConDatos:(NSDictionary *)datos
contexto:(NSManagedObjectContext *)contexto
{
Foto *foto = nil;
NSString *descripcion = [datos valueForKey:@"descripcion"];
151

Captulo 23 App: Ejemplo Core Data

Curso iOS 8

NSFetchRequest *request = [NSFetchRequest


fetchRequestWithEntityName:@"Foto"];
request.predicate = [NSPredicate predicateWithFormat:@"descripcion =
%@", descripcion];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor
sortDescriptorWithKey:@"descripcion" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *fotos = [contexto executeFetchRequest:request error:&error];
if (fotos == nil) {
// error, el array fotos es nil
} else if ([fotos count] > 1) {
// error, solo debera haber un resultado
// y descripcion no es un identificador nico
} else if([fotos count] == 0) {
// si el array est vaco, la foto no est en la BD y hay que
meterlo
foto = [NSEntityDescription
insertNewObjectForEntityForName:@"Foto" inManagedObjectContext:contexto];
foto.descripcion = [datos valueForKey:@"descripcion"];
foto.url_grande = [datos valueForKey:@"url_grande"];
foto.url_mini = [datos valueForKey:@"url_mini"];
} else if([fotos count] == 1) {
// si el array tiene un elemento, devolvemos esa foto
// aqu podramos decidir cambiar algn dato
foto = [fotos lastObject];
}
return foto;
}
@end

23.6 Fotografo+Metodos.h
#import "Fotografo.h"
@interface Fotografo (Metodos)
+ (Fotografo *)crearFotografoConDatos:(NSDictionary *)datos
contexto:(NSManagedObjectContext *)contexto;
@end

152

Curso iOS 8

Captulo 23 App: Ejemplo Core Data

23.7 Fotografo+Metodos.m
#import "Fotografo+Metodos.h"
@implementation Fotografo (Metodos)
+ (Fotografo *)crearFotografoConDatos:(NSDictionary *)datos
contexto:(NSManagedObjectContext *)contexto
{
Fotografo *fotografo = nil;
NSString *nombre = [datos valueForKey:@"nombre"];
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Fotografo"];
request.predicate = [NSPredicate predicateWithFormat:@"nombre = %@",
nombre];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor
sortDescriptorWithKey:@"nombre" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *fotografos = [contexto executeFetchRequest:request
error:&error];
if (fotografos == nil) {
// error, el array fotografos es nil
} else if ([fotografos count] > 1) {
// error, solo debera haber un resultado
// y nombre no es un identificador nico
} else if([fotografos count] == 0) {
// si el array est vaco, el fotografo no est en la BD y hay
que meterlo
fotografo = [NSEntityDescription
insertNewObjectForEntityForName:@"Fotografo"
inManagedObjectContext:contexto];
fotografo.nombre = nombre;
} else if([fotografos count] == 1) {
// si el array tiene un elemento, devolvemos ese fotgrafo
// aqu podramos decidir cambiar algn dato
fotografo = [fotografos lastObject];
}
return fotografo;
}
153

Captulo 23 App: Ejemplo Core Data

@end

154

Curso iOS 8

Captulo 24

NSFetchedResultsController
Se trata de un controlador especialmente pensado para trabajar con Core Data y un TableView.
Bsicamente encapsula una consulta NSFetchRequest y reduce el cdigo necesario para
visualizar el TableView.
Pero adems est atento a todos los cambios en el contexto managedObjectContext y los
enva como eventos a su delegado para actuar sobre la tabla y crear, modificar y eliminar
celdas.

24.1 Creacin del controlador

Lo primero que tenemos que hacer es crear el controlador y lo asociamos a la consulta que
deseemos mostrar.

24.1.1 Ejemplo consulta: Todos los fotografos


- (void)setupFetchedResultsController
{
NSLog(@"setupFetchedResultsController");
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Fotografo"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor
sortDescriptorWithKey:@"nombre" ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:self.FotoDB.managedObjectContext
sectionNameKeyPath:nil cacheName:nil];
155

Captulo 24 NSFetchedResultsController

Curso iOS 8

NSError *error = nil;


[self.fetchedResultsController performFetch:&error];
if(error) NSLog(@"%@", error);
[self.tableView reloadData];
}

24.1.2 Ejemplo consulta: Todas las fotos separadas por fotgrafo


- (void)setupFetchedResultsController
{
NSLog(@"setupFetchedResultsController");
NSFetchRequest *request = [NSFetchRequest
fetchRequestWithEntityName:@"Foto"];
request.sortDescriptors = @[[NSSortDescriptor
sortDescriptorWithKey:@"autor.nombre" ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)],[NSSortDescriptor
sortDescriptorWithKey:@"descripcion" ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:self.FotoDB.managedObjectContext
sectionNameKeyPath:@"autor.nombre" cacheName:nil];
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if(error) NSLog(@"%@", error);
[self.tableView reloadData];
}

24.2 Construccin del TableView


#pragma mark UITableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections]
objectAtIndex:section] numberOfObjects];
}
156

Curso iOS 8

Captulo 24 NSFetchedResultsController

24.2.1 Para la consulta fotgrafos


-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *celda = [self.tableView
dequeueReusableCellWithIdentifier:@"Celda"];
Fotografo *fotografo = [self.fetchedResultsController
objectAtIndexPath:indexPath];
celda.textLabel.text = fotografo.nombre;
celda.detailTextLabel.text = [NSString stringWithFormat:@"Fotos:
%i", [fotografo.fotos count]];
return celda;
}

24.2.2 Para la consulta fotos


-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *celda = [self.tableView
dequeueReusableCellWithIdentifier:@"Celda"];
Foto *foto = [self.fetchedResultsController
objectAtIndexPath:indexPath];
celda.textLabel.text = foto.descripcion;
celda.detailTextLabel.text = foto.autor.nombre;
return celda;
}
-(NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections]
objectAtIndex:section] name];
}

24.3 Delegacin y eventos NSFetchedResultsControllerDelegate


Establecer nuestro ViewController como delegado del controlador:
- (void)setupFetchedResultsController
{
// cdigo...
157

Captulo 24 NSFetchedResultsController

Curso iOS 8

self.fetchedResultsController.delegate = self;
}

24.3.1 controllerWillChangeContent:
Este evento nos avisa de que van a comenzar los cambios en la tabla.
-(void)controllerWillChangeContent:(NSFetchedResultsController
*)controller
{
[self.tableView beginUpdates];
}

24.3.2 controllerDidChangeContent:
Este evento nos avisa de que han terminado los cambios en la tabla.
-(void)controllerDidChangeContent:(NSFetchedResultsController
*)controller
{
[self.tableView endUpdates];
}

24.3.3 controller:didChangeSection:
Este evento nos avisa de que
-(void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:sectionIndex];
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:indexSet
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:indexSet
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}

158

Curso iOS 8

Captulo 24 NSFetchedResultsController

24.3.4 controller:didChangeObject:
-(void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath
*)newIndexPath
{
NSArray *objetoNuevo = nil;
if(newIndexPath) objetoNuevo = [NSArray
arrayWithObject:newIndexPath];
NSArray *objetoViejo = nil;
if(indexPath) objetoViejo = [NSArray arrayWithObject:indexPath];
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:objetoNuevo
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:objetoViejo
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
{
UITableViewCell *celda = [self.tableView
cellForRowAtIndexPath:indexPath];
Foto *foto = [self.fetchedResultsController
objectAtIndexPath:indexPath];
celda.textLabel.text = foto.descripcion;
break;
}
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:objetoViejo
withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:objetoNuevo
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}

159

Esta pgina se ha dejado vaca a propsito

160

Captulo 25

iCloud
25.1 Introduccin

Se usa para compartir los documentos de un usuario entre sus dispositivos.


Es una URL en un directorio compartido, en Internet, por lo que puede ser lento y hay que
minimizar los cambios.
Portal de iCloud para developers:
https://developer.apple.com/icloud/

25.1.1 iCloud Entitlements


Para poder usar iCloud en una aplicacin hay que empezar por darle los permisos y claves
necesarios

161

Captulo 25 iCloud

Curso iOS 8

Figura 25.1 Entitlements > iCloud

25.1.2 iCloud URL


Para obtener la URL dentro de iCloud usamos un NSFileManager:
[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

Pondremos los documentos en el directorio Documents dentro de esta URL.


Se puede usar un NSFileManager para navegar por los contenidos, pero sera lento.

25.2 Coordinacin

Los diferentes dispositivos se coordinan mediante varios NSFilePresenters (un protocolo) usando la clase NSFileCoordinator.
Nuestro UIManagedDocument es un NSFilePresenter perfecto para usarlo con iCloud
(implementa ese protocolo).
Es necesario suscribirse a las notificaciones que nos indican los cambios en iCloud.
Para poner un UIManagedDocument primero necesitamos la URL en la que vamos a guardarlo:
iCloudDocumentsURL = [iCloudURL
URLByAppendingPathComponent:@"Documents"];

162

Curso iOS 8

Captulo 25 iCloud

Pero adems, solo deberamos sincronizar los cambios de los UIManagedDocument. Usando Core Data podemos disponer de un log de estos cambios.
Para ello introducimos estas claves en el diccionario de opciones del documento persistentStoreOptions, pero siempre antes de crearlo o abrirlo:
NSPersistentStoreUbiquitousContentNameKey: el nombre del documento
NSPersistentStoreUbiquitousContentURLKey: directorio para guardar todos
los logs de cambios
Este directorio que usaremos para los logs NO debe estar en el directorio Documents de
iCloud, pero s puede ser el mismo para todos los documentos:
iCloudLogsURL = [iCloudURL URLByAppendingPathComponent:@"CoreData"];

Para establecer ContentNameKey debemos primero leerla de DocumentMetadata.plist


NSURL *metadataURL = [docURL
URLByAppendingPathComponent:@"DocumentMetadata.plist"];

25.3 Enumerar el contenido de iCloud

Debemos crear una consulta que se actualizar automticamente y observar los cambios
que nos enviar mediante el sistema de notificaciones.

25.3.1 Crear la consulta


NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
query.searchScopes = [NSArray arrayWithObjects:scope1, scope2, nil];

NSMetadataQueryUbiquitousDocumentsScope son todos los ficheros del


directorio Documents.
NSMetadataQueryUbiquitousDataScope son todos los ficheros fuera del
directorio Documents.
Predicado de una consulta para devolver todos los archivos:
query.predicate = [NSPredicate predicateWithFormat:@"%K like '*'",
NSMetadataItemFSNameKey];

25.3.2 Arrancar y parar la consulta


[query startQuery];
[query stopQuery];

163

Captulo 25 iCloud

Curso iOS 8

25.3.3 Activar y desactivar notificaciones


[query enableUpdates];
[query disableUpdates];

Un buen lugar para hacerlo es viewWillAppear y viewWillDisappear, por dos razones:


Si no estoy visible en pantalla no me interesan las notificaciones
Adems, nunca van a eliminar de la memoria a un ViewController que est en
pantalla
Es importantsimo desuscribirse de cualquier notificacin antes de ser eliminado
de la memoria (o el programa cascar porque los punteros a observers no son
seguros)

25.3.4 Suscribirse a notificaciones


Primeros resultados:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(processQueryResults:)
name:NSMetadataQueryDidFinishGatheringNotification
object:query];

Actualizacin de resultados:
[center addObserver:self
selector:@selector(processQueryResults:)
name:NSMetadataQueryDidUpdateNotification
object:query];

Muy importante otra vez. Antes de ser eliminados de la memoria (dealloc), desuscribirse
como observador de cualquier notificacin.
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

25.4 Procesar notificaciones


Recibiremos objetos NSNotification
Paramos la consulta durante el procesamiento
No usamos for in porque es muy lento para estas consultas que se autoactualizan
164

Curso iOS 8

Captulo 25 iCloud

Cada resultado es un NSMetadataQuery del que obtenemos su URL


Estas URLs son de los archivos cambiados, no del documento (que es un directorio)
Hay que eliminar el nombre del archivo
- (void)processQueryResults:(NSNotification *)notification
{
[query disableUpdates];
int resultCount = [query resultCount];
for (int i = 0; i < resultCount; i++) {
NSMetadataItem *item = [query resultAtIndex:i];
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
// Procesar URLs
// Son URLs a archivos, hay que convertirlas a URLs de documento
(es un directorio)
}
[query enableUpdates];
}

25.4.1 Coordinar los cambios


Debe hacerse cada vez de accedes a una URL iCloud usando NSFileManager
Debe hacerse fuera del hilo main, no porque sea lento...
Si las tareas de UI se bloquean esperando a los cambios y el procesamiento de estos
se bloquea esperando los cambios del usuario nuestra app habr muerto (deadlock)
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc]
initWithFilePresenter:nil];
NSError *coordinationError;
[coordinator coordinateReadingItemAtURL:(NSURL *)url
options:(NSFileCoordinatorReadingOptions)options
error:(NSError **)error
byAccessor:^(NSURL *urlToUse){
// do your NSFileManager stuff here using urlToUse
}];
if (coordinationError) {
// Error
}

Hay otros mtodos para coordinar escrituras, etc.

25.5 Estados del documento

En iCloud es an ms importante que en Core Data comprobar el documentState


165

Captulo 25 iCloud

Curso iOS 8

Los estados importantes son:


InConflict
EditingDisabled
SavingError

25.5.1 InConflict
Si dos dispositivos tienen versiones distintas de un documento en iCloud:
Podremos comparar varias versiones
Aplicar manualmente los cambios de una a otra (quizs preguntando al usuario)
Cambiar de estado a esas versiones (ya no estn en conflicto)
Y finalmente elminar las versiones que ahora estn duplicadas

25.5.2 EditingDisabled
En este estado no podremos aplicar cambios.

25.5.3 SavingError
Avisar al usuario o intentar guardar ms tarde: conflicto? problemas de red?

25.6 Mover un archivo entre dispositivos e iCloud

Podemos cambiar las opciones de un documento de compartido en iCloud a no compartido, pero siempre fuera del hilo main

25.6.1 Ejemplo: Exportar a iCloud:


dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
NSURL *localURL = ...; // document a transferir a iCloud
NSString *name = [localURL lastPathComponent];
NSURL *iCloudURL = [iCloudDocumentsURL
URLByAppendingPathComponent:name];
NSError *error = nil;
[[[NSFileManager alloc] init] setUbiquitous:YES
itemAtURL:localURL
destinationURL:iCloudURL
error:&error];
});

166

Curso iOS 8

Captulo 25 iCloud

25.7 Compartir un fichero usando iCloud

Adems de usar iCloud para compartir los documentos de un usuario entre sus dispositivos. Tambin es posible exportar una URL temporal para compartir un fichero entre
usuarios distintos. Pero solo ficheros no directorios. La URL apunta a la copia de este fichero (que es solo de lectura)
NSURL *urlToShare = @"...";
NSDate *date;
NSError *error;
NSURL *sharedURL =
[[NSFileManager defaultManager]
URLForPublishingUbiquitousItemAtURL:urlToShare
expirationDate:&date
error:&error];

25.8 NSUbiquitousKeyValueStore
Como NSUserDefaults, pero en iCloud

25.8.1 Para obtener la instancia compartida


[NSUbiquitousKeyValueStore defaultStore]

25.8.2 Para leer y escribir valores


Igual que en un diccionario:
NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore
defaultStore];
[store setObject:@"valor" forKey:@"clave"];
[store synchronize];

Synchronize sincroniza en ambos sentidos, as que suele llamarse al iniciar la


aplicacin
o es instantneo ya que se conecta a Internet

25.8.3 Notificaciones
Como los datos pueden cambiar en cualquier momento hay que suscribirse a sus notificaciones:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(ubiquitousKeyValueStoreChanged:)
name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
object:[NSUbiquitousKeyValueStore defaultStore]];
167

Captulo 25 iCloud

Curso iOS 8

Mtodo que recibe las notificaciones:


- (void)ubiquitousKeyValueStoreChanged:(NSNotification *)notification
{
// procesar notification.userInfo
}

NSUbiquitousKeyValueStoreChangeReasonKey: Server, InitialSync,


QuotaViolation
NSUbiquitousKeyValueStoreChangedKeysKey: NSArray de NSStrings de las
claves cambiadas
No se llama si tu aplicacin cambia claves, solo si se cambian en iCloud (desde otro dispositivo)

168

Captulo 26

Servicios Web
Prcticamente cualquier aplicacin que desarrollemos deber conectarse en algn momento con un servicio web.
Para ello deberemos utilizar alguno de los protocolo de comunicaciones que estos servicios web implementen, p.ej:
SOAP/WSDL
REST basado en XML o JSON
SDKs oficiales (o de terceros)

26.1 SOAP/WSDL

Es un protocolo antiguo basado en HTTP para el transporte y XML para los contenidos de
las llamadas. Se ha usado bastante en el mundo de Java y C# .NET.
Wikipedia: SOAP (http://es.wikipedia.org/wiki/SOAP)
Wikipedia: WSDL (http://es.wikipedia.org/wiki/WSDL)
No tenemos soporte directo en el iOS SDK, as que en principio deberamos construir
nuestras consultas manualmente utilizando la infraestructura bsica que proporcionan
NSURLRequest y NSXMLParser.
Aunque nuestra mejor opcin aqu es utilizar una herramienta de generacin de cdigo:
wsdl2objc (http://code.google.com/p/wsdl2objc/)

169

Captulo 26 Servicios Web

Curso iOS 8

Se trata de una aplicacin de Mac que solicita la URL del archivo WSDL y genera unas clases Objective C que podremos incorporar a nuestro proyecto.
Este proyecto es antiguo y no usa ARC as que o bien desactivamos ARC en esos archivos
con el flag del compilador -fno-objc-arc o bien utilizamos la herramienta de migracin automtica:
Gua de Apple: Migracin a ARC (https://developer.apple.com/library/ios/
releasenotes/ObjectiveC/RN-TransitioningToARC/RN-TransitioningToARC.pdf)
Stack Overflow: Desactivar ARC en un archivo (http://stackoverflow.com/
questions/6646052/how-can-i-disable-arc-for-a-single-file-in-a-project)

26.2 REST basado en XML o JSON

Este protocolo es ms moderno y la tendencia actual cuando se desarrolla un sitio web.


Tambin se basa en HTTP para el transporte y XML o JSON como formato de las respuestas:
Wikipedia: REST (http://es.wikipedia.org/wiki/Representational_State_Transfer)
Se tienden a utilizan los mtodos del protocolo HTTP (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) tal y como fueron concebidos para una web de lectura y escritura:
GET: Lectura (parmetros en la URL)
POST: Lectura/escritura (envo de parmetros en la cabecera HEADER)
PUT: Escritura (p.ej. envo de un archivo)
UPDATE: Actualizacin
DELETE: Borrado
En la prctica y por limitaciones de los navegadores, JavaScript, los servidores de aplicacin y los lenguajes de programacin utilizados (PHP, Python, Ruby, Java, C#, etc.) muchas veces solo se utilizan los mtodos GET y POST.
Estos mtodos se mapean con las operaciones que cualquier base de datos (o capa de persistencia) debera implementar.
Estas operaciones se suelen denominar en ingls CRUD (http://es.wikipedia.org/wiki/
CRUD) :
CREATE: Crear
170

Curso iOS 8

Captulo 26 Servicios Web

READ: Leer
UPDATE: Actualizar
DELETE: Borrar
Y en castellano muchas veces ABM: Alta, Baja y Modificacin, obviando la lectura de datos.

171

Esta pgina se ha dejado vaca a propsito

172

Captulo 27

Cmara: Fotos
27.1 Introduccin

Para sacar una foto con la cmara del dispositivo utilizamos el controlador UIImagePickerController.
Antes de poder hacerlo hay que comprobar si el dispositivo realmente tiene una cmara
de fotos (o varias).
Por ejemplo estos dispositivos no tienen cmara:
Simulador de iOS
iPad de primera generacin
iPod touch de la primera a la tercera generacin
Ms informacin:
Wikipedia: Lista de dispositivos iOS (http://en.wikipedia.org/wiki/
List_of_iOS_devices)
En los dispositivos sin cmara deberemos ofrecer la alternativa de obtener una foto del lbum de fotos.

27.2 Ejemplo: UIImagePickerController

Comprobar si el dispositivo tiene cmara y mostrar picker de cmara o lbum de fotos:


- (IBAction)pulsarCamara:(UIBarButtonItem *)sender {
if([UIImagePickerController
173

Captulo 27 Cmara: Fotos

Curso iOS 8

isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[self showImagePicker:UIImagePickerControllerSourceTypeCamera];
} else {
[self
showImagePicker:UIImagePickerControllerSourceTypePhotoLibrary];
}
}

Mostrar picker del tipo seleccionado:


- (void)showImagePicker:(UIImagePickerControllerSourceType)sourceType
{
if([UIImagePickerController isSourceTypeAvailable:sourceType]) {
self.imagePickerController = [[UIImagePickerController alloc]
init];
self.imagePickerController.sourceType = sourceType;
self.imagePickerController.delegate = self;
[self presentViewController:self.imagePickerController
animated:YES completion:^{}];
}
}

27.3 Ejemplo: UIImagePickerControllerDelegate


Recibir la foto seleccionada y mostrarla en un UIImageView:
#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info
valueForKey:UIImagePickerControllerOriginalImage];
self.portadaImageView.image = image;
[self dismissViewControllerAnimated:YES completion:^{}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:^{}];
}

27.4 Ejemplo: AVCaptureDevice

Listar los dispositivos de captura de audio y video (micrfono y cmaras):

174

Curso iOS 8

Captulo 27 Cmara: Fotos

- (void)logCameraDevices
{
NSLog(@"AVCaptureDevice devices: %@", [AVCaptureDevice devices]);
}

27.5 Referencias:
Gua Apple: Camera Programming Topics for iOS (http://developer.apple.com/
library/ios/documentation/AudioVideo/Conceptual/
CameraAndPhotoLib_TopicsForIOS/CameraAndPhotoLib_TopicsForIOS.pdf)
Referencia: UIImagePickerController (http://developer.apple.com/library/ios/
documentation/uikit/reference/UIImagePickerController_Class/
UIImagePickerController_Class.pdf)
Referencia: UIImagePickerControllerDelegate (http://developer.apple.com/
library/ios/documentation/uikit/reference/
UIImagePickerControllerDelegate_Protocol/
UIImagePickerControllerDelegate_Protocol.pdf)
Referencia: AVCaptureDevice (https://developer.apple.com/library/mac/
documentation/AVFoundation/Reference/AVCaptureDevice_Class/
AVCaptureDevice_Class.pdf)

175

Esta pgina se ha dejado vaca a propsito

176

Captulo 28

Cmara en el Simulador
El simulador no permite utilizar directamente la cmara.

28.1 Usar una imgen

Para usar una imagen guardada previamente en la app Fotos del Simulador:
1. Mantener pulsado Alt y el botn del ratn

177

Captulo 28 Cmara en el Simulador

Curso iOS 8

Figura 28.1 Camera Simulation


2. Seleccionar una foto de los lbumes disponibles.

28.2 Guardar una imgen

Para guardar una imagen en los lbumes de Fotos:


1. Arrastrar una imagen con el formato y las proporciones adecuadas (.jpg y 640x960
pxeles) al Simulador y se abrir Safari.
2. Mantener pulsado el botn del ratn y se abrir un dilogo, tocar en Save Image.

178

Curso iOS 8

Captulo 28 Cmara en el Simulador

Figura 28.2 Dilogo Save Image

179

Captulo 28 Cmara en el Simulador

28.3 Imgenes de ejemplo

180

Curso iOS 8

Curso iOS 8

Captulo 28 Cmara en el Simulador

Figura 28.3 Cdigo de barras


181

Captulo 28 Cmara en el Simulador

Curso iOS 8

28.4 Referencias
Stack Overflow (http://stackoverflow.com/questions/1250199/how-do-i-addphotos-to-the-iphone-simulator-for-osx)

182

Captulo 29

App: Libros Avanzado


En este proyecto deberis crear una aplicacin que permita guardar vuestros libros y si estn prestados a algn amigo.
Utilizaremos la cmara del dispositivo (o del simulador) para capturar la portada.
Tambin incluiremos la posibilidad de escanear el ISBN (cdigo de barras) del libro mediante ZBarSDK y realizar una bsqueda en Internet para obtener sus datos, incluyendo
la portada.

29.1 Core Data

Utilizaremos Core Data y un UIManagedDocument para guardar toda nuestra biblioteca


y posteriormente poder compartirla en iCloud entre nuestros dispositivos.
El modelo de Core Data tendr al menos las entidades Libro, Autor y Amigo.

29.1.1 Libro
Ttulo
Autor
ISBN
Portada (foto)
Prestado a (amigo)
Fecha del prstamo

183

Captulo 29 App: Libros Avanzado

Curso iOS 8

29.1.2 Autor
Nombre
Libros

29.1.3 Amigo
Nombre
Libros
Telfono

29.2 Pantallas

Listado de libros, con posibilidad de aadir, editar y borrar.


Por comodidad, si ponemos un nombre de autor que no existe ya, lo crearemos.
Listado de autores, no es necesario crear las pantallas de edicin.
Listado de libros prestados ordenados por fecha.
Podremos indicar que nos han devuelto el libro eliminando el prestado a y la fecha.
Avanzado No es necesario, pero si alguien se quiere liar que guarde en una nueva entidad
todos los prstamos y devoluciones de un libro.

29.3 Google Books API

Documentacin (https://developers.google.com/books/docs/v1/getting_started)
Ejemplo de llamada a Google Books API:
https://www.googleapis.com/books/v1/volumes?q=isbn:0789723107
Ejemplo de thumbnail:
http://bks5.books.google.es/
books?id=_VYvIG5TYXEC&printsec=frontcover&img=1&zoom=1&source=gbs_api

29.4 Cmara de fotos

Utilizaremos la cmara del dispositivo (o del simulador) para capturar la portada...

184

Curso iOS 8

Captulo 29 App: Libros Avanzado

29.5 Escanear ISBN

Incluiremos la posibilidad de escanear el ISBN (cdigo de barras) del libro mediante


ZBarSDK y realizar una bsqueda en Internet para obtener ms datos, incluyendo la portada...

29.6 Recursos
Portadas e ISBNs Libros.zip (/descargas/Libros.zip)
Property list Libros.plist (/descargas/Libros.plist)

29.7 Ejemplos de cdigo


29.7.1 Usar documento del modelo con completion
En ModeloLibros.h
typedef void(^usarDocumentoCompletion)(void);
- (void)usarDocumentoConCompletion:(usarDocumentoCompletion)completion;

En ModeloLibros.m
- (void)usarDocumentoConCompletion:(usarDocumentoCompletion)completion
{
if (![[NSFileManager defaultManager]
fileExistsAtPath:[self.librosDoc.fileURL path]]) {
[self.librosDoc saveToURL:self.librosDoc.fileURL
forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL
success) {
NSLog(@"El documento est creado, hacer consultas...");
completion();
}];
} else if (self.librosDoc.documentState == UIDocumentStateClosed) {
[self.librosDoc openWithCompletionHandler:^(BOOL success) {
NSLog(@"El documento est abierto, hacer consultas...");
completion();
}];
} else if (self.librosDoc.documentState == UIDocumentStateNormal) {
NSLog(@"El documento ya est abierto, hacer consultas...");
completion();
}
}

185

Captulo 29 App: Libros Avanzado

Curso iOS 8

29.7.2 Habilitar editButtonItem en tableView de ViewController


Cuando se pulsa el botn editButtonItem enva a tu ViewController el mensaje setEditing:animated:

As que si has creado un tableView dentro de un ViewController normal y quieres habilitarlo debes crear este mtodo:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
}
#pragma mark - editButtonItem
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
}

Referencias:
Gua Apple: ViewController PG for iOS (http://developer.apple.com/library/ios/
featuredarticles/ViewControllerPGforiPhoneOS/ViewControllerPGforiOS.pdf)
Buscar: Enabling Edit Mode in a View Controller

29.7.3 Cachear foto


Para obtener la representacin en JPG de un UIImage:
if(self.portadaImage) {
NSData *imageData = UIImageJPEGRepresentation(self.portadaImage,
0.6);
self.libro.portada = [[self.libro cachearFoto:imageData]
absoluteString];
}
- (NSURL *)cachearFoto:(NSData *)fotoData
{
NSURL *fotoUrl = [self uniqueFileUrl];
[fotoData writeToURL:fotoUrl atomically:YES];
return fotoUrl;
}
186

Curso iOS 8

Captulo 29 App: Libros Avanzado

Necesitamos crear un nombre de archivo nico para guardar la portada.


Ejemplo de id nicos de objetos de Core Data en formato URI:
x-coredata://54849077-5F4E-49E6-9134-02E0FE2E3243/Libro/p1
x-coredata://54849077-5F4E-49E6-9134-02E0FE2E3243/Libro/p2
Podramos usar los dos componentes finales junto con la fecha y hora actual
- (NSURL *)uniqueFileUrl
{
// Necesito una referencia al modelo para obtener los directorios
para escribir
Libros *libros = [Libros sharedInstance];
// Identificador nico del objeto Core Data separado por componentes
NSArray *components = [[[self objectID] URIRepresentation]
components];
// Creo un formato para obtener la fecha y hora actual con segundos
NSDateFormatter *ddMMyyHHmmss = [[NSDateFormatter alloc] init];
[ddMMyyHHmmss setDateFormat:@"ddMMyyHHmmss"];
NSString *fotoFilename = [NSString stringWithFormat:@"%@_%@_%@.jpg",
components[1], components[2], [ddMMyyHHmmss stringFromDate:[NSDate
dateWithTimeIntervalSinceNow:0]]];
// libros.imagesUel es un directorio que previamente ha creado el
modelo
NSURL *fotoUrl = [libros.imagesUrl
URLByAppendingPathComponent:fotoFilename];
NSLog(@"%@", [fotoUrl path]);
}

29.7.4 Picker de fechas semimodal


Para no tener que crear una pantalla nueva para por ejemplo seleccionar una fecha con un
picker, podemos crear un "teclado personalizado" para nuestros campos de texto y vincularlo con una "semimodal" como esta:

187

Captulo 29 App: Libros Avanzado

Curso iOS 8

Figura 29.1 Custom Picker Semimodal


Esta semimodal no es ms que un View que contiene un toolbar, dos botones y el picker
de fechas:

Figura 29.2 Custom Picker Semimodal


188

Curso iOS 8

Captulo 29 App: Libros Avanzado

Necesitamos conectar los outlets y atender a los target-actions de estos views como hacemos siempre en el mismo ViewController que presenta la semimodal.
En archivo.h
@property (weak, nonatomic) IBOutlet UITextField *fechaInicioText;
@property (weak, nonatomic) IBOutlet UITextField *fechaFinText;
@property (weak, nonatomic) IBOutlet UIView *fechaView;
@property (weak, nonatomic) IBOutlet UIDatePicker *fechaPicker;

En archivo.m
#pragma mark - Setup
- (void)setup
{
ddMMyyyy = [[NSDateFormatter alloc] init];
[ddMMyyyy setDateFormat:@"dd/MM/yyyy"];
fechaInicioText.inputView = fechaView;
fechaFinText.inputView = fechaView;
}
#pragma mark - Fecha
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField == fechaInicioText && fechaInicio) fechaPicker.date =
fechaInicio;
if(textField == fechaFinText && fechaFin) fechaPicker.date =
fechaFin;
fechaSelectedText = textField;
return YES;
}
- (IBAction)fechaCancelarTap:(id)sender {
[self.view endEditing:YES];
}
- (IBAction)fechaAceptarTap:(id)sender {
if(fechaSelectedText == fechaInicioText) fechaInicio =
fechaPicker.date;
if(fechaSelectedText == fechaFinText) fechaFin = fechaPicker.date;
fechaSelectedText.text = [ddMMyyyy stringFromDate:fechaPicker.date];

189

Captulo 29 App: Libros Avanzado

Curso iOS 8

[self.view endEditing:YES];
}

29.7.5 Mi clase modelo Libros completa con .h y .m


En Libros.h
#import
#import
#import
#import

<Foundation/Foundation.h>
"Libro+Metodos.h"
"Autor+Metodos.h"
"Amigo+Metodos.h"

@interface Libros : NSObject


+ (Libros *)sharedInstance;
@property
@property
@property
@property

(strong,
(strong,
(strong,
(strong,

nonatomic)
nonatomic)
nonatomic)
nonatomic)

NSURL *documentsUrl;
NSURL *imagesUrl;
NSURL *librosUrl;
UIManagedDocument *librosDoc;

typedef void(^usarDocumentoCompletion)(void);
- (void)usarDocumentoConCompletion:(usarDocumentoCompletion)completion;
@end

En Libros.m
#import "Libros.h"
@implementation Libros
+ (Libros *)sharedInstance
{
static Libros *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[Libros alloc] init];
});
return sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
// initializations
190

Curso iOS 8

Captulo 29 App: Libros Avanzado

}
return self;
}
- (NSURL *)documentsUrl
{
if(!_documentsUrl) {
_documentsUrl = [[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]
lastObject];
}
return _documentsUrl;
}
- (NSURL *)imagesUrl
{
if(!_imagesUrl) {
_imagesUrl = [self.documentsUrl
URLByAppendingPathComponent:@"images"];
if(![[NSFileManager defaultManager] fileExistsAtPath:[_imagesUrl
path]]) {
NSError *error;
[[NSFileManager defaultManager]
createDirectoryAtURL:_imagesUrl withIntermediateDirectories:YES
attributes:nil error:&error];
if(error) NSLog(@"imagesUrl: %@", error);
}
}
return _imagesUrl;
}
- (NSURL *)librosUrl
{
if(!_librosUrl) {
_librosUrl = [self.documentsUrl
URLByAppendingPathComponent:@"librosDoc"];
}
return _librosUrl;
}
- (UIManagedDocument *)librosDoc
{
if(!_librosDoc) {
_librosDoc = [[UIManagedDocument alloc]
initWithFileURL:self.librosUrl];
191

Captulo 29 App: Libros Avanzado

Curso iOS 8

}
return _librosDoc;
}
- (void)usarDocumentoConCompletion:(usarDocumentoCompletion)completion
{
if (![[NSFileManager defaultManager]
fileExistsAtPath:[self.librosDoc.fileURL path]]) {
[self.librosDoc saveToURL:self.librosDoc.fileURL
forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL
success) {
NSLog(@"El documento est creado, hacer consultas...");
completion();
}];
} else if (self.librosDoc.documentState == UIDocumentStateClosed) {
[self.librosDoc openWithCompletionHandler:^(BOOL success) {
NSLog(@"El documento est abierto, hacer consultas...");
completion();
}];
} else if (self.librosDoc.documentState == UIDocumentStateNormal) {
NSLog(@"El documento ya est abierto, hacer consultas...");
completion();
}
}
@end

192

Foundation

Esta pgina se ha dejado vaca a propsito

194

Captulo NS.1

NSLog

Usado para registrar un log (con fecha y hora) en la consola de depuracin.


void NSLog (
NSString *format,
...
);

Requiere un formato NSString compatible con printf de C y tantos parmetros como


"huecos" haya en el formato.
Ejemplo:
NSLog(@"Formato sin
NSLog(@"Formato con
NSLog(@"Formato con
NSLog(@"Formato con
NSLog(@"Formato con
NSString tambin es

huecos ni parmetros");
hueco int: %i", 2);
hueco float: %f", 3.14);
hueco float sin ceros decimales: %g", 6.0);
hueco objeto (usa mensaje description): %@", @"Un
un objeto");

NS.1.1 Referencias
Gua Apple: Foundation Functions (https://developer.apple.com/library/mac/
documentation/cocoa/reference/foundation/miscellaneous/
foundation_functions/Foundation_Functions.pdf)
Gua Apple: Strings (https://developer.apple.com/library/ios/documentation/
Cocoa/Conceptual/Strings/Strings.pdf)

195

Esta pgina se ha dejado vaca a propsito

196

Captulo NS.2

NSObject
NS.2.1 Introspeccin

Todos los objetos que heredan de NSObject implementan estos tres mtodos:
isKindOfClass: devuelve si un objeto es este tipo de class (herencia incluida)
isMemberOfClass: devuelve si un objeto es exactamente este tipo de class (sin
herencia)
respondsToSelector: devuelve si un objeto responde al un mtodo concreto
Son muy tiles para comprobar si un objeto pertenece a una clase antes de hacer un cast
(conversin de tipos muy peligrosa si nos equivocamos de tipo).
A este tipo de comprobaciones se las denomina Introspeccin, es decir, inspeccionar de forma segura los tipos y valores internos de los objetos.

NS.2.2 Mensaje class

Para obtener el argumento para comparar con una clase utilizar el mensaje class:
[NSString class]

Dentro de un if y con un cast sera as:


if([objeto isKindOfClass:[NSString class]]) {
NSString *nuevo =
[(NSString *)objeto stringByAppendingString:@" nuevo"];
}
197

Captulo NS.2 NSObject

Curso iOS 8

NS.2.3 Conversin @selector()

Para obtener el argumento para comparar con un mensaje utilizar @selector():


@selector(metodoSinParametros)
@selector(metodoConUnParametro:)
@selector(metodoConParametro:yOtroParametro:)

Es importante para no cometer errores darse cuenta que los dos puntos : forman parte de
los nombres de los mtodos.

NS.2.4 Tipo genrico id

Se denomina id al tipo genrico de Objective C para denotar un objeto cualquiera.


Hay que observar que nunca definimos una variable como id *, el asterisco que denota
un puntero ya est implicito en los id
Muchas veces se pasan estos objetos genricos, por ejemplo:
En las colecciones como NSArray se almacenan siempre id y al sacar los objetos de
la coleccin deberemos hacer un cast seguramente tras una comprobacin de clase
En las propiedades delegate, no nos interesa realmente el tipo del delegado, solo
que implemente un protocolo, p.ej. id <MyClassDelegate> delegate
Otras veces, pasamos un objeto generico ciego para que a quien lo recibe no le entren
tentaciones de manipularlo. El sentido es pasar un objeto que luego nos tendrn que
devolver (cookie o context)

198

Captulo NS.3

NSString
Clase fundamental para manejar strings.
La sintaxis ms sencilla para crear uno es:
NSString *unString = @"Hola";

Los objetos NSString son inmutables, es decir, no se pueden cambiar una vez creados.
La clase NSMutableString s permite ser cambiada, pero trabajar con strings inmutables
es ms fcil de lo que parece.
Para obtener un nuevo string a partir de otro basta con crear uno nuevo utilizando un formato o aadiendo texto detrs. Hay multitud de funciones que nos ayudan con esto.

NS.3.1 Mtodos tiles


NS.3.1.1 stringWithFormat
Crear un string usando un formato. Especificadores de formato
(https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/
Articles/formatSpecifiers.html)
NSString *unString = @"Hola";
[NSString stringWithFormat:@"Formato %@ %i %g", unString, entero,
decimal];

199

Captulo NS.3 NSString

Curso iOS 8

NS.3.1.2 stringByAppendingString
NSString *errorTag = @"Error: ";
NSString *errorString = @"premature end of file.";
NSString *errorMessage = [errorTag stringByAppendingString:errorString];

NS.3.2 Tareas
NS.3.2.1 Crear e inicializar
+

+
+
+
+
+
+

string
init
initWithBytes:length:encoding:
initWithBytesNoCopy:length:encoding:freeWhenDone:
initWithCharacters:length:
initWithCharactersNoCopy:length:freeWhenDone:
initWithString:
initWithCString:encoding:
initWithUTF8String:
initWithFormat:
initWithFormat:arguments:
initWithFormat:locale:
initWithFormat:locale:arguments:
initWithData:encoding:
stringWithFormat:
localizedStringWithFormat:
stringWithCharacters:length:
stringWithString:
stringWithCString:encoding:
stringWithUTF8String:

NS.3.2.2 Crear e inicializar desde un fichero


+

stringWithContentsOfFile:encoding:error:
initWithContentsOfFile:encoding:error:
stringWithContentsOfFile:usedEncoding:error:
initWithContentsOfFile:usedEncoding:error:

NS.3.2.3 Crear e inicializar desde una URL


+

200

stringWithContentsOfURL:encoding:error:
initWithContentsOfURL:encoding:error:
stringWithContentsOfURL:usedEncoding:error:
initWithContentsOfURL:usedEncoding:error:

Curso iOS 8

Captulo NS.3 NSString

NS.3.2.4 Escribir a un fichero o URL

writeToFile:atomically:encoding:error:
writeToURL:atomically:encoding:error:
writeToFile:atomically: Deprecated in iOS 2.0
writeToURL:atomically: Deprecated in iOS 2.0

NS.3.2.5 Tamao
length
lengthOfBytesUsingEncoding:
maximumLengthOfBytesUsingEncoding:

NS.3.2.6 Obtener caracteres y bytes

characterAtIndex:
getCharacters:range:
getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
getCharacters: Deprecated in iOS 4.0

NS.3.2.7 Obtener C Strings


cStringUsingEncoding:
getCString:maxLength:encoding:
UTF8String

NS.3.2.8 Combinar Strings


stringByAppendingFormat:
stringByAppendingString:
stringByPaddingToLength:withString:startingAtIndex:

NS.3.2.9 Dividir Strings

componentsSeparatedByString:
componentsSeparatedByCharactersInSet:
stringByTrimmingCharactersInSet:
substringFromIndex:
substringWithRange:
substringToIndex:

NS.3.2.10 Encontrar Caracteres y Substrings

rangeOfCharacterFromSet:
rangeOfCharacterFromSet:options:
rangeOfCharacterFromSet:options:range:
rangeOfString:
rangeOfString:options:
rangeOfString:options:range:
rangeOfString:options:range:locale:
201

Captulo NS.3 NSString

enumerateLinesUsingBlock:
enumerateSubstringsInRange:options:usingBlock:

NS.3.2.11 Reemplazar Substrings


stringByReplacingOccurrencesOfString:withString:
stringByReplacingOccurrencesOfString:withString:options:range:
stringByReplacingCharactersInRange:withString:

NS.3.2.12 Rangos

getLineStart:end:contentsEnd:forRange:
lineRangeForRange:
getParagraphStart:end:contentsEnd:forRange:
paragraphRangeForRange:
rangeOfComposedCharacterSequenceAtIndex:
rangeOfComposedCharacterSequencesForRange:

NS.3.2.13 Convertir a Property List


propertyList
propertyListFromStringsFileFormat

NS.3.2.14 Identificar y comparar

caseInsensitiveCompare:
localizedCaseInsensitiveCompare:
compare:
localizedCompare:
compare:options:
compare:options:range:
compare:options:range:locale:
localizedStandardCompare:
hasPrefix:
hasSuffix:
isEqualToString:
hash

NS.3.2.15 Maysculas y minsculas

202

capitalizedString
capitalizedStringWithLocale:
lowercaseString
lowercaseStringWithLocale:
uppercaseString
uppercaseStringWithLocale:

Curso iOS 8

Curso iOS 8

Captulo NS.3 NSString

NS.3.2.16 Valores numricos

doubleValue
floatValue
intValue
integerValue
longLongValue
boolValue

NS.3.2.17 Trabajar con Encodings


+
+
+

availableStringEncodings
defaultCStringEncoding
localizedNameOfStringEncoding:
canBeConvertedToEncoding:
dataUsingEncoding:
dataUsingEncoding:allowLossyConversion:
description
fastestEncoding
smallestEncoding

NS.3.2.18 Trabajar con Paths


+

pathWithComponents:
pathComponents
completePathIntoString:caseSensitive:matchesIntoArray:filterTypes:
fileSystemRepresentation
getFileSystemRepresentation:maxLength:
isAbsolutePath
lastPathComponent
pathExtension
stringByAbbreviatingWithTildeInPath
stringByAppendingPathComponent:
stringByAppendingPathExtension:
stringByDeletingLastPathComponent
stringByDeletingPathExtension
stringByExpandingTildeInPath
stringByResolvingSymlinksInPath
stringByStandardizingPath
stringsByAppendingPaths:

NS.3.2.19 Trabajar con URLs


stringByAddingPercentEscapesUsingEncoding:
stringByReplacingPercentEscapesUsingEncoding:

203

Captulo NS.3 NSString

Curso iOS 8

NS.3.3 Referencias
Gua Apple: Strings (https://developer.apple.com/library/ios/documentation/
Cocoa/Conceptual/Strings/Strings.pdf)
Gua Apple: Data Formatting (https://developer.apple.com/library/ios/
documentation/Cocoa/Conceptual/DataFormatting/DataFormatting.pdf)

204

Captulo NS.4

NSMutableString
Versin mutable de NSString. Se usa menos de lo que parece.
Hereda de NSString por lo que se pueden usar los mismos mtodos.
Pero puede usarse para cambiar un string in situ:
NSMutableString *ms = [[NSMutableString alloc] initWithString:@"0."];
NSMutableString *ms = [NSMutableString stringWithString:@"0."];
[ms appendString:digit];

NS.4.1 Tareas
NS.4.1.1 Creacin e inicializacin
+ stringWithCapacity:
initWithCapacity:

Ejemplo:
self.display = [NSMutableString stringWithCapacity:20];

NS.4.1.2 Modificacin

appendFormat:
appendString:
deleteCharactersInRange:
insertString:atIndex:
replaceCharactersInRange:withString:
replaceOccurrencesOfString:withString:options:range:
setString:
205

Captulo NS.4 NSMutableString

Curso iOS 8

Ejemplo:
[self.display appendString:digito];

NS.4.2 Referencias
Gua Apple: Strings (https://developer.apple.com/library/ios/documentation/
Cocoa/Conceptual/Strings/Strings.pdf)

206

Captulo NS.5

NSNumber
NSNumber es una subclase de NSValue que ofrece como valor cualquier tipo numrico de

C.

Define un conjunto de mtodos para establecer y obtener el valor con o sin signo de: char,
short int, int, long int, long long int, float, double o BOOL.
Tambin define un mtodo compare: para determinar el orden de dos objetos NSNumber.
Para crear un NSNumber a partir de una constante o una operacin entre constantes se puede usar:
NSNumber *x = @2;
NSNumber *y = @(2 + 2); // El contenido es 4

NS.5.1 Tareas
NS.5.1.1 Creacin
+
+
+
+
+
+
+
+
+
+
+

numberWithBool:
numberWithChar:
numberWithDouble:
numberWithFloat:
numberWithInt:
numberWithInteger:
numberWithLong:
numberWithLongLong:
numberWithShort:
numberWithUnsignedChar:
numberWithUnsignedInt:
207

Captulo NS.5 NSNumber

+
+
+
+

numberWithUnsignedInteger:
numberWithUnsignedLong:
numberWithUnsignedLongLong:
numberWithUnsignedShort:

NS.5.1.2 Inicializacin

initWithBool:
initWithChar:
initWithDouble:
initWithFloat:
initWithInt:
initWithInteger:
initWithLong:
initWithLongLong:
initWithShort:
initWithUnsignedChar:
initWithUnsignedInt:
initWithUnsignedInteger:
initWithUnsignedLong:
initWithUnsignedLongLong:
initWithUnsignedShort:

NS.5.1.3 Valores Numricos

boolValue
charValue
decimalValue
doubleValue
floatValue
intValue
integerValue
longLongValue
longValue
shortValue
unsignedCharValue
unsignedIntegerValue
unsignedIntValue
unsignedLongLongValue
unsignedLongValue
unsignedShortValue

NS.5.1.4 Convertir a String


descriptionWithLocale:
stringValue
208

Curso iOS 8

Curso iOS 8

Captulo NS.5 NSNumber

NS.5.1.5 Comparacin
compare:
isEqualToNumber:

NS.5.1.6 Informacin de tipo C


objCType

209

Esta pgina se ha dejado vaca a propsito

210

Captulo NS.6

NSDate

NS.6.1 Creacion de fechas

Para inicializar un NSDate con la fecha y hora actual:


NSDate *ahora = [NSDate dateWithTimeIntervalSinceNow:0];
NSLog(@"%@", ahora);

NS.6.2 Formatos

Para inicializar una fecha desde un string con un formato especfico:


NSDateFormatter *ddmmyyyy = [[NSDateFormatter alloc] init];
ddmmyyyy.timeStyle = NSDateFormatterNoStyle;
ddmmyyyy.dateFormat = @"dd/MM/yyyy";
NSDate *fecha = [ddmmyyyy dateFromString:@"02/04/2013"];
NSLog(@"%@", fecha);

Tambin se usan formatos para presentarla al usuario:


NSLog(@"formato ddmmyyyy: %@", [ddmmyyyy stringFromDate:fecha]);

Se puede usar un locale para las descripciones en cada idioma:


NSDate *ahora = [NSDate dateWithTimeIntervalSinceNow:0];
NSLocale *esLocale = [[NSLocale alloc]
initWithLocaleIdentifier:@"es-ES"];
NSLog(@"%@", [ahora descriptionWithLocale:esLocale]);

Y usar un formato con un locale especfico:


211

Captulo NS.6 NSDate

ddmmyyyy.locale = esLocale;
NSLog(@"formato ddmmyyyy: %@", [ddmmyyyy stringFromDate:fecha]);

NS.6.3 Tareas
NS.6.3.1 Creacin e inicializacin
+
+
+
+
+

date
dateWithTimeIntervalSinceNow:
dateWithTimeInterval:sinceDate:
dateWithTimeIntervalSinceReferenceDate:
dateWithTimeIntervalSince1970:
init
initWithTimeIntervalSinceNow:
initWithTimeInterval:sinceDate:
initWithTimeIntervalSinceReferenceDate:
initWithTimeIntervalSince1970:

NS.6.3.2 Obtener lmites temporales


+ distantFuture
+ distantPast

NS.6.3.3 Comparacin

isEqualToDate:
earlierDate:
laterDate:
compare:

NS.6.3.4 Obtener intevalos

timeIntervalSinceDate:
timeIntervalSinceNow
timeIntervalSinceReferenceDate
timeIntervalSinceReferenceDate
timeIntervalSince1970

NS.6.3.5 Sumar intervalo


dateByAddingTimeInterval:

NS.6.3.6 Representar dates como strings


description
descriptionWithLocale:

212

Curso iOS 8

Curso iOS 8

Captulo NS.6 NSDate

NS.6.4 Referencias

Gua Apple: Formateo de datos (y fechas) (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DataFormatting/DataFormatting.pdf)

213

Esta pgina se ha dejado vaca a propsito

214

Captulo NS.7

NSValue
Es un objeto genrico para empaquetar otros datos que no son objetos (p.ej. structs de C).
Ejemplo:
NSValue *edgeInsetsObject = [NSValue
valueWithUIEdgeInsets:UIEdgeInsetsMake(1,1,1,1)];

NS.7.1 Tareas
NS.7.1.1 Creacin e inicializacin

+
+
+
+
+

initWithBytes:objCType:
valueWithBytes:objCType:
value:withObjCType:
valueWithNonretainedObject:
valueWithPointer:
valueWithRange:

NS.7.1.2 Acceso a datos

getValue:
nonretainedObjectValue
objCType
pointerValue
rangeValue

NS.7.1.3 Comparacin
isEqualToValue:

215

Esta pgina se ha dejado vaca a propsito

216

Captulo NS.8

NSData

Es un objeto genrico para empaquetar buffers de datos.


Se usa para guardar/restaurar/transmitir datos puros (crudos).

NS.8.1 Tareas
NS.8.1.1 Creacin e inicializacin
+
+
+
+
+
+
+
+
+

data
dataWithBytes:length:
dataWithBytesNoCopy:length:
dataWithBytesNoCopy:length:freeWhenDone:
dataWithContentsOfFile:
dataWithContentsOfFile:options:error:
dataWithContentsOfURL:
dataWithContentsOfURL:options:error:
dataWithData:
initWithBase64EncodedData:options:
initWithBase64EncodedString:options:
initWithBytes:length:
initWithBytesNoCopy:length:
initWithBytesNoCopy:length:deallocator:
initWithBytesNoCopy:length:freeWhenDone:
initWithContentsOfFile:
initWithContentsOfFile:options:error:
initWithContentsOfURL:
initWithContentsOfURL:options:error:
initWithData:
217

Captulo NS.8 NSData

NS.8.1.2 Acceso a datos

bytes
description
enumerateByteRangesUsingBlock:
getBytes:length:
getBytes:range:
subdataWithRange:
rangeOfData:options:range:

NS.8.1.3 Base-64 Encoding


base64EncodedDataWithOptions:
base64EncodedStringWithOptions:

NS.8.1.4 Comparacin y tamao


isEqualToData:
length

NS.8.1.5 Persistencia

218

writeToFile:atomically:
writeToFile:options:error:
writeToURL:atomically:
writeToURL:options:error:

Curso iOS 8

Captulo NS.9

NSArray
Coleccin ordenada de objetos.
Inmutable. Una vez creado no se pueden aadir o quitar objetos.
Normalmente se crea manipulando otros arrays o mediante @[].

NS.9.1 Mtodos tiles


- (NSUInteger)count; // N de elementos
- (id)objectAtIndex:(NSUInteger)index; // Devuelve un id. Crash si el
ndice est fuera de lmites.
- (id)lastObject; // devuelve nil (sin crash) si no hay objetos en el
array
- (id)firstObject; // devuelve nil (sin crash) si no hay objetos en el
array
- (NSArray *)sortedArrayUsingSelector:(SEL)aSelector;
- (void)makeObjectsPerformSelector:(SEL)aSelector
withObject:(id)selectorArgument;
- (NSString *)componentsJoinedByString:(NSString *)separator;

219

Esta pgina se ha dejado vaca a propsito

220

Captulo NS.10

NSMutableArray
Versin mutable de NSArray.
Se crea con alloc/init o
+ (id)arrayWithCapacity:(NSUInteger)numItems; // puede crecer ms que
numItems (espacio inicial)
+ (id)array; // [NSMutableArray array] es igual que [[NSMutableArray
alloc] init]

NSMutableArray hereda todos los mtodos de NSArray: count, objectAtIndex:, etc.

NS.10.1 Mtodos tiles


- (void)addObject:(id)object; // aade el id al final del array
- (void)insertObject:(id)object atIndex:(NSUInteger)index;
- (void)removeObjectAtIndex:(NSUInteger)index;

221

Esta pgina se ha dejado vaca a propsito

222

Captulo NS.11

NSDictionary
NS.11.0.1 NSDictionary
Coleccin inmutable de objetos que se introducen y extraen mediante su clave.
Todas las claves y valores son mantenidas de manera strong por un NSDictionary.
Se pueden crear con esta sintaxis:
@{ key1 : value1, key2 : value2, key3 : value3 }
NSDictionary *colors = @{ @green : [UIColor greenColor],
@blue : [UIColor blueColor],
@red : [UIColor redColor] };

Se pueden extraet mediante la sintaxis simple tipo array []


NSString *colorString = ...;
UIColor *colorObject = colors[colorString]; // funciona igual que
objectForKey:
- (NSUInteger)count;
- (id)objectForKey:(id)key; // la clave debe ser copiable e implementar
`isEqual:` (p.ej. NSStrings)

NS.11.1 Tareas
NS.11.1.1 Creacin
+
+
+
+

dictionary
dictionaryWithContentsOfFile:
dictionaryWithContentsOfURL:
dictionaryWithDictionary:
223

Captulo NS.11 NSDictionary

+
+
+
+

Curso iOS 8

dictionaryWithObject:forKey:
dictionaryWithObjects:forKeys:
dictionaryWithObjects:forKeys:count:
dictionaryWithObjectsAndKeys:

NS.11.1.2 Inicializacin

initWithContentsOfFile:
initWithContentsOfURL:
initWithDictionary:
initWithDictionary:copyItems:
initWithObjects:forKeys:
initWithObjects:forKeys:count:
initWithObjectsAndKeys:
init

NS.11.1.3 Creacin de conjuntos de claves compartidas


+ sharedKeySetForKeys:

NS.11.1.4 Nmero de elementos


count

NS.11.1.5 Comparacin
isEqualToDictionary:

NS.11.1.6 Acceso a claves y valores

allKeys
allKeysForObject:
allValues
getObjects:andKeys:
objectForKey:
objectForKeyedSubscript:
objectsForKeys:notFoundMarker:
valueForKey:

NS.11.1.7 Enumeracin

224

keyEnumerator
objectEnumerator
enumerateKeysAndObjectsUsingBlock:
enumerateKeysAndObjectsWithOptions:usingBlock:

Curso iOS 8

Captulo NS.11 NSDictionary

NS.11.1.8 Ordenacin
keysSortedByValueUsingSelector:
keysSortedByValueUsingComparator:
keysSortedByValueWithOptions:usingComparator:

NS.11.1.9 Filtrado
keysOfEntriesPassingTest:
keysOfEntriesWithOptions:passingTest:

NS.11.1.10 Persistencia
writeToFile:atomically:
writeToURL:atomically:

NS.11.1.11 Acceso a atributos de archivo

fileCreationDate
fileExtensionHidden
fileGroupOwnerAccountID
fileGroupOwnerAccountName
fileHFSCreatorCode
fileHFSTypeCode
fileIsAppendOnly
fileIsImmutable
fileModificationDate
fileOwnerAccountID
fileOwnerAccountName
filePosixPermissions
fileSize
fileSystemFileNumber
fileSystemNumber
fileType

NS.11.1.12 Descripcin

description
descriptionInStringsFileFormat
descriptionWithLocale:
descriptionWithLocale:indent:

225

Esta pgina se ha dejado vaca a propsito

226

Captulo NS.12

NSMutableDictionary
Versin mutable de NSDictionary
Se crean mediante alloc/init o uno de los mtodos de clase
+ (id)dictionary... class methods.

Adems de los mtodos de NSDictionary, estn estos mtodos importantes:


-

(void)setObject:(id)anObject forKey:(id)key;
(void)removeObjectForKey:(id)key;
(void)removeAllObjects;
(void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;

NS.12.1 Tareas
NS.12.1.1 Creacin e inicializacin
+

dictionaryWithCapacity:
initWithCapacity:
init
dictionaryWithSharedKeySet:

NS.12.1.2 Aadir elementos

setObject:forKey:
setObject:forKeyedSubscript:
setValue:forKey:
addEntriesFromDictionary:
setDictionary:

227

Captulo NS.12 NSMutableDictionary

NS.12.1.3 Eliminar elementos


removeObjectForKey:
removeAllObjects
removeObjectsForKeys:

228

Curso iOS 8

Captulo NS.13

NSSet

Coleccin desordenada e inmutable de objetos.


Se utilizan cuando la velocidad de comprobacin de si un objeto existe o no dentro del set
es importante. Para esta tarea son ms rpidos que los arrays.

NS.13.1 Tareas
NS.13.1.1 Creacin
+
+
+
+
+
+

set
setWithArray:
setWithObject:
setWithObjects:
setWithObjects:count:
setWithSet:
setByAddingObject:
setByAddingObjectsFromSet:
setByAddingObjectsFromArray:

NS.13.1.2 Inicializacin

initWithArray:
initWithObjects:
initWithObjects:count:
initWithSet:
initWithSet:copyItems:
init

229

Captulo NS.13 NSSet

NS.13.1.3 Contar elementos


count

NS.13.1.4 Acceso a elementos

allObjects
anyObject
containsObject:
filteredSetUsingPredicate:
makeObjectsPerformSelector:
makeObjectsPerformSelector:withObject:
member:
objectEnumerator
enumerateObjectsUsingBlock:
enumerateObjectsWithOptions:usingBlock:
objectsPassingTest:
objectsWithOptions:passingTest:

NS.13.1.5 Comparacin

isSubsetOfSet:
intersectsSet:
isEqualToSet:
valueForKey:
setValue:forKey:

NS.13.1.6 Creacin de un array ordenado


sortedArrayUsingDescriptors:

NS.13.1.7 Key-Value Observing


addObserver:forKeyPath:options:context:
removeObserver:forKeyPath:context:
removeObserver:forKeyPath:

NS.13.1.8 description
description
descriptionWithLocale:

230

Curso iOS 8

Captulo NS.14

NSMutableSet
Coleccin desordenada y mutable de objetos. Versin mutable de NSSet.
Se utilizan cuando la velocidad de comprobacin de si un objeto existe o no dentro del set
es importante. Para esta tarea son ms rpidos que los arrays.

NS.14.1 Tareas
NS.14.1.1 Creacin
+ setWithCapacity:
initWithCapacity:
init

NS.14.1.2 Aadir y eliminar elementos

addObject:
filterUsingPredicate:
removeObject:
removeAllObjects
addObjectsFromArray:

NS.14.1.3 Combinacin

unionSet:
minusSet:
intersectSet:
setSet:

231

Esta pgina se ha dejado vaca a propsito

232

Captulo NS.15

NSOrderedSet
Coleccin ordenada inmutable de objetos.
Se utilizan cuando la velocidad de comprobacin de si un objeto existe o no dentro del set
es importante. Para esta tarea son ms rpidos que los arrays.

NS.15.1 Tareas
NS.15.1.1 Creacin
+
+
+
+
+
+
+
+
+
+

orderedSet
orderedSetWithArray:
orderedSetWithArray:range:copyItems:
orderedSetWithObject:
orderedSetWithObjects:
orderedSetWithObjects:count:
orderedSetWithOrderedSet:
orderedSetWithOrderedSet:range:copyItems:
orderedSetWithSet:
orderedSetWithSet:copyItems:

NS.15.1.2 Inicializacin

initWithArray:
initWithArray:copyItems:
initWithArray:range:copyItems:
initWithObject:
initWithObjects:
initWithObjects:count:
initWithOrderedSet:
233

Captulo NS.15 NSOrderedSet

initWithOrderedSet:copyItems:
initWithOrderedSet:range:copyItems:
initWithSet:
initWithSet:copyItems:
init

NS.15.1.3 Nmero de elementos


count

NS.15.1.4 Acceso a elementos

containsObject:
enumerateObjectsAtIndexes:options:usingBlock:
enumerateObjectsUsingBlock:
enumerateObjectsWithOptions:usingBlock:
firstObject
lastObject
objectAtIndex:
objectAtIndexedSubscript:
objectsAtIndexes:
indexOfObject:
indexOfObject:inSortedRange:options:usingComparator:
indexOfObjectAtIndexes:options:passingTest:
indexOfObjectPassingTest:
indexOfObjectWithOptions:passingTest:
indexesOfObjectsAtIndexes:options:passingTest:
indexesOfObjectsPassingTest:
indexesOfObjectsWithOptions:passingTest:
objectEnumerator
reverseObjectEnumerator
reversedOrderedSet
getObjects:range:

NS.15.1.5 Key-Value Coding


setValue:forKey:
valueForKey:

NS.15.1.6 Key-Value Observing


addObserver:forKeyPath:options:context:
removeObserver:forKeyPath:
removeObserver:forKeyPath:context:

234

Curso iOS 8

Curso iOS 8

Captulo NS.15 NSOrderedSet

NS.15.1.7 Comparacin

isEqualToOrderedSet:
intersectsOrderedSet:
intersectsSet:
isSubsetOfOrderedSet:
isSubsetOfSet:

NS.15.1.8 Creacin de un array ordenado


sortedArrayUsingDescriptors:
sortedArrayUsingComparator:
sortedArrayWithOptions:usingComparator:

NS.15.1.9 Filtrado
filteredOrderedSetUsingPredicate:

NS.15.1.10 Descripcin
description
descriptionWithLocale:
descriptionWithLocale:indent:

NS.15.1.11 Conversin
array
set

235

Esta pgina se ha dejado vaca a propsito

236

Captulo NS.16

NSMutableOrderedSet
Versin mutable de NSOrderedSet.

NS.16.1 Tareas
NS.16.1.1 Creacin
+ orderedSetWithCapacity:
initWithCapacity:
init

NS.16.1.2 Aadir, eliminar y reordenar elementos

addObject:
addObjects:count:
addObjectsFromArray:
insertObject:atIndex:
setObject:atIndexedSubscript:
insertObjects:atIndexes:
removeObject:
removeObjectAtIndex:
removeObjectsAtIndexes:
removeObjectsInArray:
removeObjectsInRange:
removeAllObjects
replaceObjectAtIndex:withObject:
replaceObjectsAtIndexes:withObjects:
replaceObjectsInRange:withObjects:count:
setObject:atIndex:
moveObjectsAtIndexes:toIndex:
237

Captulo NS.16 NSMutableOrderedSet

exchangeObjectAtIndex:withObjectAtIndex:
filterUsingPredicate:

NS.16.1.3 Ordenacin

sortUsingDescriptors:
sortUsingComparator:
sortWithOptions:usingComparator:
sortRange:options:usingComparator:

NS.16.1.4 Combinacin

238

intersectOrderedSet:
intersectSet:
minusOrderedSet:
minusSet:
unionOrderedSet:
unionSet:

Curso iOS 8

Captulo NS.17

NSCountedSet
Coleccin mutable, desordenada de objetos indistintos.
Util en el caso de necesitar llevar la cuenta del nmero de veces que se ha aadido un mismo elemento.

NS.17.1 Tareas
NS.17.1.1 Inicializacin
initWithArray: initWithSet: initWithCapacity:

NS.17.1.2 Aadir y eliminar elementos


addObject: removeObject:

NS.17.1.3 Contador de elemento


countForObject:

NS.17.1.4 Enumeracin
objectEnumerator

239

Esta pgina se ha dejado vaca a propsito

240

Captulo NS.18

Enumeracin rpida
NS.18.1 Sentencia for(... in ...) { ... }

Utilizado para pasar cmodamente por todos los miembros de una coleccin de manera
rpida y eficiente

NS.18.2 Ejemplo 1: NSArray de objetos NSString


NSArray *array = @[
@"Lunes",
@"Martes",
@"Mircoles",
@"Jueves",
@"Viernes"
];

Log recursivo utilizando llamada a mtodo description de cada objeto:


NSLog(@"array (%i): %@", [array count], array);

Enumeracin rpida utilizando for(in):


NSLog(@"enumeracin rpida array: ");
for(NSString *elemento in array) {
NSLog(@"elemento: %@", elemento);
}

NS.18.3 Ejemplo 2: NSDictionary con claves y valores NSString


Funciona exactamente igual de fcil con NSDictionary o cualquier otra coleccin:

241

Captulo NS.18 Enumeracin rpida

NSDictionary *diccionario = @{
@"Nombre" : @"Juan",
@"Apellido" : @"Fernndez",
@"Edad" : @22
};

Log recursivo utilizando llamada a mtodo description de cada objeto:


NSLog(@"diccionario (%i): %@", [diccionario count], diccionario);

Enumeracin rpida utilizando for(in):


NSLog(@"enumeracin rpida diccionario: ");
for (id clave in diccionario) {
//id valor = [diccionario objectForKey:clave];
id valor = [diccionario valueForKey:clave];
NSLog(@"elemento %@ => %@", clave, valor);
}

242

Curso iOS 8

Captulo NS.19

Sintaxis Simple
NS.19.1 Crear nuevo proyecto de Xcode Single View
El archivo ViewController.m inicialmente debera tener un cdigo similar a este:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Aqu insertaremos nuestro cdigo y
// veremos los resultados en la consola de depuracin
}
@end

NS.19.2 NSString
NSString *textoSimple = @"Esto es un texto";
NSLog(@"textoSimple: %@", textoSimple);

NS.19.3 NSNumber
NSNumber *numero = [NSNumber numberWithInt:20];
NSLog(@"numero: %@", numero);
NSNumber *numeroSimple = @20;
NSLog(@"numeroSimple: %@", numeroSimple);
NSNumber *numeroSumado = [NSNumber numberWithInt:20+2];
NSLog(@"numeroSumado: %@", numeroSumado);
243

Captulo NS.19 Sintaxis Simple

NSNumber *numeroSimpleSumado = @(20+2);


NSLog(@"numeroSimpleSumado: %@", numeroSimpleSumado);
NSNumber *suma = [NSNumber numberWithInt:[numero intValue] +
[numeroSimple intValue]];
NSLog(@"suma: %@", suma);

NS.19.4 NSArray
NSArray *array = @[
@"Lunes",
@"Martes",
@"Mircoles",
@"Jueves",
@"Viernes"
];
NSLog(@"array (%i): %@", [array count], array);
NSLog(@"enumeracin rpida array: ");
for (NSString *elemento in array) {
NSLog(@"elemento: %@", elemento);
}

NS.19.5 NSDictionary
NSDictionary *diccionario = @{
@"Nombre" : @"Fer",
@"Apellido" : @"Alava",
@"Edad" : @39
};
NSLog(@"diccionario (%i): %@", [diccionario count], diccionario);
NSLog(@"enumeracin rpida diccionario: ");
for (id clave in diccionario) {
//id valor = [diccionario objectForKey:clave];
id valor = [diccionario valueForKey:clave];
NSLog(@"elemento %@ => %@", clave, valor);
}

NS.19.6 NSSet
NSSet *conjunto = [NSSet setWithArray:@[
@"rojo",
@"verde",
@"azul"
]];
NSLog(@"conjunto (%i): %@", [conjunto count], conjunto);

244

Curso iOS 8

Curso iOS 8

Captulo NS.19 Sintaxis Simple

NSLog(@"enumeracin rpida conjunto: ");


for (NSString *elemento in conjunto) {
NSLog(@"elemento: %@", conjunto);
}

NS.19.7 NSCountedSet
NSCountedSet *conjuntoConContador = [NSCountedSet setWithArray:@[
@"rojo",
@"rojo",
@"verde",
@"verde",
@"verde",
@"azul"
]];
NSLog(@"conjunto (%i): %@", [conjuntoConContador count],
conjuntoConContador);
NSLog(@"enumeracin rpida conjuntoConContador: ");
for (NSString *elemento in conjuntoConContador) {
NSLog(@"elemento (%i): %@", [conjuntoConContador
countForObject:elemento], conjuntoConContador);
}

245

Esta pgina se ha dejado vaca a propsito

246

Captulo NS.20

Property Lists
El trmino Property List se utiliza para denotar una coleccin que contiene solo objetos y
colecciones bsicos. Es solo una frase.
Sera el equivalente a un JSON de JavaScript.
Estos tipos y colecciones bsicos son exactamente:
NSArray, NSDictionary, NSNumber, NSString, NSDate, NSData o sus versiones
mutables.
Por ejemplo:
Un NSArray de NSString es una Property List
List.
Un NSArray ser una Property List si todos los objetos que hay dentro pertenece a
esos tipos bsicos.
Un NSDictionary es una Property List si y solo si todas las claves y valores tambin pertenece a esos tipos bsicos.
Ejemplos:
Un NSArray de NSDictionarys cuyas claves sean NSStrings y valores sean
NSNumbers es una Property List
List.
Y por qu se define este trmino?
Porque el SDK tiene muchos mtodos que requieren para operar Property Lists
Lists.
247

Captulo NS.20 Property Lists

Curso iOS 8

Por ejemplo:
- (void)writeToFile:(NSString *)path atomically:(BOOL)atom;

Este mtodo solo se le puede mandar a un NSArray o NSDictionary que sean Property
Lists
Lists.

248

Captulo NS.21

NSUserDefaults
Espacio de almacenamiento ligero para Property Lists
Es bsicamente un diccionario que persiste entre ejecuciones de nuestra aplicacin.
No es una base de datos completa, solo se guardan cosas pequeas ah.
Se escriben y leen mediante una instacia compartida que se obtiene mediante: [NSUserDefaults standardUserDefaults].
[[NSUserDefaults standardUserDefaults] setArray:rvArray
forKey:@"RecentlyViewed"];

Mtodos:
- (void)setDouble:(double)aDouble forKey:(NSString *)key;
- (NSInteger)integerForKey:(NSString *)key;
- (void)setObject:(id)obj forKey:(NSString *)key; // obj debe ser
Property List
- (NSArray *)arrayForKey:(NSString *)key; // devuevle nil si el valor
para esa clave no es un NSArray

Recordar siempre sincronizar (guardar) los cambios tras efectuarlos:


[[NSUserDefaults standardUserDefaults] synchronize];

249

Esta pgina se ha dejado vaca a propsito

250

Captulo NS.22

Singleton
NS.22.1 Interfaz pblico
En MiSingleton.h:

#import <Foundation/Foundation.h>
@interface MiSingleton : NSObject
+ (MiSingleton *)sharedInstance;
@end

NS.22.2 Implementacin
En MiSingleton.m:

@implementation MiSingleton
+ (MiSingleton *)sharedInstance
{
static MiSingleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[MiSingleton alloc] init];
});
return sharedInstance;
}
@end

251

Captulo NS.22 Singleton

Aadir mtodo init:


- (id)init
{
self = [super init];
if (self) {
// cdigo inicializacin...
}
return self;
}

252

Curso iOS 8

UIKit

Esta pgina se ha dejado vaca a propsito

254

Captulo UI.1

UIViewController
UI.1.1 Ciclo de vida

Los View Controllers tiene un ciclo de vida.


Se les enva una secuencia de mensajes segn sta progresa.
Es importante saber cuales para poder introducir cdigo en ellos
El principio de ciclo de vida es la creacin:
Los MVCs se suelen instanciar del Storyboard.
Tambin es posible hacerlo desde cdigo.
Tras la instanciacin y establecimiento de outlets se enva viewDidLoad. El mejor lugar
para cdigo de inicializacin.
- (void)viewDidLoad
{
[super viewDidLoad];
// do some setup of my MVC
}

Lo nico, la geometra de las views no est establecida an. En este momento no sabemos
si estamos en un iPhone 5 o en un iPad. As que no hay que realizar inicializacin que dependa de la geometra.
Justo antes de aparecer en la pantalla se nos notifica con:
255

Captulo UI.1 UIViewController

Curso iOS 8

- (void)viewWillAppear:(BOOL)animated;

El View Controller se carga una vez, pero puede aparecer y desaparecer de la pantalla muchas veces.
Si pones cdigo de inicializacin aqu se ejecutar muchas veces tambin. Aqu si est establecida la geometra.
Tambin somos avisados cuando el View Controller desaparecer de la pantalla.
Estes lugar es til para cdigo de limpieza (desuscripcin de notificaciones)
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self rememberScrollPosition];
[self saveDataToPermanentStore];
}

Tambin hay versiones did de ambos mtodos:


- (void)viewDidAppear:(BOOL)animated;
- (void)viewDidDisappear:(BOOL)animated;

UI.1.1.1 Cambio de geometra


Se suele gestionar automticamente con Autolayout:
- (void)view{Will,Did}LayoutSubviews;

Se llaman cada vez que el frame cambia y sus subviews son reubicadas, por ejemplo con la
autorotacin.
Aqu se pueden resetear los frames de nuestras views o establecer otras propiedades que
son afectadas por la geometra. Entre will y did, ocurre el Autolayout.

UI.1.1.2 Autorotacin
Cuando se rota el dispositivo el view ms alto de la jerarqua tendr sus bounds reoriendados si:
El ViewController devuelve YES en shouldAutorotate.
El ViewController devuelve la nueva orientacin en
supportedInterfaceOrientations.
La aplicacin permite la rotacin a esa orientacin. Se define en Info.plist.
256

Curso iOS 8

Captulo UI.1 UIViewController

Generalmente es buena idea soportar la rotacin en los MVCs.


Notacin especfica cuando suceden las rotaciones:
(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)anOrientation
duration:(NSTimeInterval)seconds;
(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOriention)orient
duration:(NSTimeInterval)seconds;
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)anOrientation;

Esta propiedad guarda la orienzacin cuando se llama a los mtodos anteriores:


@property UIInterfaceOrientation interfaceOrientation;

Ahora es raro implementar esto teniendo Autolayout y los mtodos viewWillLayoutSubviews.

UI.1.1.3 didReceiveMemoryWarning
En situaciones de poca memoria se enva didReceiveMemoryWarning
Todo lo que pueda ser recreado debera aqu ser eliminado (estableciendo sus punteros a
nil).

UI.1.1.4 awakeFromNib
Este mtodo se enva a todos los objetos que salen del Storyboard (incluyendo al controlador).
Ocurre antes de que los outlets se establezcan. Pon el cdigo en otro lugar si es posible
(viewDidLoad o viewWillAppear:).
Todo lo que vaya en el mtodo init tambin deber ir en awakeFromNib porque los mtodos init no se llaman para los objetos que salen del Storyboard.
Ejemplo:
- (void)setup {};
- (void)awakeFromNib { [self setup]; }
// El init designado de UIViewController es initWithNibName:bundle:
- (instancetype)initWithNibName:(NSString *)name bundle:(NSBundle
*)bundle
{
257

Captulo UI.1 UIViewController

Curso iOS 8

self = [super initWithNibName:name bundle:bundle];


[self setup];
return self;
}

UI.1.1.5 Sumario
Instanciacin del from storyboard:
awakeFromNib
outlets establecidos
viewDidLoad
se determina la geometra
viewWillLayoutSubviews: y viewDidLayoutSubviews:
Tantas veces como el MVC aparezca y desaparezca de la pantalla:
viewWillAppear: y viewDidAppear:
si cambia la geometra: viewWillLayoutSubviews: y viewDidLayoutSubviews:
si hay autorotacin will/didRotateTo/From
viewWillDisappear: y viewDidDisappear:
si queda poca memoria: didReceiveMemoryWarning

258

Captulo UI.2

UIView

UI.2.1 Vistas o views

Una vista o view (p.ej. una subclase de UIView) representa una rea rectangular.
Define un espacio de coordenadas
Su responsabilidad es dibuja y gestionar eventos en ese rectngulo.
Son jerrquicas:
Un view tiene solo una superview:
- (UIView *)superview

Pero puede tener muchas (o cero) subviews:


- (NSArray *)subviews

El orden de las subviews importa (en dicho array): Las que estn al final del array estn encima de las que estn al principio (porque se dibujan encima).
Una view puede recortar opcionalmente a sus subviews segn sus lmites / bounds. Esto
se cambia en Xcode o bien con un mtodo de UIView

UI.2.1.1 UIWindow
Es el UIView que est en el origen de la jerarqua.

259

Captulo UI.2 UIView

Curso iOS 8

Solo hay un UIWindow (generalmente) en una app de iOS. Se trabaja con views no con windows.
Las jerarquas normalmente las hacemos en el Storyboard. Incluso las custom views las
aadimos as y luego les asignamos su clase.
Pero tambin se puede hacer en cdigo:
- (void)addSubview:(UIView *)aView; // sent to aViews (soon to be)
superview
- (void)removeFromSuperview; // sent to the view that is being removed

UI.2.1.2 Inicializar un UIView


Por la misma razn que con los UIViewController (no siempre se ejecuta el init) se suele
llamar al cdigo de inicializacin tambin desde awakeFromNib.
Cdigo de ejemplo:
- (void)setup { ... }
- (void)awakeFromNib { [self setup]; }
- (id)initWithFrame:(CGRect)aRect
{
self = [super initWithFrame:aRect];
[self setup];
return self;
}

UI.2.1.3 Coordenadas de View


- CGFloat: Simplemente un float (nmero en coma flotante) (puede ser de 64-bit o no), pero se usa siempre para grficos.
CGPoint: struct de C con dos CGFloats: x e y.
CGPoint p = CGPointMake(34.5, 22.0);
p.x += 20; // mover 20 puntos a la derecha

CGSize: struct de C con dos CGFloats: width y height.


CGSize s = CGSizeMake(100.0, 200.0);
s.height += 50; // 50 puntos ms alta

CGRect: struct de C con un CGPoint origin y un CGSize size.

260

Curso iOS 8

Captulo UI.2 UIView

CGRect aRect = CGRectMake(45.0, 75.5, 300, 500);


aRect.size.height += 45; // rectngulo 45 puntos ms alto
aRect.origin.x += 30; // mover el rectngulo 30 puntos a la derecha

UI.2.1.4 Graphics State


Consideraciones especiales para subrutinas de dibujo:
Qu ocurre si quieres tener mtodos de utilidad que dibujan cosas?
No querremos tocar el graphics state del mtodo que los llama. Usaremos las funciones para guardar/recuperar el contexto:
- (void)drawGreenCircle:(CGContextRef)ctxt {
CGContextSaveGState(ctxt);
[[UIColor greenColor] setFill];
// draw my circle
CGContextRestoreGState(ctxt);
}
- (void)drawRect:(CGRect)aRect {
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor redColor] setFill];
// do some stuff
[self drawGreenCircle:context];
// do more stuff and expect fill color to be red
}

UI.2.1.5 Dibujar texto


Podemos usar un UILabel como subview para dibujar texto en nuestra view.
Pero hay ocasiones en las que queremos dibujar directamente el texto en drawRect:.
Para ello usaremos NSAttributedString:
NSAttributedString *text = ...;
[text drawAtPoint:(CGPoint)p]; // NSAttributedString instance method
added by UIKit

Cuando espacio ocupar un texto cuando sea dibujado?


CGSize textSize = [text size]; // another UIKit NSAttributedString
instance method

261

Captulo UI.2 UIView

Curso iOS 8

Si os extraa que haya mtodos de dibujar en Foundation. En realidad estos mtodos se


definen en UIKit mediante un mecanismo de Objetive C llamado categoras. Al igual que
los nombres de los atributos como NSFontAttributeName
Las categoras permiten aadir mtodos a clases existentes sin utilizar la crear subclases.

UI.2.1.6 Dibujar imgenes


UIImageView es como el UILabel de las imgenes.

Pero puede que queramos dibujar directamente una UIImage con en el drawRect:.
Crear un objeto UIImage desde un archivo del directorio de Xcode:
UIImage *image = [UIImage imageNamed:@"foo.jpg"]; // you did this in
Matchismo

O crear una desde el nombre de un archivo o datos crudos:


UIImage *image = [[UIImage alloc] initWithContentsOfFile:(NSString
*)fullPath];
UIImage *image = [[UIImage alloc] initWithData:(NSData *)imageData];

Se puede crear una dibujando con las funciones de CGContext:


UIGraphicsBeginImageContext(CGSize);
// draw with CGContext functions
UIImage *myImage = UIGraphicsGetImageFromCurrentContext();
UIGraphicsEndImageContext();

Pasar los bits de UIImage al graphics context:


UIImage *image = ...;
[image drawAtPoint:(CGPoint)p]; // p is upper left corner of the image
[image drawInRect:(CGRect)r]; // scales the image to fit in r
[image drawAsPatternInRect:(CGRect)patRect; // tiles the image into
patRect

Adems, se puede obtener la representacin PNG o JPG de UIImage con:


NSData *jpgData = UIImageJPEGRepresentation((UIImage *)myImage,
(CGFloat)quality);
NSData *pngData = UIImagePNGRepresentation((UIImage *)myImage);

262

Curso iOS 8

Captulo UI.2 UIView

UI.2.1.7 Redibujar con el cambio de lmites / bounds


Por defecto cuando cambian los bounds, no hay redraw.
En su lugar, los pixels del view se mueven o estiran.
Muchas veces no queremos esto... Afortunadamente, hay una propiedad de UIView que
controla esto.
Se puede cambiar en Xcode:
@property (nonatomic) UIViewContentMode contentMode;

Estos modos mueven los bits del dibujo a esa ubicacin:


UIViewContentMode{Left,Right,Top,Right,BottomLeft,BottomRight,TopLeft,TopRight}

Estos estiran o encojen el dibujo:


UIViewContentModeScale{ToFill,AspectFill,AspectFit} // bit stretching/shrinking
Este modo llama a drawRect: para redibujar todo:
UIViewContentModeRedraw // el ms habitual

Por defecto es UIViewContentModeScaleToFill (estirar o encojer para rellenar los lmites / bounds)

263

Esta pgina se ha dejado vaca a propsito

264

Captulo UI.3

UIGestureRecognizer
UI.3.1 Cmo reconocemos toques?

Podramos ser avisados con los eventos de toque/touch directamente, pero es ms sencillo ser avisados cuando se reconoce un gesto/gesture

UI.3.2 UIGestureRecognizer

Es la clase que reconoce los gestos. Es abstracta, solo usamos subclases concretas de ella
Hay dos partes para usar un gesture recognizer
1. Aadir un *gesture recognizer* a un `UIView` para pedirle que
reconozca gestos sobre ese view
2. Proporcionar la implementacin de un mtodo para ser llamado cuando
el gesto ocurra

El punto 1 lo suele hacer un Controlador.


Aunque ocasionalmente un UIView podra hacerlo si no tiene sentido sin ese gesto (scroll).
El punto 2 lo suele proveer la propia UIView, aunque podra hacerlo tambin el Controlador.
Tambin podra ocurrir que el Controlador decida que quiere gestionar un gesto de manera diferente a como lo hace esa Vista.
As se aade un gesture recognizer a un UIView desde el Controlador:

265

Captulo UI.3 UIGestureRecognizer

Curso iOS 8

- (void)setPannableView:(UIView *)pannableView // maybe this is a setter


in a Controller
{
_pannableView = pannableView;
UIPanGestureRecognizer *pangr =
[[UIPanGestureRecognizer alloc] initWithTarget:pannableView
action:@selector(pan:)];
[pannableView addGestureRecognizer:pangr];
}

Esta es una clase concreta de UIGestureRecognizer que reconoce panning (arrastrar el


dedo).
Hay otras clases concretas para swipe, pinch y tap.
En el ejemplo anterior el view es el target para reconocer el pan.
No siempre el UIView tiene que interpretar el gesto, podra haber sido el Controlador:
La vista interpretar los gestos que modifican cmo se dibuja ella misma.
El controlador interpretar los gestos que modifican el modelo.
Solo los UIView pueden reconocer gestos porque son los que gestionan todos los toques sobre ellas:
Pero cualquier objeto puede mandar la orden a un UIView para que empiece a
reconocer gestos (aadiendole el reconocedor)
Y cualquier objeto puede interpretar ese reconocimiento (siendo el target de la
accin del gesto)

UI.3.3 Cmo implementamos el target de un gesture recognizer?


Cada clase concreta proporciona mtodos de ayuda tiles.

Por ejemplo, UIPanGestureRecognizer proporciona 3 mtodos:


- (CGPoint)translationInView:(UIView *)aView;
- (CGPoint)velocityInView:(UIView *)aView;
- (void)setTranslation:(CGPoint)translation inView:(UIView *)aView;

Tambin, la clase base, UIGestureRecognizer proporciona esta propiedad:


@property (readonly) UIGestureRecognizerState state;
266

Curso iOS 8

Captulo UI.3 UIGestureRecognizer

El gesture recognizer se mantienen en el estado Possible hasta que inicia el reconocimiento del gesto.
Entonces para a Recognized para gestos discretos como tap.
O pasan a Began para gestos continuos como pan.
En cualquier momento el estado puede pasar a Failed (hay que comprobarlo)
Si el gesto es contnuo, ir pasando al estado Changed hasta llegar a Ended o bien a Cancelled (si al final el gesto no lo era realmente)
As podra implementarse un pan::
- (void)pan:(UIPanGestureRecognizer *)recognizer
{
if ((recognizer.state == UIGestureRecognizerStateChanged) ||
(recognizer.state == UIGestureRecognizerStateEnded)) {
CGPoint translation = [recognizer translationInView:self];
// move something in myself (Im a UIView) by translation.x
and translation.y
// for example, if I were a graph and my origin was set by
an @property called origin
self.origin = CGPointMake(self.origin.x+translation.x,
self.origin.y+translation.y);
[recognizer setTranslation:CGPointZero inView:self];
}
}

UI.3.4 Otros gestos


UI.3.4.1 UIPinchGestureRecognizer
@property CGFloat scale; // no es readonly, se puede resetear con cada
movimiento
@property (readonly) CGFloat velocity; // readonly, factor de escala por
segundo

UI.3.4.2 UIRotationGestureRecognizer
@property CGFloat rotation; // no es readonly, en radianes
@property (readonly) CGFloat velocity; // readonly; radianes por segundo

UI.3.4.3 UISwipeGestureRecognizer
Se configura para reconocer ciertos tipos de swipe, y entonces se comprueba si el estado es
Recognized
267

Captulo UI.3 UIGestureRecognizer

Curso iOS 8

@property UISwipeGestureRecognizerDirection direction; // direccin


deseada
@property NSUInteger numberOfTouchesRequired; // con un dedo, dos,
tres...

UI.3.4.4 UITapGestureRecognizer
Configurar las propiedades y luego comprobar el estado Recognized
@property NSUInteger numberOfTapsRequired; // un tap o doble, triple,
etc.
@property NSUInteger numberOfTouchesRequired; // un dedo, dos, tres...

268

Captulo UI.4

UIScrollView
UI.4.1 App de Ejemplo

Figura UI.4.1 Foto Scroll

269

Captulo UI.4 UIScrollView

Curso iOS 8

UI.4.1.1 ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (strong, nonatomic) UIImageView *imageView;
@end

UI.4.1.2 ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
#pragma mark View Life Cycle
- (void)viewDidLoad
{
[super viewDidLoad];
[self meterImagenEnScrollView];
[self activarEscaladoEnScrollView];
}
- (void)viewDidAppear:(BOOL)animated
{
[self.scrollView flashScrollIndicators];
}
- (void)meterImagenEnScrollView
{
UIImage *image = [UIImage imageNamed:@"Mireia.jpg"];
self.imageView = [[UIImageView alloc] initWithImage:image];
[self.scrollView addSubview:self.imageView];
[self.scrollView setContentSize:self.imageView.bounds.size];
}
- (void)activarEscaladoEnScrollView
{
self.scrollView.minimumZoomScale = 0.2;
self.scrollView.maximumZoomScale = 2.0;
}
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
#pragma mark Botones
- (IBAction)min:(UIBarButtonItem *)sender {
[self.scrollView zoomToRect:self.imageView.bounds animated:YES];
}
- (IBAction)cara:(UIBarButtonItem *)sender {
270

Curso iOS 8

Captulo UI.4 UIScrollView

NSLog(@"%g %g", self.imageView.bounds.size.width,


self.imageView.bounds.size.height);
[self.scrollView zoomToRect:CGRectMake(700, 500, 200, 200)
animated:YES];
}
- (IBAction)max:(UIBarButtonItem *)sender {
[self.scrollView zoomToRect:CGRectMake(300, 300, 800, 800)
animated:YES];
}
@end

271

Esta pgina se ha dejado vaca a propsito

272

Captulo UI.5

UICollectionViewController
UI.5.1 Mtodos en UICollectionViewDatasource
- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView
*)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)view
numberOfItemsInSection:(NSInteger)section {
return [self.fotos count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv
dequeueReusableCellWithReuseIdentifier:@"Foto" forIndexPath:indexPath];
return cell;
}

UI.5.2 Celda personalizada

En el Storyboard debemos configurar nuestra celda y adems para poder usar un UICollectionViewController debemos crear una subclase de UICollectionViewCell, ya
que no hay ningn tipo bsico por defecto.

UI.5.3 Referencia
Lecture Stanford 2013 (/descargas/CollectionView.pdf)
273

Captulo UI.5 UICollectionViewController

Gua Apple: Collection View Programming Guide for iOS


(http://developer.apple.com/library/ios/documentation/WindowsViews/
Conceptual/CollectionViewPGforIOS/CollectionViewPGforIOS.pdf)

274

Curso iOS 8

Captulo UI.6

UISplitView
UI.6.1 MaestroTableViewController.h
[objc]

#import <UIKit/UIKit.h>
@interface MaestroTableViewController : UITableViewController
@end

UI.6.2 MaestroTableViewController.m
#import "MaestroTableViewController.h"
#import "DetalleViewController.h"
#import "DetalleViewControllerDelegate.h"
@interface MaestroTableViewController ()
<UISplitViewControllerDelegate,UINavigationControllerDelegate>
@property (strong, nonatomic) UIBarButtonItem *botonSplitView;
@property (strong, nonatomic) UIPopoverController *popover;
@end
@implementation MaestroTableViewController
-(void)awakeFromNib
{
NSLog(@"MaestroTableViewController awakeFromNib");
// Establecerse como delegado del SplitView
self.splitViewController.delegate = self;
// Establecerse como delegado del Detalle Navigation Controller
UINavigationController *detalleNav =
self.splitViewController.viewControllers[1];
detalleNav.delegate = self;
}
275

Captulo UI.6 UISplitView

Curso iOS 8

- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"MaestroTableViewController viewDidLoad");
// Uncomment the following line to preserve selection between
presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the
navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return 0;
}
#pragma mark UISplitViewControllerDelegate
-(BOOL)splitViewController:(UISplitViewController *)svc
shouldHideViewController:(UIViewController *)vc
inOrientation:(UIInterfaceOrientation)orientation
{
// No ocultar el master en ninguna orientacin
// return NO;
return UIInterfaceOrientationIsPortrait(orientation);
}
-(void)splitViewController:(UISplitViewController *)splitView
willHideViewController:(UIViewController *)master
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)popover
{
NSLog(@"Ttulo maestro: %@", self.title);
NSLog(@"Ttulo navigationItem: %@", self.navigationItem.title);
barButtonItem.title = self.navigationItem.title;
self.botonSplitView = barButtonItem;
self.popover = popover;
// Obtener referencia al detalle del splitView
// que es un navigation controller
UINavigationController *detalleNav =
276

Curso iOS 8

Captulo UI.6 UISplitView

self.splitViewController.viewControllers[1];
// Obtener referencia a la pantalla visible del navigation controller
// que debe implementar el protocolo DetalleViewControllerDelegate
id <DetalleViewControllerDelegate> detalle =
(id <DetalleViewControllerDelegate>)detalleNav.topViewController;
NSLog(@"Detalle: %@", detalle);
[detalle ponerBotonSplitView:self.botonSplitView];
}
-(void)splitViewController:(UISplitViewController *)splitView
willShowViewController:(UIViewController *)master
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
self.botonSplitView = nil;
self.popover = nil;
// Obtener referencia al detalle del splitView
// que es un navigation controller
UINavigationController *detalleNav =
self.splitViewController.viewControllers[1];
// Obtener referencia a la pantalla visible del navigation controller
// que debe implementar el protocolo DetalleViewControllerDelegate
id <DetalleViewControllerDelegate> detalle =
(id <DetalleViewControllerDelegate>)detalleNav.topViewController;
NSLog(@"Detalle: %@", detalle);
[detalle quitarBotonSplitView:barButtonItem];
}
#pragma mark UINavigationControllerDelegate
-(void)navigationController:(UINavigationController
*)navigationController willShowViewController:(UIViewController
*)viewController animated:(BOOL)animated
{
id <DetalleViewControllerDelegate> detalle =
(id <DetalleViewControllerDelegate>)viewController;
if (self.botonSplitView) {
[detalle ponerBotonSplitView:self.botonSplitView];
} else {
[detalle quitarBotonSplitView:self.botonSplitView];
}
}
@end

277

Esta pgina se ha dejado vaca a propsito

278

Captulo UI.7

UIPopoverController
UI.7.1 Bugs!
UI.7.1.1 Popover segue y viewDidLoad del contenido
El popover segue y la inicializacin del contenido se ejecutan en paralelo y a veces el viewDidLoad se ejecuta antes de terminar la ejecucin del prepareForSegue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(@"prepareForSegue %@", segue.identifier);
if([segue.identifier isEqualToString:@"ToolBarTransicionPopover"]) {
if([segue.destinationViewController
isKindOfClass:[PopoverViewController class]]) {
PopoverViewController *contenido =
segue.destinationViewController;
[contenido setUrl:@"http://www.apple.es/"];
// Debemos llamar a la inicializacin del contenido ya que
// su viewDidLoad podra haberse ejecutado antes de tiempo
[contenido setup];
}
}
}

UI.7.1.2 Popover segue desde el botn de una toolbar


El Popover no se cierra automticamente al pulsar repetidamente el botn de una toolbar.

279

Captulo UI.7 UIPopoverController

Curso iOS 8

Para cerrarlo hay que guardar una referencia al UIPopoverController y comprobar si


ya est visible antes de permitir un nuevo segue.
Primero necesitamos una propiedad para guardar la referencia al UIPopoverController:
@interface ViewController ()
@property (strong, nonatomic) UIPopoverController
*toolbarPopoverController;
@end

Luego debemos guardar la referencia al UIPopoverController en prepareForSegue:


cada vez que se abra:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(@"prepareForSegue %@", segue.identifier);
if([segue.identifier isEqualToString:@"ToolBarTransicionPopover"]) {
if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) {
// Guardamos la referencia al toolbarPopoverController
// para poder cerrarlo ms tarde.
UIStoryboardPopoverSegue *popoverSegue =
(UIStoryboardPopoverSegue *)segue;
self.toolbarPopoverController =
popoverSegue.popoverController;
}
// Resto de implementacin del segue
}
}

Finalmente, si el Popover ya est abierto debemos cerrarlo, anular nuestra referencia y devolver NO para impedir el segue en shouldPerformSegueWithIdentifier::
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier
sender:(id)sender
{
// Si abrimos un popover desde un toolbar button no se cerrar
// automticamente. Hay que hacerlo manualmente.
if([identifier isEqualToString:@"ToolBarTransicionPopover"]) {
if([self.toolbarPopoverController isPopoverVisible]) {
[self.toolbarPopoverController dismissPopoverAnimated:YES];
self.toolbarPopoverController = nil;
return NO;
280

Curso iOS 8

Captulo UI.7 UIPopoverController

}
}
return YES;
}

281

Esta pgina se ha dejado vaca a propsito

Cocoapods

Esta pgina se ha dejado vaca a propsito

284

Captulo POD.1

Cocoapods
POD.1.1 Documentacin
http://cocoapods.org
https://github.com/CocoaPods/CocoaPods

POD.1.2 Instalacin

Primero instalar las Command Line Tools de Xcode para disponer de un compilador de C
en el sistema.
sudo gem update --system
sudo gem install cocoapods
pod setup

POD.1.3 Ejemplo de uso

Utilizar Cocoapods para instalar ZBarSDK:


Crear nuevo proyecto y cerrarlo.
Crear archivo Podfile.
Podfile
platform :ios, "5.0"
pod "ZBarSDK"

Instalar o actualizar dependencias


285

Captulo POD.1 Cocoapods

pod install
pod update

A partir de ahora siempre usar el xcworkspace para abrir el proyecto


Abrir nuevo Proyecto.xcworkspace
open Proyecto.xcworkspace

POD.1.4 Referencias
http://nsscreencast.com/episodes/5-cocoapods
http://afnetworking.com
https://github.com/AFNetworking/Xcode-Project-Templates
Heroku Mobile (http://mobile.heroku.com/)

286

Curso iOS 8

Captulo POD.2

ZBarSDK
POD.2.1 Documentacin
http://zbar.sourceforge.net/iphone/sdkdoc/index.html
http://cocoapods.org/?q=zbarsdk

POD.2.2 Instalacin

Utilizar Cocoapods para instalar ZBarSDK:


Crear nuevo proyecto y cerrarlo.
Crear archivo Podfile.
Podfile
platform :ios, "5.0"
pod "ZBarSDK"

Instalar o actualizar dependencias


pod install
pod update

Abrir nuevo Proyecto.xcworkspace


open Proyecto.xcworkspace

287

Captulo POD.2 ZBarSDK

Curso iOS 8

POD.2.3 Cdigo de ejemplo bsico

Son necesarios un UIImageView y UITextView en el Storyboard y un UIButton para lanzar la accin de escanear.
ViewController.h
#import <UIKit/UIKit.h>
#import "ZBarSDK.h"
@interface ViewController : UIViewController <ZBarReaderDelegate>
@end

ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *resultImage;
@property (weak, nonatomic) IBOutlet UITextView *resultText;
@end
@implementation ViewController
- (IBAction)pressScan:(UIButton *)sender {
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here
// EXAMPLE: disable rarely used I2/5 to improve performance
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
// present and release the controller
[self presentModalViewController:reader animated:YES];
}
- (void)imagePickerController:(UIImagePickerController*)reader
didFinishPickingMediaWithInfo:(NSDictionary*) info
288

Curso iOS 8

Captulo POD.2 ZBarSDK

{
// ADD: get the decode results
id<NSFastEnumeration> results = [info objectForKey:
ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;
// EXAMPLE: do something useful with the barcode data
self.resultText.text = symbol.data;
// EXAMPLE: do something useful with the barcode image
self.resultImage.image = [info objectForKey:
UIImagePickerControllerOriginalImage];
// ADD: dismiss the controller (NB dismiss from the *reader*!)
[reader dismissModalViewControllerAnimated:YES];
}

289

Esta pgina se ha dejado vaca a propsito

Stanford CS193P

Esta pgina se ha dejado vaca a propsito

292

Captulo S

Stanford CS193p
S.1 Introduccin

Curso de Stanford sobre iOS impartido por Paul Hegarty que se da una o dos veces al ao.
Est disponible libremente en iTunes (gratis y con licencia CC).
Sin duda la mejor referencia disponible para aprender y mantenerse actualizado, por la
calidad de los materiales y videos.

Figura S.1 Curso en web iTunes


293

Captulo S Stanford CS193p

S.2 Presentaciones

S.3 Videos

294

Curso iOS 8

Curso iOS 8

Captulo S Stanford CS193p

S.4 Referencias
Web Stanford (http://online.stanford.edu/course/developing-ios7-apps-fall-2013)
Curso iTunes (https://itunes.apple.com/us/course/developing-ios-7-apps-for/
id733644550)

295

Esta pgina se ha dejado vaca a propsito

296

Captulo S.1

Stanford: Lecture 1
S.1.1 Componentes de la Plataforma

Herramientas: Xcode 5 e Instruments


Lenguaje: Objective C
Frameworks: Foundation, UIKit, Core Data...
Estrategia de diseo OO: MVC
297

Captulo S.1 Stanford: Lecture 1

Curso iOS 8

S.1.2 Vocabulario bsico de Orientacin a Objetos


Class / Clase (descripcin/plantilla para un objeto)
Instance / Instancia (objeto construdo de una clase)
Message / Mensaje (enviado a un objeto para hacerle actuar)
Method / Mtodo (funcin invocada por un mensaje)
Instance Variable / Variable de instancia (almacenamiento especfico de un objeto)
Superclass-Subclass / Superclase-Subclase (Herencia)

S.1.3 MVC

298

Curso iOS 8

Captulo S.1 Stanford: Lecture 1

S.1.4 Objective C

S.1.5 Referencias
PDF: Lecture 1 (/doc/stanford/Lecture-1.pdf)

299

Esta pgina se ha dejado vaca a propsito

300

Captulo S.2

Stanford: Lecture 2
S.2.1 App: Cartas

S.2.2 Objective C
S.2.2.1 Clases
Card
301

Captulo S.2 Stanford: Lecture 2

Deck
PlayingCard
PlayingCardDeck

S.2.3 Paseo por Xcode

S.2.4 Referencias
PDF: Lecture 2 (/doc/stanford/Lecture-2.pdf)

302

Curso iOS 8

Captulo S.3

Stanford: Lecture 3
S.3.1 App: Cartas (continuacin)

S.3.2 Repaso MVC


S.3.2.1 El Modelo es independiente de las Vistas
Tiene Cards y Decks, y no UIButtons o UILabels
303

Captulo S.3 Stanford: Lecture 3

Curso iOS 8

S.3.2.2 Las Vistas son elementos de UI completamente genricos


UIButton
UILabel

S.3.2.3 El Controlador interpreta el Modelo para las Vistas


(y viceversa)
Ejemplo: convertir isChosen a estado seleccionado de un botn
Ejemplo: convertir isMatched a estado activo de un botn
Ejemplo: recibir toque de botn y pasarlo a chooseCardAtIndex: en el Modelo
(Target/Action y Outlets)

S.3.3 Repaso Xcode


S.3.3.1 Crear un proyecto y maniobrar por Xcode
Ocultar/Mostrar Navegadores, Utilidades, Editores enparejados...
Ejecutar en el Simulador.

S.3.3.2 Editar
No solo cdigo, tambin storyboard, inspectores de atributos...
Ctrl-drag para conectar (actions y outlets).
Click derecho sobre botones para ver conexiones (y desconectar)
Encontrar errores y avisos (y corregirlos)
Depurador

S.3.3.3 Aadir clases al proyecto


Aadir Card, Deck, etc al Modelo

S.3.3.4 Use the documentation


Varias forma de acceder, pero recordar ALT-click sobre una palabra clave
Importante para programar bien el saber usar la documentacin (buscar, etc)

304

Curso iOS 8

Captulo S.3 Stanford: Lecture 3

S.3.4 Repaso Objective C


S.3.4.1 Clases
Cabecera .h (pblica) frente a Implementacin .m (privada)
@interface MyClass : MySuperclass ... @end (solo en cabecera)
@interface MyClass() ... @end (solo en implementacin)
@implementation ... @end (solo en implementacin)
#import

S.3.4.2 Propiedades
@property (nonatomic) <type> <property name> (siempre nonatomic en
este curso)
Son solo mtodos setter y getter. Por defecto generados automticamente por el
compilador.
Mejor que variables de instancia solas (lazy instantiation, chequear consistencia,
actualizar UI, etc)
@property (strong or weak) <type which is a pointer to an object>
<property name>

@property (getter=<getter name>) ...


@property (readonly) ... y @property (readwrite) ...
Invocar setter y getter usando dot notation, p.ej. self.cards = ... o if (rank >
self.rank) ...

@synthesize <prop name> = _<prop name> (solo si t implementas ambos


setter y getter)

S.3.4.3 Tipos y memoria


Tipos: MyClass *, BOOL (YES o NO), int, NSUInteger, etc. (id pendiente explicar)
Todos los objetos viven en el heap (montn) (solo tenemos punteros hacia ellos)
El almacenamineto de objectos en el heap se gestiona automticamente (mediante
declaraciones strong y weak)
Lazy instantiation (usar el getter de una @property para hacer alloc init del objeto
"bajo demanda", no lo hacemos siempre)
305

Captulo S.3 Stanford: Lecture 3

Curso iOS 8

Si un puntero tiene el valor nil (p.ej. 0), significa que el puntero no apunta a nada

S.3.4.4 Mtodos
Declarar y definir mtodos de instancia - (int)match:(NSArray *)otherCards
Declarar y definir mtodos de clase + (NSArray *)validSuits
Invocar mtodos de instancia [myArray addObject:anObject]
Invocar mtodos de clase unsigned int rank = [PlayingCard maxRank]
El nombre del mtodo y sus parametros se intercalan [deck addCard:aCard
atTop:YES]

S.3.4.5 NSString
Inmutable y generalmente creado manipulando otros strings o mediante @"" o
mtodos de clase
Ejemplo: NSString *myString = @"hello"
Ejepmlo: NSString *myString = [otherString
stringByAppendingString:yetAnotherString]

Ejemplo: NSString *myString = [NSString stringWithFormat:@"%d%@",


myInt, myObj]

Hay una subclase NSMutableString pero se usa menos.


Normalmente creamos nuevos strings pidiendo a los anteriores que creen una
nueva versin modificada.

S.3.4.6 NSArray
Inmutable y generalmente creados manipulando otros arrays o mediante "@[]"
@[@"a",@"b"] es igual que [[NSArray alloc] initWithObjects: @"a",
@"b", nil]

Acceder mediante [] (como arrays de C normales) myArray[index]


myArray[index] es igual que [myArray objectAtIndex:index]
El mtodo count (que devuelve un NSUInteger) indica cuantos items tiene el
array. (Accidentalmente se uso used dot notation para llamar a este mtodo en la
Lecture 2)
Cuidado con acceder a un array con un ndice fuera de lmites (crash).
306

Curso iOS 8

Captulo S.3 Stanford: Lecture 3

Solo last y firstObject son inmunes.


Pueden contener cualquier mezcla de objetos de cualquier clase. No hay sintaxis
para indicar qu contiene (hay que saberlo o mira cada objeto)
Usar la subclase NSMutableArray si se necesita mutabilidad:
(void)addObject:(id)anObject;
(void)insertObject:(id)anObject atIndex:(int)index;
(void)removeObjectAtIndex:(int)index;
Normalmente se crean con [[NSMutableArray alloc] init]

S.3.4.7 Crear objetos en el heap (montn)


La asignacin de espacio (NSObject alloc) y la inicializacin (init) siempre a la
vez
Ejemplo: [[NSMutableArray alloc] init]
Ejemplo: [[CardMatchingGame alloc] initWithCardCount:c usingDeck:d]

S.3.4.8 Inicializadores de nuestras clases


Dos tipos de init: designado (uno por clase) y de conveniencia (cero o ms por clase)
Solo se denotan mediante comentarios (no hay nada obligatorio en la sintaxis del
lenguaje)
Debes llamar al init designado de la clase super (desde tu init designado)
O a tu init designado desde los init de conveniencia

S.3.4.9 Otros
Enumeracin rpida: for (MyClass *myObject in arrayOfMyObjects) { }
#define
NSLog(@"show this object %@ in the console", anObject);

S.3.5 Referencias
PDF: Lecture 3 (/doc/stanford/Lecture-3.pdf)

307

Esta pgina se ha dejado vaca a propsito

308

Captulo S.4

Stanford: Lecture 4

S.4.1 Resumen
S.4.1.1 Objective C
Crear objetos
nil
El superimportante tipo id (y el concepto de dynamic binding)
309

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

Introspeccin
App: Cartas (mejorar con introspeccin)

S.4.1.2 Foundation
NSObject, NSArray, NSNumber, NSData, NSDictionary, etc
Property Lists y NSUserDefaults
NSRange
UIFont y UIColor (pertenecen a UIKit)
NSAttributedString (y su extensiones en UIKit)
Attributed strings en UITextView y UILabel

S.4.2 Crear objetos

Casi siempre crearemos objetos con alloc init:


NSMutableArray *cards = [[NSMutableArray alloc] init];
CardMatchingGame *game = [[CardMatchingGame alloc] initWithCardCount:12
usingDeck:d];

O con mtodos de clase:


// NSString
(id)stringWithFormat:(NSString *)format, ...
NSString *moltuae = [NSString stringWithFormat:@%d, 42]; // NSString
+ (id)buttonWithType:(UIButtonType)buttonType; // UIButton
+ (id)arrayWithCapacity:(int)count; // NSMutableArray
+ (id)arrayWithObject:(id)anObject; // NSArray

A veces existen mtodos de clase e inits que hacen lo mismo:


[NSString stringWithFormat:...]
[[NSString alloc] initWithFormat:...]

Tambin se puede pedir a otros objetos que creen objetos por ti:
- (NSString *)stringByAppendingString:(NSString *)otherString; //
NSString
- (NSString *)componentsJoinedByString:(NSString *)separator; // NSArray
- (id)mutableCopy; // NSString y NSArray

Pero no todos los objetos que nos dan son recin creados:
310

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

- (id)lastObject; // de NSArray
- (id)objectAtIndex:(int)index; // de NSArray

A no ser que el mtodo tenga la palabra copy, si el objeto ya existe, nos dan un puntero al
mismo. Si el objeto no existe, entonces lo estaremos creando.

S.4.3 nil

El valor que indica un puntero vaco es nil.


Es posible enviar mensajes a nil. Si el mtodo devuelve un valor ser cero.
int i = [obj methodWhichReturnsAnInt]; // ser cero si el objeto es nil

Es perfectamente vlido usar este mecanismo (sin pasarse).


Pero tener cuidado si el mtodo devuelve una struct de C, que no son objetos, porque el valor de retorno no est definido (basura)
CGPoint p = [obj getLocation]; // p tendr un valor indefinido si el
objeto es nil

S.4.4 Ligadura dinmica o dynamic binding

A seleccionar el cdigo que debe ejecutarse cuando un mensaje se enva a un objeto en


tiempo de ejecucin se le llama ligadura dinmica o dynamic binding
binding.
Para ello Objective C tiene un tipo muy importante llamado id, que indica un puntero a
un objeto de tipo desconocido:
id myObject;

En realidad todos los punteros son tratados como id por el runtime.


Pero en tiempo de compilacin, si especificas NSString * en lugar de id, el compilador
nos ayuda:
Puede encontrar bugs y sugerir mtodos que son apropiados en el momento de
escribir cdigo
Si escribes cdigo usando id, el compilador no nos puede ayudar porque no sabe el
tipo real (puede ser cualquiera)
Es seguro?
Tratar a todos los punteros como "punteros a objeto de tipo desconocido" es peligroso.
311

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

Porque nada te impide enviar un mensaje a un objeto que no lo reconoce (crash).


Programar en Objective C es ms sencillo si al programar usamos los tipos estticos (p.ej.
NSString *) en lugar de id para todo. As el compilador nos ayuda todo lo posible.
Ejemplo peligroso
NSString *s = @"x";
id obj = s;
NSArray *a = obj;

El compilador no se quejar de asignaciones entre un id y una variable tipada estticamente.


Algunas veces hemos hecho esto:
- (int)match:(NSArray *)otherCards
{
// ...
PlayingCard *otherCard = [otherCards firstObject]; // firstObject
devuelve id
}

id ya es un puntero. Nunca usar id * que sera un puntero a un puntero a un objeto.

Cuando utilizamos id:


Cuando necesitamos mezclar objetos de difetentes clases en una coleccin (p.ej. en
NSArray)
Cuando queremos soportar la comunicacin ciega y estructurada de MVC
(delegacin)
Para hacer esta comunicacin ms segura usaremos dos mecanismos: Introspeccin y Protocolos
Introspeccin: Preguntar al runtime de qu clase es un objeto o si se le puede
enviar un mensaje concreto.
Protocolos: Una sintaxis que est entre id y tipado esttico
No especificamos de qu clase es un objeto pero especificamos qu mtodos implementa.
Por ejemplo:
id <UIScrollViewDelegate> scrollViewDelegate;
312

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

S.4.5 Instrospeccin

Todos los objetos que heredan de NSObject implementan estos tres mtodos:
isKindOfClass: devuelve si un objeto es este tipo de class (herencia incluida)
isMemberOfClass: devuelve si un objeto es exactamente este tipo de class (sin
herencia)
respondsToSelector: devuelve si un objeto responde al un mtodo concreto
if ([obj isKindOfClass:[NSString class]]) {
NSString *s = [(NSString *)obj stringByAppendingString:@"xyz"];
}

Mtodo respondsToSelector: sirve para comprobar si un objeto implementa un mtodo:


Recibe como parmetro un selector SEL.
La directiva @selector() convierte el nombre de un mtodo en un selector.
Ejemplo:
if ([obj respondsToSelector:@selector(shoot)]) {
[obj shoot];
} else if ([obj respondsToSelector:@selector(shootAt:)]) {
[obj shootAt:target];
}

SEL es el tipo de Objective-C para indicar un selector:


SEL shootSelector = @selector(shoot);
SEL shootAtSelector = @selector(shootAt:);
SEL moveToSelector = @selector(moveTo:withPenColor:);

Si tienes un SEL, puede pedirle a un objeto que lo ejecute con performSelector:


Usando los mtodos performSelector: o performSelector:withObject: de
NSObject
[obj performSelector:shootSelector];
[obj performSelector:shootAtSelector withObject:coordinate];

Usando el mtodo makeObjectsPerformSelector: de NSArray:

313

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

[array makeObjectsPerformSelector:shootSelector];
[array makeObjectsPerformSelector:shootAtSelector withObject:target]; //
target is an id

En un UIButton:
- (void)addTarget:(id)anObject action:(SEL)action ...;
[button addTarget:self action:@selector(digitPressed:) ...];

S.4.6 Foundation Framework


S.4.6.1 NSObject
Clase base de todos los objetos.

S.4.6.2 Introspeccin
NSObject es importante porque implementa los mtodos bsicos para la introspeccin.

Los recordamos:

isKindOfClass: devuelve si un objeto es este tipo de class (herencia incluida)


isMemberOfClass: devuelve si un objeto es exactamente este tipo de class (sin
herencia)
respondsToSelector: devuelve si un objeto responde al un mtodo concreto
S.4.6.2.1 description
Otro mtodo bsico de NSObject es:
- (NSString *)description

La implementacin base solo imprime la direccin del puntero al objeto.


As que es un mtodo til para implementar en nuestros objetos para utilizarlo con el especificador %@ en NSLog()). Ejemplo:
NSLog(@"array contents are %@", myArray);

El especificador %@ se reemplaza con el resultado de invocar [myArray description].


S.4.6.2.2 Copiar objetos
La diferencia entre entre mutable e inmutable es un concepto importante que hay que entender:
No es raro hacer una copia mutable de un array o diccionario y modificarlo
314

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

O al revs, hacer una copia inmutable de un array o diccionario para congelarlo


Las copias son muy rpidas y eficientes (no hay que dudar si hacerlo o no en caso de necesidad)
Hay dos mtodos bsicos para copiar objetos:
- (id)copy; // copia inmutable
- (id)mutableCopy; // copia mutable

Pero no todos los objetos implementan este mecanismo (saltar una excepcin si se intenta copiarlos y no lo hacen).

S.4.6.3 NSArray
Coleccin ordenada de objetos.
Inmutable. Una vez creado no puedes aadir o eliminar objetos.
Todos los objetos se retienen mediante un puntero strong.
Se crean mediante manipulando otros arrays o mediante @[].
Mtodos que ya conocemos:
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index; // devuelve un id y hace crash si
el ndice est fuera de lmites
- (id)lastObject; // devulve nil (sin crash) si no hay objetos en el
array
- (id)firstObject; // devulve nil (sin crash) si no hay objetos en el
array

Ejemplos de otros mtodos tiles:


- (NSArray *)sortedArrayUsingSelector:(SEL)aSelector;
- (void)makeObjectsPerformSelector:(SEL)aSelector
withObject:(id)selectorArgument;
- (NSString *)componentsJoinedByString:(NSString *)separator;

S.4.6.4 NSMutableArray
Versin mutable de NSArray.
Se crean mediante alloc init o bien:

315

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

+ (id)arrayWithCapacity:(NSUInteger)numItems; // numItems is a
performance hint only
+ (id)array;

[NSMutableArray
init]

array] es exactamente igual que [[NSMutableArray

alloc]

NSMutableArray hereda todos los mtodos de NSArray. No solo count, objectAtIndex:, etc.

Y sabemos que implementa tambin estos mtodos:


- (void)addObject:(id)object; // al final del array
- (void)insertObject:(id)object atIndex:(NSUInteger)index;
- (void)removeObjectAtIndex:(NSUInteger)index;

S.4.6.5 Enumeracin rpida


Se denomina as a para pasar por todos los miembros de una coleccin de forma eficiente.
Para hacerlo el lenguaje soporta la utilizacin de for(... in ...).
Ejemplo con NSArray de objetos NSString:
NSArray *myArray = @[...];
for (NSString *string in myArray) { // el compilador no sabe qu
contiene el arrat
double value = [string doubleValue]; // crash si el objeto no era un
`NSString`
}

Ejemplo con NSArray de id e instrospeccin:


NSArray *myArray = @[];
for (id obj in myArray) {
// comprobar si obj es un `NSString`
if ([obj isKindOfClass:[NSString class]]) {
// hacer algo con obj
}
}

S.4.6.6 NSNumber
Es un objeto para empaquetar tipos primitivos como: int, float, double, BOOL, enums,
etc.
316

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

NSNumber *n = [NSNumber numberWithInt:36];


float f = [n floatValue]; // devuelve 36.0 como un float (convierte
tipos)

Util cuando quieres poner estos tipos primitivos en una coleccin (p.ej. NSArray o NSDictionary)
Hay una nueva sintaxis para crear un NSNumber desde iOS 6: @()
NSNumber
NSNumber
NSNumber
devuelve

*three = @3;
*underline = @(NSUnderlineStyleSingle); // enum
*match = @([card match:@[otherCard]]); // expresin que
un tipo primitivo

S.4.6.7 NSValue
Es un objeto genrico para empaquetar otros datos que no son objetos (p.ej. structs de C)
NSValue *edgeInsetsObject = [NSValue
valueWithUIEdgeInsets:UIEdgeInsetsMake(1,1,1,1)]

Probablemente no es necesario en este curso.

S.4.6.8 NSData
Es un saco de bits
Se usa para guardar/restaurar/transmitir datos puros (crudos) por el SDK de iOS.

S.4.6.9 NSDate
Se usa para encapsular fechas. Tambin hay: NSCalendar, NSDateFormatter, NSDateComponents.

S.4.6.10 NSSet y NSMutableSet


Son como un array pero no mantienen el orden (no tienen objectAtIndex:).
member: es el mtodo ms importante (devuelve un objeto si hay uno en el set que cumple
isEqual: con ste).

Puede hacerse la union e interseccin con otros sets.

S.4.6.11 NSOrderedSet y NSMutableOrderedSet


Una mezcla de NSArray y NSSet

317

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

Los objetos en un set ordenado tienen que ser diferentes. No puedes poner el mismo objeto
en ellos como en un array.

S.4.6.12 NSDictionary
Coleccin inmutable de objetos que se introducen y extraen mediante su clave.
Todas las claves y valores son mantenidas de manera strong por un NSDictionary.
Se pueden crear con esta sintaxis:
@{ key1 : value1, key2 : value2, key3 : value3 }
NSDictionary *colors = @{ @green : [UIColor greenColor],
@blue : [UIColor blueColor],
@red : [UIColor redColor] };

Se pueden extraet mediante la sintaxis simple tipo array []


NSString *colorString = ...;
UIColor *colorObject = colors[colorString]; // funciona igual que
objectForKey:
- (NSUInteger)count;
- (id)objectForKey:(id)key; // la clave debe ser copiable e implementar
`isEqual:` (p.ej. NSStrings)

S.4.6.13 NSMutableDictionary
Versin mutable de NSDictionary
Se crean mediante alloc/init o uno de los mtodos de clase
+ (id)dictionary... class methods.

Adems de los mtodos de NSDictionary, estn estos mtodos importantes:


-

(void)setObject:(id)anObject forKey:(id)key;
(void)removeObjectForKey:(id)key;
(void)removeAllObjects;
(void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;

S.4.6.14 Enumeracin
Pasar por las claves o valores de un diccionario. Ejemplo:
NSDictionary *myDictionary = ...;
for (id key in myDictionary) {
// do something with key here
318

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

id value = [myDictionary objectForKey:key];


// do something with value here }

S.4.6.15 Property List


El trmino Property List se utiliza para denotar una coleccin que contiene solo objetos y
colecciones bsicos. Es solo una frase.
Sera el equivalente a un JSON de JavaScript.
Estos tipos y colecciones bsicos son exactamente:
NSArray, NSDictionary, NSNumber, NSString, NSDate, NSData o sus versiones
mutables.
Por ejemplo:
Un NSArray de NSString es una Property List
List.
Un NSArray ser una Property List si todos los objetos que hay dentro pertenece a
esos tipos bsicos.
Un NSDictionary es una Property List si y solo si todas las claves y valores tambin pertenece a esos tipos bsicos.
Ejemplos:
Un NSArray de NSDictionarys cuyas claves sean NSStrings y valores sean
NSNumbers es una Property List
List.
Y por qu se define este trmino?
Porque el SDK tiene muchos mtodos que requieren para operar Property Lists
Lists.
Por ejemplo:
- (void)writeToFile:(NSString *)path atomically:(BOOL)atom;

Este mtodo solo se le puede mandar a un NSArray o NSDictionary que sean Property
Lists
Lists.

S.4.6.16 NSUserDefaults
Espacio de almacenamiento ligero para Property Lists
Es bsicamente un diccionario que persiste entre ejecuciones de nuestra aplicacin.
319

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

No es una base de datos completa, solo se guardan cosas pequeas ah.


Se escriben y leen mediante una instacia compartida que se obtiene mediante: [NSUserDefaults standardUserDefaults].
[[NSUserDefaults standardUserDefaults] setArray:rvArray
forKey:@"RecentlyViewed"];

Mtodos:
- (void)setDouble:(double)aDouble forKey:(NSString *)key;
- (NSInteger)integerForKey:(NSString *)key;
- (void)setObject:(id)obj forKey:(NSString *)key; // obj debe ser
Property List
- (NSArray *)arrayForKey:(NSString *)key; // devuevle nil si el valor
para esa clave no es un NSArray

Recordar siempre sincronizar (guardar) los cambios tras efectuarlos:


[[NSUserDefaults standardUserDefaults] synchronize];

S.4.6.17 NSRange
Es una struct de C (no una clase).
Se usa para especificar subrangos dentro de strings y de arrays.
typedef struct {
NSUInteger location;
NSUInteger length;
} NSRange;

Puede contener el valor NSNotFound.


NSString *greeting = @"hello world";
NSString *hi = @"hi";
NSRange r = [greeting rangeOfString:hi]; // buscar el rango de "hi"
dentro de greeting
if (r.location == NSNotFound) { /* no encontrado */ }

NSRangePointer es directamente NSRange *. Para usarlo como parmetro de salida.

Tambin existen funciones de C tiles como:


NSEqualRanges() comparar
320

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

NSMakeRange() creacin

S.4.6.18 UIColor
Objeto que representa un color.
Los inicializadores para crear un color estn basadoe en RGB, HSB e incluso una trama
UImage.
Los colores pueden tener transparencia (alpha):
UIColor *color = [otherColor colorWithAlphaComponent:0.3]

Hay una serie de colores con nombre: blanco, rojo, etc y otros como: color de texto, color de
texto claro.
[UIColor
[UIColor
[UIColor
[UIColor
[UIColor
[UIColor
[UIColor

whiteColor];
blackColor];
redColor];
greenColor];
blueColor];
orangeColor];
lightTextColor];

S.4.6.19 UIFont
Representa una fuente de letra.
Con el nuevo estilo de iOS 7 las tipografas son an ms importantes.
Para el contenido del usuario lo mejor es solicitar al sistema las fuentes preferidas del
usuario para los diferentes estilos disponibles:
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];

Otros estilos son: UIFontTextStyleHeadline, UIFontTextStyleCaption1, UIFontTextStyleFootnote, ... (ver documentacin de UIFontDescriptor)
Tambin existen las fuentes de sistema. Se usan preferentemente para los textos propios
de la aplicacin (no los del contenido del usuario).
+ (UIFont *)systemFontOfSize:(CGFloat)pointSize;
+ (UIFont *)boldSystemFontOfSize:(CGFloat)pointSize;

Nunca uses fuentes de sistema para el contenido del usuario (porque el tamao estar predefinido).
321

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

Usa preferredFontForTextStyle: para que el usuario pueda ajustarlo.

S.4.6.20 UIFontDescriptor
Las fuente son diseadas por artistas. Y no siempre encajan en las categoras que queremos. Ejemplo:
Una fuente que solo tiene maysculas.
Una fuente en la que no se ha diseado con bold o itlica.
UIFontDescriptor intenta categorizarlas en cualquier caso.

Lo hace mediante atributos como: familia, fuente, tamao y otros.


Puedes pedir fuentes que tengan esos atributos e intentar obtener el mejor candidato.
Hay que entender que quiz si pedimos a una fuente un tipo bold, puede que no exista porque el diseador no lo puso ah en primer lugar.
Puedes obtener el descriptor de un UIFont as:
- (UIFontDescriptor *)fontDescriptor;

Podramos haber obtenido ese UIFont usando preferredFontForTextStyle:.


Entonces podramos querer modificarlo as:
- (UIFontDescriptor *)fontDescriptorByAddingAttributes:(NSDictionary
*)attributes;

Los atributos y sus valores estn en la documentacin de UIFontDescriptor


Se pudede crear un UIFontDescriptor directamente desde unos atributos (es raro) usando:
+ (UIFontDescriptor *)fontDescriptorWithFontAttributes:(NSDictionary
*)attributes;

S.4.6.20.1 Symbolic Traits


Italic, Bold, Condensed, etc., son importantes como para tener su propia API en UIFontDescriptor:
- (UIFontDescriptorSymbolicTraits)symbolicTraits;
- (UIFontDescriptor
*)fontDescriptorWithSymbolicTraits:(UIFontDescriptorSymbolicTraits)traits;
322

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

Ms ejemplos de traits:
UIFontDescriptorTraitItalic
UIFontDescriptorTraitBold
UIFontDescriptorTraitCondensed
Once you have a UIFontDescriptor that describes the font you want, use this UIFont method:
(UIFont *)fontWithDescriptor:(UIFontDescriptor *)descriptor size:(CGFloat)size;
(specify size of 0 if you want to use whatever size is in the descriptor)
You will get a best match for your descriptor given available fonts and their faces.
Ejemplo para intentar obtener una bold body font:
UIFont *bodyFont = [UIFont
preferredFontForTextStyle:UIFontTextStyleBody];
UIFontDescriptor *existingDescriptor = [bodyFont fontDescriptor];
UIFontDescriptorSymbolicTraits traits =
existingDescriptor.symbolicTraits;
traits |= UIFontDescriptorTraitBold;
UIFontDescriptor *newDescriptor = [existingDescriptor
fontDescriptorWithSymbolicTraits:traits];
UIFont *boldBodyFont = [UIFont fontWithFontDescriptor:newDescriptor
size:0];

Tratar de objeter el mejor candidato, que puede que no sea bold...

S.4.7 Attributed Strings


Cmo aparecen los textos en pantalla.

La fuente es importante, pero hay otros atributos: color, si est outlined, ancho del trazo,
subrayado, etc.

S.4.7.1 NSAttributedString
Se puede pensar en ellos como un NSString donde cada letra tiene un NSDictionary de
atributos. Aunque realmente no es una subclase de NSString.
Obtener Atributos
Se puede pedir a un NSAttributedString todos los atributos en un lugar del string.
323

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

- (NSDictionary *)attributesAtIndex:(NSUInteger)index
effectiveRange:(NSRangePointer)range;

El rango es devuelto e indica cuantos caracteres comparten atributos idnticos


Tambin hay mtodos para preguntar solo por cierto atributo que nos interese.
NSRangePointer is essentially an NSRange *. Es ok pasar NULL si no nos importa.
NSAttributedString no es un NSString

No hereda de NSString, no puedes llamar a sus mtodos.


Pero si necesitas hacerlo existe el mtodo de conversin:
- (NSString *)string;

Por ejemplo, para encontrar un substring en un NSAttributedString, puede hacer esto:


NSAttributedString *attributedString = ...;
NSString *substring = ...;
NSRange r = [[attributedString string] rangeOfString:substring];

Este mtodo se garantiza que ser rpido, pero el valor es volatil. Si quieres guardar el texto es mejor hacer una copia.

S.4.7.2 NSMutableAttributedString
Al contrario que con NSString, casi siempre usamos esta versin mutable.
Aadir o establecer atributos
Se puede aadir atributos a un rango...
- (void)addAttributes:(NSDictionary *)attributes range:(NSRange)range;

... lo cual cambiar los valores de esos atributos pero no tocar otros.
Se puede establecer los atributos as:
(void)setAttributes:(NSDictionary *)attributes range:(NSRange)range;
... lo cual quitar todos los dems atributos en ese rango.
Tambin se puede eliminar atributos especficos de un rango...
324

Curso iOS 8

Captulo S.4 Stanford: Lecture 4

(void)removeAttribute:(NSString *)attributeName range:(NSRange)range;


Modificar los contenidos del string (cambiar el texto)
Se pueden usar mtodos para aadir, insertar, eliminar o reemplazar caracteres.
O usar el mtodo de NSMutableAttributedString:
- (NSMutableString *)mutableString

Y modificar el NSMutableString devuelto (increiblemente los atributos sern preservados).


UIColor *yellow = [UIColor yellowColor];
UIColor *transparentYellow = [yellow colorWithAlphaComponent:0.3];
@{
NSFontAttributeName: [UIFont
preferredFontWithTextStyle:UIFontTextStyleHeadline]
NSForegroundColorAttributeName: [UIColor greenColor],
NSStrokeWidthAttributeName: @-5,
NSStrokeColorAttributeName: [UIColor redColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone),
NSBackgroundColorAttributeName: transparentYellow
}

Cmo se usan los attributed strings?


UIButtons - (void)setAttributedTitle:(NSAttributedString *)title forState:...; UILabels
@property (nonatomic, strong) NSAttributedString *attributedText; UITextViews
@property (nonatomic, readonly) NSTextStorage *textStorage;
Dibujar strings directamente
Los NSAttributedString saben como dibujarse a s mismos en pantalla:
- (void)drawInRect:(CGRect)aRect;

S.4.7.3 UILabel
Hasta ahora sabamos establecer su contenido con la propiedad NSString *text
Pero tambin tiene una propiedad para establecer sus texto mediante un NSAttributedString:
@property (nonatomic, strong) NSAttributedString *attributedText;
325

Captulo S.4 Stanford: Lecture 4

Curso iOS 8

Es inmutable (el valor, pero se pude cambiar completo)


Para modificarlo hay que hacer un mutableCopy, modificarlo y establecerlo de nuevo.
NSMutableAttributedString *labelText = [myLabel.attributedText
mutableCopy]; [labelText setAttributes:...];
myLabel.attributedText = labelText;

Tambin hay propiedades para establecer el font, textColor, etc. a la vez para todos los caracteres.

S.4.8 Referencias
PDF: Lecture 4 (/doc/stanford/Lecture-4.pdf)

326

Captulo S.5

Stanford: Lecture 5

S.5.1 UITextView

Vista de un mutable attributed string con scroll, editable y seleccionable.

S.5.2 View Controller Lifecycle

Eventos que ocurren cuando un ViewController es creado, enganchado al View, aparece/


desaparece, etc.

327

Captulo S.5 Stanford: Lecture 5

Curso iOS 8

S.5.3 NSNotification

El mecanismo de comunicacin de MVC tipo "estacin de radio".

S.5.4 Demo
UITextView
NSAttributedString, NSMutableAttributedString, NSTextStorage, UIFont,
UIColor

NSNotification
View Controller Lifecycle

S.5.5 Referencias
PDF: Lecture 5 (/doc/stanford/Lecture-5.pdf)

328

Captulo S.6

Stanford: Lecture 6
S.6.1 Multiple MVCs

329

Captulo S.6 Stanford: Lecture 6

S.6.2 UINavigarionController

330

Curso iOS 8

Curso iOS 8

Captulo S.6 Stanford: Lecture 6

S.6.3 UITabBarController

S.6.4 Referencias
PDF: Lecture 6 (/doc/stanford/Lecture-6.pdf)

331

Esta pgina se ha dejado vaca a propsito

332

Captulo S.7

Stanford: Lecture 7

333

Captulo S.7 Stanford: Lecture 7

S.7.1 Vistas y UIVIew

S.7.2 Gestos y UIGestureRecognizer

334

Curso iOS 8

Curso iOS 8

Captulo S.7 Stanford: Lecture 7

S.7.3 Referencias
PDF: Lecture 7 (/doc/stanford/Lecture-7.pdf)

335

Esta pgina se ha dejado vaca a propsito

336

Captulo S.8

Stanford: Lecture 8

337

Captulo S.8 Stanford: Lecture 8

S.8.1 Protocolos

S.8.2 Blocks

338

Curso iOS 8

Curso iOS 8

Captulo S.8 Stanford: Lecture 8

S.8.3 Animaciones

S.8.4 Referencias
PDF: Lecture 8 (/doc/stanford/Lecture-8.pdf)

339

Esta pgina se ha dejado vaca a propsito

340

Captulo S.9

Stanford: Lecture 9

341

Captulo S.9 Stanford: Lecture 9

S.9.1 Autolayout

S.9.2 Referencias
PDF: Lecture 9 (/doc/stanford/Lecture-9.pdf)
342

Curso iOS 8

Captulo S.10

Stanford: Lecture 10

S.10.1 Multithreading

Enviar blocks a colas (que se ejecutan en otros threads).

343

Captulo S.10 Stanford: Lecture 10

S.10.2 UIScrollView

Curso iOS 8

Una ventana de contenido tan grande como se quiera, que se puede mover y sobre el que
se puede hacer zoom.

344

Curso iOS 8

Captulo S.10 Stanford: Lecture 10

S.10.3 UITableView

Listado vertical de datos (views y datasource).

S.10.4 Referencias
PDF: Lecture 10 (/doc/stanford/Lecture-10.pdf)

345

Esta pgina se ha dejado vaca a propsito

346

Captulo S.11

Stanford: Lecture 11

347

Captulo S.11 Stanford: Lecture 11

S.11.1 UITableView

S.11.2 iPad

348

Curso iOS 8

Curso iOS 8

Captulo S.11 Stanford: Lecture 11

S.11.3 Referencias
PDF: Lecture 11 (/doc/stanford/Lecture-11.pdf)

349

Esta pgina se ha dejado vaca a propsito

350

Captulo S.12

Stanford: Lecture 12

351

Captulo S.12 Stanford: Lecture 12

S.12.1 Core Data

S.12.2 UIManagedDocument

352

Curso iOS 8

Curso iOS 8

Captulo S.12 Stanford: Lecture 12

S.12.3 NSNotification

S.12.4 Categoras

353

Captulo S.12 Stanford: Lecture 12

S.12.5 Referencias
PDF: Lecture 12 (/doc/stanford/Lecture-12.pdf)

354

Curso iOS 8

Captulo S.13

Stanford: Lecture 13

355

Captulo S.13 Stanford: Lecture 13

S.13.1 Core Data y UITableView

S.13.2 NSFetchedResultsController

356

Curso iOS 8

Curso iOS 8

Captulo S.13 Stanford: Lecture 13

S.13.3 CoreDataTableViewController

S.13.4 Referencias
PDF: Lecture 13 (/doc/stanford/Lecture-13.pdf)

357

Esta pgina se ha dejado vaca a propsito

358

Captulo S.14

Stanford: Lecture 14

359

Captulo S.14 Stanford: Lecture 14

S.14.1 UIApplication

S.14.2 Network Activity Indicator

360

Curso iOS 8

Curso iOS 8

Captulo S.14 Stanford: Lecture 14

S.14.3 Core Location

S.14.4 Referencias
PDF: Lecture 14 (/doc/stanford/Lecture-14.pdf)

361

Esta pgina se ha dejado vaca a propsito

362

Captulo S.15

Stanford: Lecture 15

363

Captulo S.15 Stanford: Lecture 15

S.15.1 Map Kit

S.15.2 MkAnnotation

364

Curso iOS 8

Curso iOS 8

Captulo S.15 Stanford: Lecture 15

S.15.3 MkDirections

S.15.4 Referencias
PDF: Lecture 15 (/doc/stanford/Lecture-15.pdf)

365

Esta pgina se ha dejado vaca a propsito

366

Captulo S.16

Stanford: Lecture 16

367

Captulo S.16 Stanford: Lecture 16

S.16.1 Modal View Controllers

S.16.2 UITextField

368

Curso iOS 8

Curso iOS 8

Captulo S.16 Stanford: Lecture 16

S.16.3 Action Sheet y Alert

S.16.4 Referencias
PDF: Lecture 16 (/doc/stanford/Lecture-16.pdf)

369

Esta pgina se ha dejado vaca a propsito

370

Captulo S.17

Stanford: Lecture 17

371

Captulo S.17 Stanford: Lecture 17

S.17.1 Cmara y UIImagePickerController

S.17.2 Core Motion

372

Curso iOS 8

Curso iOS 8

Captulo S.17 Stanford: Lecture 17

S.17.3 Application State

S.17.4 Referencias
PDF: Lecture 17 (/doc/stanford/Lecture-17.pdf)

373

Esta pgina se ha dejado vaca a propsito

374

Captulo S.18

Stanford: Lecture 18

375

Captulo S.18 Stanford: Lecture 18

S.18.1 Internacionalizacin

S.18.2 NSNumberFormatter

376

Curso iOS 8

Curso iOS 8

Captulo S.18 Stanford: Lecture 18

S.18.3 NSDateFormatter

S.18.4 Referencias
PDF: Lecture 18 (/doc/stanford/Lecture-18.pdf)

377

Esta pgina se ha dejado vaca a propsito

378

Apndice A

Descargas
A.1 Curso completo
Libro PDF (/descargas/ios.pdf)
Libro EPUB (/descargas/ios.epub)

A.2 Recursos
Iconos.zip (/descargas/Iconos.zip)
AppStore.zip (/descargas/AppStore.zip)

A.3 Apps
A.3.1 500px
Versin 1 (collection bsico) 500px.zip (/descargas/v1/500px.zip)
Versin 2 (detalle, cache, scroll infinito) 500px.zip (/descargas/v2/500px.zip)

A.3.2 CoreData
Versin 1 (bsico) EjemploCoreData.zip (/descargas/v1/EjemploCoreData.zip)

A.3.3 Libros
Recursos: Libros.zip (/descargas/Libros.zip)

379

Apndice A Descargas

Curso iOS 8

A.3.4 Ejemplos
Fechas: EjemploSplitView.zip (/descargas/EjemploSplitView.zip)
Fechas: Fechas.zip (/descargas/Fechas.zip)
Fechas: EjemploMapa.zip (/descargas/EjemploMapa.zip)
Fechas: EjemploWebView.zip (/descargas/EjemploWebView.zip)

A.3.5 Juegos
Tetris.zip (/descargas/Tetris.zip)

A.3.6 Rutas
MapKit: Dibujar rea Parque Natural AreaMapa.zip (/descargas/AreaMapa.zip)

A.3.7 GCD
GCD: Descarga asncrona de fotos GCD.zip (/descargas/GCD.zip)

A.3.8 Cervezas
Lista y fotos Cervezas.zip (/descargas/Cervezas.zip)
App iPhone con edicin, borrado, persistencia y picker de fotos Cervezas2.zip
(/descargas/Cervezas2.zip)

A.3.9 Agenda Viaje


Modelo y datos iniciales: AgendaViaje.zip (/descargas/AgendaViaje.zip)
App iPhone: AgendaViaje2.zip (/descargas/AgendaViaje2.zip)
App Universal: AgendaViaje3.zip (/descargas/AgendaViaje3.zip) (falta edicin
iPhone)

A.3.10 Happy
CoreDraw: Happy.zip (/descargas/Happy.zip)
Protocolos y delegacin: HappyDelegate.zip (/descargas/HappyDelegate.zip)

A.3.11 Cuestionario
Cuestionario.zip (/descargas/Cuestionario.zip)

380

Curso iOS 8

Apndice A Descargas

A.4 Ejemplos
Blocks.zip (/descargas/Blocks.zip)
SplitView.zip (/descargas/SplitView.zip)
Popover.zip (/descargas/Popover.zip)
Alertas.zip (/descargas/Alertas.zip)
UIWebView.zip (/descargas/UIWebView.zip)
UIScrollView.zip (/descargas/UIScrollView.zip)
Table.zip (/descargas/Table.zip)

381

Anda mungkin juga menyukai