You are on page 1of 242

Repaso 1

QUE NECESITO PARA HACER UNA


APP IOS

Hardware

Software

Conocimiento

Ideas

Tiempo

HARDWARE NECESARIO

Mnimo

Recomendado

SOFTWARE NECESARIO

Mnimo
SDK

PIXELMATOR

SMULTRON

Recomendado
SDK

PHOTOSHOP

DREAMWEAVER

SMARTSVN

NAVICAT

CONOCIMIENTO NECESARIO PARA


HACER APPS
Diseo grfico y de interfaces
Objective - C
Cocoa
Quartz
C/C++
OpenGL ES 1.5/2.0
GLSL
HTML5
Javascript
CSS
PHP
SQLite
MySQL

QUE VAMOS A APRENDER EN ESTE


CURSO?

Objective C
Cocoa
Quartz

HTML5
Javascript
CSS

OpenGL ES 1.5
OpenGL ES 2.0
GLSL

PHP
MySQL
SQLite

1.Introduccin
- Vamos a crear una aplicacin de ejemplo y repasaremos algunos
aspectos bsicos
- Daremos un repaso a Objective - C
- Gestin de memoria con ARC
- Delegation and Core Location

2.Patrones bsicos en cocoa: Patrn MVC

El modelo-vista-controlador es un patrn arquitectnico. Se


emplea para estructurar las interfaces de los programas de una manera
en la que separamos tareas diferentes en diferentes capas. Por un lado
tenemos la presentacin, por otro la lgica de aplicacin y por otro la
informacin del dominio.

2.Patrones bsicos en cocoa: Delegation

El mecanismo de delegados consiste en que un clase A implementa


los mtodos de otra clase B para hacer se cargo del
comportamiento de esta, cuando esos mtodos son llamados. El
objeto A se llama delegado de B

3.Aplicacin de ejemplo
- Ver diferentes templates de proyectos XCode
- Iconos
- Imgenes de Lanzamiento
- Cmo creamos las interfaces desde Interface Builder
- Declaracin de variables
- Declaracin de mtodos
- Creando conexiones de variables y objetos de IB
- Enlazando objetivos y acciones
- Ejecucin en el simulador
- Ejecucin en el dispositivo
- Debugger
- Instruments

4.Gestin de vistas

- Las diferentes vistas se gestionan


como diferentes capas, pudiendo
superponer unas a otras y soportando
transparencias.

5.Ciclo de vida
Delegate

Vista

Controlador

Inicio
Inicio {AbrirTitulo()}

AbrirTitulo()

Botn {Preferencias()}

AbrirPreferencias()

Fin

Preferencias()

6.Objective-C
- Objective-C es una extensin del lenguaje C
- Las aplicaciones iOS se desarrollan utilizando Objective-C y las libreras de
Cocoa Touch
- Cocoa Touch est escrito en Objective-C y es un conjunto de APIs que
nos permiten programar las aplicaciones

6.Clases
Coche
int numRuedas; //Atributo
-(int) getNumRuedas; //Mtodo
-(void) setNumRuedas:(int)n;

- Clase: Define una estructura y comportamiento.


- Objeto: Es una instancia a una clase.
- Atributo: Propiedad de una clase.
- Mtodo: Define un comportamiento
- Evento: Interaccin del usuario con la mquina.
- Mensaje: comunicacin dirigida a un objeto ordenndole que
ejecute uno de sus mtodos.

7.Instancias
Para crear una instancia de una clase primero debemos pedir memoria
NSMutableArray *listaPersonas = [NSMutableArray alloc];

Pero para ser usado ese objeto, necesita ser inicializado, para ello llamaremos
a su mtodo constructor.
[listaPersonas init];

Se suele usar mediante llamadas anidadas:


NSMutableArray *listaPersonas = [[NSMutableArray alloc] init];

8.Mensajes
- Mensaje : Comunicacin dirigida a un objeto para que ejecute uno de sus
mtodos
NSMutableArray *listaPersonas = [[NSMutableArray alloc] init];
[listaPersonas addObject:@""];

9.Listas y bucles
- Usamos NSArray para crear listas de objetos. NSArray tiene un tamao
fijo, como una constante, definida cuando se crea
- NSMutableArray es como NSArray pero la gestin de memoria es
dinmica, podemos aadir y quitar elementos y el compilador gestionar el
tamao en memoria de la lista
NSMutableArray
[listaPersonas
[listaPersonas
[listaPersonas

*listaPersonas = [[NSMutableArray alloc] init];


addObject:@"Carlos"];
addObject:@"David"];
addObject:@"Juan"];

for (int i=0;i<[listaPersonas count];i++) {


NSLog(@"Posicin %d de la lista es %@",i,[listaPersonas objectAtIndex:i]);
}

10.NSString
- NSString es una clase de Objective-C usada para representar cadenas.
NSString *cadena1 = @"Reserva de memoria implcita";
NSString *cadena2 = [[NSString alloc] initWithString:@"Reserva de memoria con reference counting"];
[cadena2 release];
NSString *cadena3 = [[[NSString alloc] initWithString:@"Reserva de memoria autorelease"] autorelease];

11.Heredar de una clase


- Todas las clases de Objective-C tiene una superclase, excepto NSObject
- Una clase hereda el comportamiento de su superclase

12.Variables y mtodos de instancia


- Para acceder a las variables de instancia hace falta tener una instancia de
esa clase.
@interface Persona : NSObject {
NSString *nombre;
NSString *dni;
int edad;
}
@property (nonatomic, retain) NSString *nombre;
@property (nonatomic, retain) NSString *dni;
@property (nonatomic) int edad;
@end

12.Variables y mtodos de instancia


Propiedades:
@property (atributos) tipo nombre;
Lectura/escritura:
- readwrite: opcin por defecto en la definicin de las
propiedades, y permite que se pueda leer y escribir su contenido.
- readonly: Esta opcin indica que la propiedad es solo de lectura.
Tipo de asignacin:
- assign: opcin por defecto. Se realiza la asignacin sin invocar a
retain. Este tipo se suele utilizar para propiedades de tipos que no son
objetos.
- retain: Se realiza la asignacin invocando a retain. Este tipo solo se
puede utilizar para objetos.
- copy: se le asigna a la propiedad una copia del objeto pasado al
setter.

12.Variables y mtodos de instancia


Atomicidad:
- atomic: es la opcin por defecto y su funcin es bloquear la
asignacin para que ningn hilo pueda modificar la propiedad mientras
lo est haciendo otro hilo.
- nonatomic: en esta opcin no hay bloqueo, por lo que cualquier
hilo puede modificar el valor sin tener que esperar a que termine el
otro.
Mtodos para acceder:
- getter=nombre: por defecto, si no se indica nada, el getter tendr
el mismo nombre que el identificador de la propiedad. Por ejemplo:
getName.
- setter=nombre: por defecto, si no se indica nada, el setter tendr
como nombre al identificador de la propiedad precedido de la palabra
set. Por ejemplo: setName.

13.Mtodos de clase vs mtodos de instancia


Mtodo esttico de la clase:
+ (tipo) nombre;
+ (tipo) nombre:(tipo)param1 ... nombreArgN:(tipo)paramN;
Mtodo de la clase:
- (tipo) nombre;
- (tipo) nombre:(tipo)param1 ... nombreArgN:(tipo)paramN;

14.Gestin de memoria
Implcito
NSString *cadena = [NSString stringWithString:@Hola]; //sin alloc
Manual
alloc +1
retain +1
release -1
NSString *cadena = [[NSString alloc] initWithString:@Hola];
[cadena release];
Automtico
NSString *cadena = [[NSString alloc] initWithString:@Hola];
[cadena autorelease];

15.Gestin de memoria con ARC


- ARC: Automatic Reference Counting
- Evitamos tener que liberar memoria de forma manual y el tiempo que
perdemos buscando memory leaks.
- ARC es un paso de pre-compilacin que aade retain/
release/autorelease sin tener que aadirlo manualmente.
- A pesar de eso, no nos podemos olvidar de la gestin de memoria por
completo.

15.Gestin de memoria con ARC

15.Gestin de memoria con ARC


- Cuando habilitamos ARC nuestro cdigo queda de la siguiente manera:
NSObject *obj = [[NSObject alloc] init];

- Esto no significa que el contador de referencias desaparezca, sino que es


automtico.
- Cuando el precompilador considera que el objeto no se va a usar ms,
aade automticamente una lnea para liberar ese objeto:
[obj release];

16.Referencias fuertes
Se utiliza el atributo strong.
Especifica que hay una relacin de propiedad (fuerte) sobre el objeto de
destino.
Sin ARC:
@property(retain) NSObject *obj;
Con ARC:
@property(strong) NSObject *obj;
@property(weak) NSObject *obj;

17.Referencias dbiles
Se utiliza el atributo weak.
Especifica que hay una relacin de no-propiedad (dbil) sobre el objeto
de destino. Contamos con la ventaja de que si el objeto en cuestin
resulta desalojado de la memoria (dealloc), entonces el valor de la
propiedad se ajustar automticamente a nil y, por tanto, en ningn caso se
producir un cuelgue del programa dado que el lenguaje permite enviar
mensajes a nil.

Repaso 2

1.Introduccin
- Cadenas
- Propiedades comunes de los objetos
- Labels
- Imgenes
- Slider
- AlertView
- MapKit
- Text Input
- UIView
- UIScrollView
- UIWebView
- Mltiples controladores
- AppDelegate

2.Cadenas
Componemos la cadena con el texto de los labels y
textfields
!
!
!
!
!

NSString
cadena =
cadena =
cadena =
cadena =

*cadena
[cadena
[cadena
[cadena
[cadena

= [[NSString alloc] initWithString:@"La cadena es : "];


stringByAppendingFormat:label1.text];
stringByAppendingFormat:textField1.text];!
stringByAppendingFormat:label2.text];
stringByAppendingFormat:textField2.text];! !

3.Propiedades comunes de los objetos


UIView *objeto = [[UIView alloc] initWithFrame:CGRectMake:(0,0,300,300)];

Posicin: [objeto setCenter:CGPointMake(30,30)];


Tamao: [objeto setBounds:CGRectMake(0,0,300,300)];
Transparencia: [objeto setAlpha:0.5];
Hidden: [objeto setHidden:TRUE];
...

4.Label
Cambiar texto de un UILabel:
[label setText:@Texto deseado];

5.Imgenes
Instanciar UIImageView y aadirlo a la vista
UIImageView *imagen = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,100,100)];
[imagen addSubview:self.view];

Cambiar imagen de un UIImageView:


UIImage *im = [UIImage imageNamed:@imagen.jpg];
imagen.image=im;

6.Slider
Configuracin del slider en la carga de la vista
- (void)viewDidLoad
{
[slider setMinimumValue:1.0];
! [slider setMaximumValue:10.0];
! [slider setValue:5.0];
[super viewDidLoad];
}

Mtodo que se invocar cuando el slider cambie de valor


-(IBAction)valueChange:(id)sender{
! int valor = (int)slider.value;
! NSString *cadena = [NSString stringWithFormat:@"El valor es %d",valor];
! [label setText:cadena];
}

7.UISegmentedControl
Detectar cambio en un UISegmentedControl.
- (IBAction)segmentAction:(id)sender
{
! switch ([sender selectedSegmentIndex]) !
{
! ! case 0:
//Hacer algo para la primera pestaa
! ! ! break;
! ! case 1:
//Hacer algo para la primera pestaa
! ! ! break;
! }
}

8.AlertView
Mostramos un AlertView
UIAlertView *alert = [[UIAlertView alloc]
! ! ! initWithTitle: @"Titulo"
! ! ! message: @"Texto aqu"
! ! ! delegate: nil
! ! ! cancelButtonTitle:@"OK"
! ! ! otherButtonTitles:nil];
[alert show];
[alert release];

9.MapKit
Debemos aadir los frameworks de MapKit
Configuracin del mapa en la carga
de la vista
{
!
!
!
!
!
!

(void)viewDidLoad
[mapa
[mapa
[mapa
[mapa

setMapType:MKMapTypeHybrid];
setZoomEnabled:YES];
setScrollEnabled:YES];
setShowsUserLocation:YES];!

[super viewDidLoad];
}

10.Text Input
- Cajas de introducir texto, permiten seleccionar diferentes tipos de
teclados
- Para liberar teclado implementar el protocolo UITextFieldDelegate y
sobreescribir el mtodo de su delegado
- (BOOL)textFieldShouldReturn:(UITextField *)tf
{
[tf resignFirstResponder];
return YES;
}

11.UIView
- Uno de los elementos ms usados
- Podemos tener vistas dentro de otras vistas de manera jerrquica
- Podemos sobreescribir el mtodo drawRect para que la vista pinte algo
especfico

12.UIScrollView
- Crearemos una app de tipo Single View
Application
- Crear un UIScrollView programticamente
y aadirlo a la vista
- Implementar UIScrollViewDelegate en
nuestro controlador
- Crear un UIImageView y asignarle una
imagen, aadirlo al UIScrollView
- Sobreescribir los mtodos adecuados para que
nos permita hacer zoom sobre la imagen

12.UIScrollView
- Creacin y ajuste de elementos
//Instanciar ScrollView
sv = [[UIScrollView alloc] initWithFrame:
CGRectMake(0,0,self.view.bounds.size.width,
self.view.bounds.size.height)];
[self.view addSubview:sv];
[sv release];
//Instanciar UIImageView
iv = [[UIImageView alloc] initWithFrame:
CGRectMake(0,0,self.view.bounds.size.width*2,
self.view.bounds.size.height*2)];
[sv addSubview:iv];
[iv release];
//Asignar propiedades UIImageView
[iv setImage:[UIImage imageNamed:@"wallpaper.jpg"]];
//Asignar propiedades UIScrollView
[sv setContentSize:CGSizeMake(iv.bounds.size.width, iv.bounds.size.height)];
[sv setMinimumZoomScale:0.5];
[sv setMaximumZoomScale:2.5];
[sv setZoomScale:1.0 animated:TRUE];
[sv setDelegate:self];

12.UIScrollView
- Devolver vista sobre la que se realizar zoom
-(UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return iv;
}

13.UIWebView
Cargar web en un UIWebView
-(IBAction)irAPagina:(id)sender
{
! //Obtain the url
! NSString *urlAddress = textField.text;
!
! //Create an NSURL Object
! NSURL *url = [NSURL URLWithString:urlAddress];
!
! //URL Request Object
! NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
!
! //Load the request in the UIWebView.
! [webView loadRequest:requestObj];
}

14.UITabBar
Seleccionar tabButton
//Seleccionar el primer elemento
[tabBar setSelectedItem:[tabBar.items objectAtIndex:0]];

Recoger pulsacin
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
! switch (item.tag) {
! ! case 0:
! ! ! //Pestaa1
! ! ! break;
! ! case 1:
! ! ! //Pestaa2
! ! ! break;
! }! ! !
}

15.Mltiples controladores

Cargar un controlador y aadirlo a una vista


!

controlador1=[[Controlador1 alloc] initWithNibName:@"Controlador1" bundle:nil];

[vistaControladores addSubview:controlador1.view];

Quitar la vista de un controlador y liberarlo


[controlador1.view removeFromSuperview];
[controlador1 release];
controlador1=nil;

16.AppDelegate
- Para controlar el ciclo de vida utilizaremos el AppDelegate.
- En AppDelegate instanciaremos nuevos controladores y
eliminaremos los que no usemos.
- Desde los controladores podremos acceder al AppDelegate para
invocar un mtodo
#import ClaseD.h
ClaseD *mainDelegate = (ClaseD*) [[UIApplication sharedApplication] delegate];
[mainDelegate cambiarAVista2];

Repaso 3

1.Introduccin
- UITableView y UITableViewController
- Edicin de UITableView
- UINavigationController
- UIPopoverController
- Vistas Modales

2.UITableView

- Podemos trabajar con este elemento haciendo


subclassing de UITableViewController o
implementando el delegate de
UITableViewControllerDelegate en otro
controlador
- Vamos a crear un Single View Application
- Mostrar una lista de los meses en un
UITableView

2.UITableView
- Implementar el protocolo UITableViewDelegate en nuestro
controlador
- Escribir los mtodos del delegate
- Rellenar array
lista = [[NSMutableArray alloc] initWithCapacity:12];
[lista addObject:@"Enero"];
[lista addObject:@"Febrero"];
[lista addObject:@"Marzo"];
[lista addObject:@"Abril"];
[lista addObject:@"Mayo"];
[lista addObject:@"Junio"];
[lista addObject:@"Julio"];
[lista addObject:@"Agosto"];
[lista addObject:@"Septiembre"];
[lista addObject:@"Octubre"];
[lista addObject:@"Noviembre"];
[lista addObject:@"Diciembre"];

2.UITableView
- Mtodos para rellenar contenido
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [lista count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (!cell) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"UITableViewCell"] autorelease];
}
[[cell textLabel] setText:[lista objectAtIndex:indexPath.row]];
return cell;
}

2.UITableView
- Mtodo para modo de editar
- (IBAction)toggleEditingMode:(id)sender
{
if ([tableView isEditing]) {
[sender setTitle:@"Editar"];
[tableView setEditing:NO animated:YES];
} else {
[sender setTitle:@"Hecho"];
[tableView setEditing:YES animated:YES];
}
}

2.UITableView
- Mtodo para mover celdas
- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
{
if (fromIndexPath.row == toIndexPath.row) {
return;
}
//Quitamos elemento de posicin from
NSString *e1 = [lista objectAtIndex:fromIndexPath.row];
[e1 retain];
[lista removeObjectAtIndex:fromIndexPath.row];
//Lo aadimos a posicin to
[lista insertObject:e1 atIndex:toIndexPath.row];
[e1 release];
}

2.UITableView
- Mtodo para eliminar celdas
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
//Eliminamos el elemento del array
[lista removeObjectAtIndex:indexPath.row];
//Y del tableView con una animacin
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:YES];
}
}

2.UITableView
- Mtodo para cuando seleccionemos una celda
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Ha seleccionado el mes %@",[lista
objectAtIndex:indexPath.row]);
}

3.UINavigationController
- Cambiemos algo de cdigo en AppDelegate para aadir un
UINavigationController
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
autorelease];
// Override point for customization after application launch.
UIViewController *vc = [[[ViewController alloc] initWithNibName:@"ViewController"
bundle:nil] autorelease];
self.window.rootViewController = [[[UINavigationController alloc]
initWithRootViewController:vc] autorelease];
[self.window makeKeyAndVisible];
return YES;
}

3.UINavigationController
- Configurar barra de navegacin
//Poner ttulo
[self.navigationItem setTitle:@"Meses"];
//Aadir botn editar
UIBarButtonItem *editar = [[UIBarButtonItem alloc] initWithTitle:@"Editar"
style:UIBarButtonItemStylePlain
target:self action:@selector(toggleEditingMode:)];
self.navigationItem.rightBarButtonItem = editar;
[editar release];

4.UIPopoverController
- Vamos a hacer un nuevo ejemplo
p a r a i Pa d y u s a r e m o s u n
UIPopoverController, que
slo est disponible en estos
dispositivos y no en iPhone e iPod
Touch
- Crear proyecto Single View
Application
- Aadir otro controlador y
programarlo con la vista que
queramos mostrar

4.UIPopoverController
1. Implementar protocolo UIPopoverControllerDelegate
2. Crear puntero en la cabecera de nuestro controlador
UIPopoverController *mesesPopover;

3. Escribir mtodos del delegate UIPopoverController


4. Invocar popOver cuando corresponda

4.UIPopoverController
- Mtodo del delegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
[popOver autorelease];
popOver = nil;
}

- Nos permitir responder al evento de cerrar esta vista modal

4.UIPopoverController
- Mtodo que lo despliega
-(IBAction)verPopover:(id)sender{
if (popOver==nil) {
Otro *otro = [[[Otro alloc] initWithNibName:@"Otro" bundle:nil] autorelease];
popOver = [[UIPopoverController alloc] initWithContentViewController:otro];
[popOver setDelegate:self];
[popOver presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
} else {
[popOver dismissPopoverAnimated:YES];
[popOver autorelease];
popOver = nil;
}
}

5.Vistas Modales
- Las vistas modales son ViewControllers predefinidos que nos
proporciona el sistema y que nos permiten hacer cosas habituales como
seleccionar una foto, enviar un mail, elegir un contacto, etc..

5.Vistas Modales
- En nuestro ejemplo vamos a aadir un botn nuevo que nos permita enviar
un mail
1. Implementar el protocolo
MFMailComposeViewControllerDelegate

2. Aadir el framework
MessageUI.framework
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>

3. Sobreescribir mensajes del delegate implementado


4. Crear mensaje lanzador

5.Vistas Modales
- Sobreescribir mtodo del delegate implementado
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {!
! [self dismissModalViewControllerAnimated:YES];
}

- Nos permitir responder al evento de cerrar esta vista modal

5.Vistas Modales
- Invocar vista modal
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!

Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));


if (mailClass != nil)!{
!
if ([mailClass canSendMail]) {
!
!
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
!
!
picker.mailComposeDelegate = self;
!
!
picker.navigationBar.barStyle = UIBarStyleBlack;
!
!
!
!
[picker setSubject:@"Ttulo del mensaje"];
!
!
!
!
// Aadir destinatarios por defecto
!
!
NSArray *toRecipients = [NSArray arrayWithObject:@"correo@enviar.com"];
!
!
!
!
[picker setToRecipients:toRecipients];
!
!
!
!
// Rellenar contenido del mail por defecto
!
!
NSString *emailBody = @"Introduce aqu tu texto...";
!
!
[picker setMessageBody:emailBody isHTML:NO];
!
!
!
!
[self presentModalViewController:picker animated:YES];
!
!
[picker release];!!
!
}
}

Repaso 4

1.Introduccin
- Notification and Rotation
- Camera
- Settings
- Localization
- Multitarea
- Gestures
- Animaciones
- Transiciones predefinidas entre vistas

2.Notification and Rotation


- Usaremos notificaciones para atender a ciertos eventos, como por
ejemplo la rotacin del dispositivo
// Obtener el objeto dispositivo
UIDevice *device = [UIDevice currentDevice];
// Empezar a monitorizar notificaciones que tengan que ver con la orientacin
[device beginGeneratingDeviceOrientationNotifications];

Texto

//Aadir notificacin y asignarle un mtodo


NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:device];

- Mtodo manejador
- (void)orientationChanged:(NSNotification *)note
{
NSLog(@"orientationChanged: %d", [[note object] orientation]);
}

3.Camera

- Crearemos un programa que tome una


foto de la biblioteca y la asigne en un
UIImageView sobre la pantalla

3.Camera
- Implementar el protocolo UIImagePickerControllerDelegate
- Obtener foto
-(IBAction)tomarFoto:(id)sender{
//Instanciar controlador
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
//Asignar la vista actual como delegate y presentarlo
[imagePicker setDelegate:self];
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
}

3.Camera
- Obtener foto seleccionada
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//Obtener la imagen y asignarla a un UIImageView
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[imagen setImage:image];
[self dismissModalViewControllerAnimated:YES];
}

4.Settings
- Guardar preferencias
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
standardUserDefaults setObject:@Hola forKey:@"clave"];
[standardUserDefaults synchronize]; !

- Cargar preferencias
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *cadena = [[standardUserDefaults objectForKey:@clave] retain];

5.Localization - XIBs
- Creamos nuevo proyecto Single View Application
- Aadimos algunos labels y otros elementos a la vista
- Despus aadimos a la localizacin de la vista el idioma Espaol
- Desde la consola usaremos el comando ibtool para generar el fichero de
cadenas a partir de nuestro xib
ibtool --generate-strings-file ~/Desktop/ViewController.strings ViewController.xib

- Ese comando genera un fichero con el siguiente contenido:


/* Class = "IBUILabel"; text = "Texto del label"; ObjectID = "8"; */
"8.text" = "Texto del label";
/* Class = "IBUINavigationItem"; title = "Titulo de la vista"; ObjectID = "10"; */
"10.title" = "Titulo de la vista";

5.Localization - XIBs
- Editamos el fichero para asignar los valores del idioma al que vamos a
traducir
/* Class = "IBUILabel"; text = "Texto del label"; ObjectID = "8"; */
"8.text" = "Label text";
/* Class = "IBUINavigationItem"; title = "Titulo de la vista"; ObjectID = "10"; */
"10.title" = "Title of the view";

- Ahora usamos ibtool para crear un nuevo Xib basado en nuestro xib anterior
ibtool --strings-file ~/Desktop/ViewController.strings --write ../es.lproj/ViewController.xib ViewController.xib

- Esto nos modifica el XIB cuando ese idioma sea el de por defecto
utilizando los valores del fichero de texto

5.Localization - Cdigo
- Para localizar el cdigo de la aplicacin utilizaremos la macro
NSLocalizedString
- Vamos a crear un label dinmicamente y queremos que est localizado
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,100,20)];
[self.view addSubview:label];
[label setText: NSLocalizedString(@"Label aadida",@"El texto de la label que
aadimos") ];

- Desde la consola usaremos el comando


$ genstrings ViewController.m

5.Localization - Cdigo
- Ese comando nos genera el fichero Localizable.strings que contiene lo
siguiente
/* El texto de la label que aadimos */
"Label aadida" = "Label aadida";

- Lo modificamos
/* El texto de la label que aadimos */
"Label aadida" = "Label added";

- Aadimos el fichero Localizable.strings a nuestro proyecto


- Si ejecutamos la app en el idioma al que hemos traducido, saldr localizada, ya
que NSLocalizedString lee el fichero Localizable.strings

6.Multitarea
- Controlamos la multitarea mediante la implementacin de ciertos mtodos
en el AppDelegate de nuestras aplicaciones

7.Gestures
- Podemos definir ciertos comportamiento para los gestos que registra una
vista mediante Gesture Recognizers

UITapGestureRecognizer - Toque

UIPinchGestureRecognizer - Zoom

UIRotationGestureRecognizer - Rotar

UISwipeGestureRecognizer - Arrastrar izquierda o derecha

UIPanGestureRecognizer - Mover

UILongPressGestureRecognizer - Pulsacin larga

7.Gestures
- La forma de trabajar con gestures es la siguiente:
1. Implementar protocolo UIGestureRecognizerDelegate
2. Crear el gesture regognizer y aadirlo a la vista
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:@selector(swipeRightAction:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
swipeRight.delegate = self;
[self.view addGestureRecognizer:swipeRight];!
[swipeRight release];

3. Crear mtodo que se encarga de recoger el evento cuanto se


produce ese gesto sobre la vista
-(void)swipeRightAction:(UIPanGestureRecognizer*)gestureRecognizer{
//METER CDIGO
}

8.Animaciones
- Crear una interpolacin en el valor de las propiedades de un objeto
//DEFINIR PROPIEDADES INICIALES
imagen.alpha=1;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
!//DEFINIR PROPIEDADES FINALES
!imagen.alpha=0;
[UIView commitAnimations];

9.Transiciones predefinidas entre vistas


- Eliminar primer controlador, instanciar segundo y indicar
transicin
[primerControlador.view removeFromSuperview];
[primerControlador release];
primerControlador=nil;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.window cache:YES];
!

segundoControlador = [[SegundoControlador alloc] initWithNibName:@"SegundoControlador" bundle:nil];

[self.window addSubview:segundoControlador.view];

[UIView commitAnimations];

9.Transiciones predefinidas entre vistas

Posibles transiciones entre vistas:


UIViewAnimationTransitionCurlUp
UIViewAnimationTransitionCurlDown
UIViewAnimationTransitionFlipFromLeft
UIViewAnimationTransitionFlipFromRigth

19.Touch Events and


UIResponder

1.Touch Events
- Elementos como UIScrollView permiten hacer eventos multitctiles
pero su comportamiento est predefinido.
- Usaremos Touch Events cuando queramos un comportamiento
especfico.
- En este apartado crearemos una vista sobre la que poder pintar usando
las caractersticas multitouch de los dispositivos.
- Utilizaremos el gesto doble-tap para limpiar la pantalla

1.Touch Events
- Heredando de UIResponder podremos sobreescribir cuatro mtodos
para capturar los distintos eventos:
Uno o varios dedos tocan la pantalla:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

Uno o varios dedos se mueven por la pantalla:


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

Uno o varios dedos son retirados de la pantalla:


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

El sistema interrumpe este movimiento antes de que


termine por una llamada u otro evento:
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

2.Creating the TouchTracker Application

- Podemos tocar y arrastrar


sobre la pantalla y arrastrar para
dibujar una linea
- Con doble-tap limpiamos la
pantalla

2.Creating the TouchTracker Application


- Crear proyecto de tipo Single View Application
- Crear objeto Line de tipo NSObject
- Crear objeto TouchDrawView de tipo NSObject y personalizarlo para
que herede de UIView
- Asociar un objeto de tipo UIView de ViewController.xib en interface
builder con nuestra clase TouchDrawView
- Sobreescribir los mtodos de dibujado en TouchDrawView
- Sobreescribir los mtodos de toques en TouchDrawView

2.Creating the TouchTracker Application


Line.h
#import <Foundation/Foundation.h>
@interface Line : NSObject {
CGPoint begin;
CGPoint end;
}
@property (nonatomic) CGPoint begin;
@property (nonatomic) CGPoint end;
@end

Line.m
#import Line.h
@implementation Line
@synthesize begin,end;
@end

2.Creating the TouchTracker Application


TouchDrawView.h
#import <Foundation/Foundation.h>
@interface TouchDrawView : UIView{
NSMutableArray *lines;
CGPoint lineInProgressBegin;
CGPoint lineInProgressEnd;
}
@end

2.Creating the TouchTracker Application


TouchDrawView.m
#import TouchDrawView.h
#import Line.h
@implementation TouchDrawView
-(id)initWithCoder:(NSCoder*)c
{
self = [super initWithCoder:c];
if (self) {
lines = [[NSMutableArray alloc] init];
lineInProgressBegin = CGPointMake(0,0);
lineInProgressEnd = CGPointMake(0,0);
[self setMultipleTouchEnabled:FALSE];
}
return self;
}
-(void)dealloc
{
[lines release];
[super dealloc];
}

3.Drawing with TouchDrawView


- Sobreescribir el mtodo drawRect para dibujar lo que queramos sobre
la vista.
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 10.0);
CGContextSetLineCap(context, kCGLineCapRound);
// Lineas completas en negro
[[UIColor blackColor] set];
for (Line *line in lines) {
CGContextMoveToPoint(context, [line begin].x, [line begin].y);
CGContextAddLineToPoint(context, [line end].x, [line end].y);
CGContextStrokePath(context);
}
// Linea en progreso en rojo
[[UIColor redColor] set];
if (!CGPointEqualToPoint(lineInProgressBegin,lineInProgressEnd)){
CGContextMoveToPoint(context, lineInProgressBegin.x, lineInProgressBegin.y);
CGContextAddLineToPoint(context, lineInProgressEnd.x, lineInProgressEnd.y);
CGContextStrokePath(context);
}
}

3.Drawing with TouchDrawView


- Hacer el mtodo de limpiar
- (void)clearAll
{
// Borrar la lineas
[lines removeAllObjects];
// Redibujar
[self setNeedsDisplay];
}

4.Turning Touch into Lines


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//Capturamos el evento del primer dedo detectado
UITouch *t = [touches anyObject];
if ([t tapCount] > 1) {
[self clearAll];
} else {
//Inicializamos el comienzo y el final de la linea
lineInProgressBegin = [t locationInView:self];
lineInProgressEnd = lineInProgressBegin;
// Redibujar
[self setNeedsDisplay];
}
}

4.Turning Touch into Lines


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *t = [touches anyObject];
//Actualizamos el final de la linea
lineInProgressEnd = [t locationInView:self];
// Redibujar
[self setNeedsDisplay];
}

4.Turning Touch into Lines


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
//Creamos un objeto de tipo linea y
//le asignamos los valores de nuestra linea en progreso
Line *linea = [[Line alloc] init];
linea.begin=lineInProgressBegin;
linea.end=lineInProgressEnd;
//Aadimos dicho objeto a la lista de lineas
[lines addObject:linea];
//Reiniciar linea en progreso
lineInProgressBegin = CGPointMake(0,0);
lineInProgressEnd = CGPointMake(0,0);
// Redibujar
[self setNeedsDisplay];
}

5.The Responder Chain

UIResponder no maneja el evento porque al no estar sobrescritos sus


mtodos entonces enva el evento al siguiente respondedor.
Mandar mensaje explcitamente al siguiente respondedor:
[[self nextResponder] touchesBegan:touches withEvent:event];

6.Saving and Loading


- Crear dos botones, uno de Save y otro de Load en nuestra vista y
asociarlos a dos mtodos que implementaremos
- Para poder utilizar el mtodo archiveDataWithRootObject es necesario que
implementemos en nuestro objeto Line algunos mtodos
-(IBAction)save:(id)sender{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:lines];
[prefs setObject:data forKey:@"Lineas"];
[prefs synchronize];
}

6.Saving and Loading


-(IBAction)load:(id)sender{
if (lines!=nil) {
[lines release];
}

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];


NSData *data = [prefs objectForKey:@"Lineas"];
if (data != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
if (oldSavedArray != nil)
lines = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
lines = [[NSMutableArray alloc] init];
}
[self setNeedsDisplay];

6.Saving and Loading


Line.m
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeFloat:begin.x forKey:@"beginX"];
[coder encodeFloat:begin.y forKey:@"beginY"];
[coder encodeFloat:end.x forKey:@"endX"];
[coder encodeFloat:end.y forKey:@"endY"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[Line alloc] init];
if (self != nil)
{
begin = CGPointMake([coder decodeFloatForKey:@"beginX"],[coder
decodeFloatForKey:@"beginY"]);
end = CGPointMake([coder decodeFloatForKey:@"endX"],[coder
decodeFloatForKey:@"endY"]);
}
return self;
}

7.Circles

- Podemos tocar y arrastrar


sobre la pantalla y arrastrar para
dibujar una crculo
- Con doble-tap limpiamos la
pantalla

7.Circles
//Establecer contexto
CGContextRef context = UIGraphicsGetCurrentContext();
//Poner Color
[[UIColor blackColor] set];
//Calcular cuadrado que lo engloba
CGPoint vector = CGPointMake(circle.end.x-circle.begin.x, circle.end.y-circle.begin.y);
float radio = sqrt(pow(vector.x,2) + pow(vector.y,2));
float diametro = radio*2;
float origenX = circle.begin.x - radio;
float origenY = circle.begin.y - radio;
CGRect bordes = CGRectMake(origenX,origenY,diametro,diametro);
//Pintar Crculo
CGContextFillEllipseInRect(context,bordes);

8.UIControl
- UIControl es la superclase de muchos elementos de Cocoa Touch, entre
ellos UIButton o UISlider.
- UIControl sobreescribe los mismos mtodos de UIResponder que
hemos visto en este apartado
- UIControl asocia cada posible evento con una constante. Por ejemplo
UIControlEventTouchUpInside.

8.UIControl
- Veamos como UIControl manejara el evento UIControlEventTouchUpInside
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Referencia al toque que acaba de terminar
UITouch *touch = [touches anyObject];
//Posicin del punto en el sistema de coordenadas del control
CGPoint touchLocation = [touch locationInView:self];
// Esta el punto dentro de los mrgenes de mi vista?
if (CGRectContainsPoint([self bounds], touchLocation)) {
//Enviar mensaje a todos los targets registrados para este evento
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
} else {
//Enviar un mensaje diferente
[self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
}

20.Core Animation Layer

0.Introduction
- Las animaciones son la marca caracterstica de las interfaces de iOS
y Mac OS X
- Cuando queramos usar Core Animation debemos aadir el framework
de QuartzCore
- Hay dos clases con las que Core Animation funciona, estas son CALayer
y CAAnimation
- CALayer es un buffer que contiene una imagen, se pinta en pantalla
mediante hardware, por lo que su funcionamiento es muy rpido.
- CAAnimation causa un cambio mediante interpolacin en alguna
propiedad de un objeto a lo largo de un periodo de tiempo.
- En este apartado nos centraremos en CALayer

1.Layers and views


- Una UIView es realmente una abstraccin de un objeto visible con el que
poder interaccionar
- Cada UIView renderiza su contenido en una CALayer que tiene
implcitamente
- Un CALayer es un buffer que se pinta directamente sobre la pantalla y
que slo tiene que ver con el renderizado y no con la interaccin con el
usuario
- No todas las CALayer son implcitas, ya que podemos crear CALayers
explcitamente

2.Creating a CALayer

- Imagen de fondo
- Rectngulo rojo que resalta un rea

2.Creating a CALayer
- Crear proyecto de tipo Single View Application
- Aadir el framework QuartzCore
- Incluir la librera <QuartzCore/QuartCore.h> donde vayamos a usar
este framework
- Aadir imagen a la vista ViewController.xib
- Crear el puntero a la CALayer en ViewController.m
- Instanciar nuestra CALayer en el mtodo ViewDidLoad de
ViewController.m

2.Creating a CALayer
- Instanciaremos la CALayer en el mtodo ViewDidLoad de ViewController.m
ViewController.m
//Crear el nuevo objeto de tipo CALayer
boxLayer = [[CALayer alloc] init];
//Ajustar el tamao adecuado
[boxLayer setBounds:CGRectMake(0,0,85,85)];
//Ajustar la posicin
[boxLayer setPosition:CGPointMake(160,100)];
//Crear un UIColor, despus convertirlo a CGColorRef y asociarlo al color
de fondo
UIColor *rojo = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
CGColorRef rojoCG = [rojo CGColor];
[boxLayer setBackgroundColor:rojoCG];
//Hacer que la CALayer se sublayer de la layer de la vista del controlador
[[self.view layer] addSublayer:boxLayer];

3.Layer Content
- Una layer es simplemente una imagen
- Su contenido puede ser generado a partir de una imagen o programticamente
//Crear imagen, y obtener la CGImage
UIImage *layerImage = [UIImage imageNamed:@"image.jpg"];
CGImageRef image = [layerImage CGImage];
//Poner la imagen en la layer
[boxLayer setContents:(id)image];

- Cada layer tiene una coordenada Z


para ver cual se pinta primero
[boxLayer setZPosition:-5];

4.Implicity Animatable Properties


- Las CALayer tienen propiedades que pueden ser modificadas y cuando se
cambian realizan una animacin hasta alcanzar su nuevo valor
- Modifiquemos el ejemplo anterior para que la capa reaccione a nuestros toques
en la pantalla con una animacin de la CALayer desplazandose hasta la
posicin donde hemos tocado

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event


{
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self.view];
[boxLayer setPosition:p];
}

5.Programmatically Generating Content


- Para generar el contenido podemos crear un NSObject y cambiar el padre
para que herede de CALayer y implementar la rutinas de pintado:
@implementation LayerSubclass
- (void)drawInContext:(CGContextRef)ctx {
!
UIImage *layerImage = [UIImage imageNamed:@"image.png"];
!
CGRect boundingBox = CGContextGetClipBoundingBox(ctx);
!
CGContextDrawImage(ctx, boundingBox, [layerImage CGImage]);
}
@end

- Necesario invocar al mtodo setNeedsDisplay de CALayer para que se


dibuje su contenido

5.Programmatically Generating Content


- Tambin podemos generar el contenido asignando el delegate de nuestra
instancia CALayer a otro objeto que implemente las rutinas de pintado
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
UIImage *layerImage = [UIImage imageNamed:@"image.jpg"];
CGRect boundingBox = CGContextGetClipBoundingBox(ctx);
CGContextDrawImage(ctx,boundingBox,[layerImage CGImage]);
}

- Aadir despus de la instanciacin


[boxLayer setDelegate:self];
[boxLayer setNeedsDisplay];

- Necesario invocar al mtodo setNeedsDisplay de CALayer para que se


dibuje su contenido

6.Layers, Bitmaps, and Contexts


- Una CALayer es simplemente una imagen que despus se vuelca a
pantalla.
- Una imagen es una posicin de memoria donde se almacena una lista
de componentes rojo, verde, azul y alpha para cada pixel
- Cuando ejecutamos instrucciones de QuarzCore estas realizan acciones de
pintado sobre una CALayer en concreto, estas instrucciones son ejecutadas
en ese contexto

7.Dynamic Layer Content


- Modificar el ejemplo para que dependiendo de la posicin y de
donde toquemos el rectngulo sea ms o menos rojo
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
/*
480 - 1.0
y
- cantidadAlpha;
*/
float cantidadAlpha = p.y/480.0;

UIColor *rojo = [UIColor colorWithRed:1 green:0 blue:0 alpha:cantidadAlpha];


CGColorRef rojoCG = [rojo CGColor];
[boxLayer setBackgroundColor:rojoCG];

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event


{
UITouch *t = [touches anyObject];
p = [t locationInView:self.view];
[boxLayer setPosition:p];
[boxLayer setNeedsDisplay];
}

21.Controlling Animation
with CAAnimation

1.Animation Objects
- Un objeto de animacin es un conjunto de instrucciones que
cambian las propiedades de una instancia de CALayer.
- Muchas de las propiedades de CALayer como opacidad, posicin,
tamao, etc pueden ser animadas por los objetos de animacin utilizando
una funcin de interpolacin.
- Un ejemplo sera Muevete del punto A al punto B durante 2 segundos

1.Animation Objects
- En la practica, la forma de utilizar estos objetos de animacin es mediante
alguna de las subclases que heredan de CAAnimation

2.Spinning with CABasicAnimation

- Imagen de fondo
- 3 botones, cada uno con la imagen
de un jugador
- Cuando pulsemos en cada uno de
esos botones la pelota se desplazar
hacia el jugador

2.Spinning with CABasicAnimation


- Crear proyecto de tipo Single View Application
- Aadir el framework QuartzCore
- Incluir la librera <QuartzCore/QuartCore.h> donde vayamos a usar
este framework
- Aadir imgenes y botones a la vista ViewController.xib
- Crear los punteros y hacer los enlaces
- Crear un mtodo para la pulsacin de cada botn

2.Spinning with CABasicAnimation


- Mtodo de uno de los botones
-(IBAction)jugador1:(id)sender{
CABasicAnimation *animacion = [CABasicAnimation animationWithKeyPath:@"position"];
[animacion setDuration:1.0];
CGPoint p1 = CGPointMake(pelota.center.x, pelota.center.y);
CGPoint p2 = CGPointMake(jugador1.center.x, jugador1.center.y);
[animacion setFromValue:[NSValue valueWithCGPoint:p1]];
[animacion setToValue:[NSValue valueWithCGPoint:p2]];
[[pelota layer] addAnimation:animacion forKey:@"animacion"];
}

3.Timing functions
- En nuestro ejemplo la animacin comienza de repente porque se hace una
interpolacin lineal
- Podemos cambiar la funcin de interpolacin por otra diferente como por
ejemplo una que comience aceleradamente y termine desacelerando
CAMediaTimingFunction *tf = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animacion setTimingFunction:tf];

Diferentes valores de interpolacin son:


kCAMediaTimingFunctionLinear
kCAMediaTimingFunctionEaseInEaseOut
kCAMediaTimingFunctionEaseIn
kCAMediaTimingFunctionEaseOut

4.Animation completion
- Asociar nuestro controlador como delegate de la animacin
[animacion setDelegate:self];

- Cuando la animacin termine se realizar una llamada al mtodo


animationDidStop que deberemos sobreescribir para realizar una accin
justo despus de que la animacin haya terminado.

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag


{
[pelota setCenter:puntoFinal];
}

5.Bouncing with a CAKeyframeAnimation


- En las animaciones con CAKeyframeAnimation especificaremos
diferentes valores a lo largo del tiempo. Cada valor ser un key frame
- Vamos a extender el ejemplo anterior para que la pelota cambie de tamao
a lo largo del tiempo, simulando de esta forma como si subiera en altura

5.Bouncing with a CAKeyframeAnimation


//Crear la animacin de tipo key frames
CAKeyframeAnimation *animacion3 = [CAKeyframeAnimation
animationWithKeyPath:@"transform"];
//Crear los valores por los que pasar el parmetro transform
CATransform3D t1 = CATransform3DMakeScale(1.0,1.0,1.0);
CATransform3D t2 = CATransform3DMakeScale(2.0,2.0,1.0);
CATransform3D t3 = CATransform3DMakeScale(1.0,1.0,1.0);
//Asociamos los diferentes valores
[animacion3 setValues:[NSArray arrayWithObjects:
[NSValue valueWithCATransform3D:t1],
[NSValue valueWithCATransform3D:t2],
[NSValue valueWithCATransform3D:t3],
nil]];
//Ajustamos el tiempo que durar la animacin y configuramos su delegado
[animacion3 setDuration:2.0];
[animacion3 setDelegate:self];
//Aadimos la animacin
[[pelota layer] addAnimation:animacion3 forKey:@"keyAnimation"];

6.More Animation
- Como hemos visto se pueden solapar varias animaciones en un mismo
instante de tiempo
- Extender el ejemplo anterior para que la pelota:
- tarde 2 segundos en desplazarse de un jugador a otro
- mientras tanto su alpha cambia de 0.0 a 1.0 durante 1 segundo
- adems su escala cambia a lo largo de 2 segundos los valores 1,2,1
- que los pelotazos empiecen con velocidad y terminen en seco

7.The Presentation Layer and the Model Layer


- Cuando una instancia de la clase CALayer esta siendo animada esta tiene
unos parmetros como son opacity, transform, position que cambian de
valor. Cuando hay una animacin en marcha, ldicha clase tiene dos copias
de esos parmetros.
- La capa de modelo contiene los valores finales de la animacin
- La capa de presentacin contiene los valores interpolados para ese
instante de tiempo.
- Esto es til por ejemplo cuando se tienen objetos con una animacin en
curso y el usuario realiza un toque sobre ellos. En ese caso la informacin
correcta de la posicin la tendr la capa de presentacin.
CGPoint whereIsItWhenAnimationStops = [layer position];
CGPoint whereIsItNow = [[layer presentationLayer] position];

22.Blocks and Categories

1.Colorizing TouchDrawView

- Partiremos de nuestro ejemplo


TouchDrawView
- Vamos a utilizar bloques para
pintar con diferentes colores

1.Colorizing TouchDrawView
- Antes de nada vamos a modificar la clase line para que almacene un color
Line.h :
#import <Foundation/Foundation.h>
@interface Line : NSObject {
CGPoint begin;
CGPoint end;
UIColor *color;
}
@property(nonatomic) CGPoint begin;
@property(nonatomic) CGPoint end;
@property(nonatomic,retain) UIColor *color;
@end

Line.m :

1.Colorizing TouchDrawView

#import "Line.h"
@implementation Line
@synthesize begin,end;
@synthesize color;
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeFloat:begin.x forKey:@"beginX"];
[coder encodeFloat:begin.y forKey:@"beginY"];
[coder encodeFloat:end.x forKey:@"endX"];
[coder encodeFloat:end.y forKey:@"endY"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[Line alloc] init];
if (self != nil)
{
color = [UIColor blackColor];
begin = CGPointMake([coder decodeFloatForKey:@"beginX"],[coder decodeFloatForKey:@"beginY"]);
end = CGPointMake([coder decodeFloatForKey:@"endX"],[coder decodeFloatForKey:@"endY"]);
}
return self;
}
-(void)dealloc{
[color release];
}
@end

1.Colorizing TouchDrawView
- En TouchDrawView.m, en el mtodo drawRect sustituiremos:
[[UIColor blackColor] set];

- Por la propiedad el color de nuestra linea, quedando el bucle de la siguiente


forma:
for (Line *line in lines) {
[[line color] set];
CGContextMoveToPoint(context, [line begin].x, [line begin].y);
CGContextAddLineToPoint(context, [line end].x, [line end].y);
CGContextStrokePath(context);
}

2.Blocks
- Trozos de cdigo que se pueden guardar en variables o pasar como
argumentos
- Tambin se pueden devolver como el resultado de un mensaje y ejecutar
posteriormente
- Los bloques capturan el entorno lxico, entenderemos que quiere decir
esto unas transparencias ms adelante.

3.Blocks as variables
- Vamos a crear un mtodo que reciba como variable un bloque.
- El nombre de esa variable la llamamos color
- Dentro del mtodo usamos el bloque color si fuera una funcin
-(void)transformLineColorsWithBlock:(UIColor* (^)(Line*))color{
for (Line *l in lines) {
UIColor *c = color(l);
[l setColor:c];
}
[self setNeedsDisplay];
}

3.Blocks as variables
- Despus crearemos un botn en la interface y lo enlazaremos con un
mtodo que llamaremos colorear
-(IBAction)colorear:(id)sender{
UIColor *(^esquemaDeColor)(Line*)=^(Line *l) {
float longitudX = l.end.x - l.begin.x;
float longitudY = l.end.y - l.begin.y;
/* Regla de tres
320 - 1.0
longitudX - r
480 - 1.0
longitudY - g
*/
float r=longitudX/320.0;
float g=longitudY/480.0;
float b=1.0;
return [UIColor colorWithRed:r green:g blue:b alpha:1];
};
[self transformLineColorsWithBlock:esquemaDeColor];
}

4.Capturing variables
- Los bloques capturan el entorno lxico
-(void)metodo{
int value = 5;
void (^aBlock)() = ^(void){
NSLog(@"valor=%d",value);
};
aBlock(); //Imprime "valor=5"
value = 10;
aBlock();
}

//Imprime "valor=5"

5.Using blocks with other build-in methods


- Podemos usar bloques en las siguientes acciones:
- Ordenacin (el bloque se proporciona como mtodo de comparacin)
- Notificacin (cuando ocurra un evento ejecuta el bloque)
- Gestores de error (cuando ocurra un error ejecutar bloque)
- Gestores de finalizacin (cuando termines de hacer una tarea, ejecutar
bloque)
- Animacin de vistas
- Para multitarea mediante Grand Dispatch Central

6.Keeping code compact with blocks


- Vamos a ver un ejemplo de uso de bloques en una notificacin
- En nuestro ejemplo vamos a hacer que cuando el dispositivo rote todas
las lineas se pongan rojas
- Aadimos la siguiente notificacin al mtodo initWithCoder de
TouchDrawView.m
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserverForName:UIDeviceOrientationDidChangeNotification
object:nil
queue:nil
usingBlock:
^(NSNotification *note) {
[self transformLineColorsWithBlock:
^(Line *l) {
return [UIColor redColor];
}];
}];

7.Categories
- Crear una categora consiste en coger una clase existente y aadirle
mtodos que despus podrn ser utilizables sin tener que hacer
subclassing
- En nuestro ejemplo crearemos una clase de tipo NSObject y la llamaremos
UIColor+Inverse
UIColor+Inverse.h :
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface UIColor (Inverse)
-(UIColor*)colorInvertido;
@end

7.Categories
UIColor+Inverse.m :
#import "UIColor+Inverse.h"
@implementation UIColor (Inverse)
-(UIColor*)colorInvertido{
CGColorRef cgCLR = [self CGColor];
const CGFloat *components = CGColorGetComponents(cgCLR);
float r = 1.0 - components[0];
float g = 1.0 - components[1];
float b = 1.0 - components[2];
UIColor *colorInvertido = [UIColor colorWithRed:r
green:g
blue:b
alpha:1.0];
return colorInvertido;
}
@end

7.Categories
- Para usarlo en nuestro ejemplo, en TouchDrawView.m importaremos la
cabecera UIColor+Inverse.h
- Ya podemos usar el mtodo colorInvertido con cualquier instancia de
UIColor
- Modifiquemos el ejemplo anterior, para que el mtodo
transformLineColorsWithBlock invierta el color devuelto por el
bloque colorear antes de asignarlo al color de la linea
-(void)transformLineColorsWithBlock:(UIColor* (^)(Line*))color{
for (Line *l in lines) {
UIColor *c = color(l);
[l setColor:[c colorInvertido]];
}
[self setNeedsDisplay];
}

8.Memory Managment and Blocks


- Los bloques en Cocoa son objetos aunque algo limitados. Se pueden
enviar los siguientes mensajes a los bloques:
- copy
- retain
- release
- autorelease
Por defecto los bloques reservan memoria automticamente cuando se
crean y son destruidos cuando la funcin que los crea se completa.

9.Pros and Cons of Callback Options


- Pros:
- Cdigo ms compacto
- Necesario conocerlos mtodos predefinidos en su uso con Grand
Dispatch Central (GCD) o para pasar como criterio de comparacin
en una ordenacin por ejemplo.
- tiles en algunas circunstancias especiales. Por ejemplo como los
bloques retienen en memoria los objetos que usan durante su ejecucin, si
un bloque se pasa como fragmento de cdigo a usar al terminar una
determinada accin nos garantizamos de que todos los objetos que van a
ser usados permanecen en memoria hasta que se complete esta accin.
- Contras:
- Sintaxis compleja
- Difciles de usar

23.Web Services and


UIWebView

1.Web Services
- Cualquier navegador de internet utiliza el protocolo HTTP para
comunicarse con un servicio web.
- La interaccin ms simple consiste en que el cliente enva una
peticin sobre una URL especfica al servidor y este le responde
enviando el contenido de la pgina que se ha solicitado.
- Para interacciones ms complejas el navegador puede incluir
parmetros en su peticin. Estos parmetros son procesados por el
servidor para enviar el contenido de una pgina dinmicamente
construida con respecto a esos parmetros.
- Usar un servicio web desde una aplicacin iOS requiere los siguientes
pasos:
- Formatear los datos para enviar como XML o JSON
- Enviar los datos en una peticin HTTP
- Recibir la respuesta HTTP
- Parsear y procesar el los datos recibidos como XML o JSON

2.Starting the Nerdfeed application

- Lector RSS
- Una lista con noticias RSS obtenidas
de un servidor.
- Tocando sobre cada una de esos
elementos podremos ver la noticia

2.Starting the Nerdfeed application

- Crear proyecto de tipo Empty Application


- Aadir una nueva clase de tipo NSObject y cambiar su padre para que
herede de UITableViewController
- Aadir a este fichero mtodos requeridos de data source
- En AppDelegate.m crear una instancia de ListViewController y asignarla
como root view controller de un navigation controller.
- Hacer el navigation controller el root view controller de window

2.Starting the Nerdfeed application


- En AppDeletage.m en el mtodo didFinishLaunchingWithOptions
aadiremos
//Instanciar controllador ListViewController
ListViewController *lvc =
[[ListViewController alloc] initWithStyle:UITableViewStylePlain];
[lvc autorelease];
//Instanciar controlador de navegacin
UINavigationController *masterNav =
[[UINavigationController alloc] initWithRootViewController:lvc];
[masterNav autorelease];
//Asignar como rootViewController el control de navegacin
[[self window] setRootViewController:masterNav];

- Con eso tendremos nuestro UITableView en pantalla, pero est vaco

3.Fetching data from a URL


- 1. Crear contenedor de datos
- 2. Iniciar conexin
- 3. Recoger datos con los mtodos delegados
- Para crear nuestro contenedor de datos:
ListViewController.h
NSMutableData *responseData;
ListViewController.m : Instanciarlo Antes de usarlo
responseData = [[NSMutableData data] retain];

4.Working with NSURLConnection


- Iniciaremos la conexin
responseData = [[NSMutableData data] retain];
NSURL *baseURL = [[NSURL URLWithString:@"http://www.atomicflavor.com/feed/"] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:baseURL];
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];

- Asignamos nuestro controlador como delegate de la conexin


- Despus debemos implementar una serie de mtodos en nuestro
controlador para que se vayan recibiendo los datos
-

(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response


(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
(void)connectionDidFinishLoading:(NSURLConnection *)connection

4.Working with NSURLConnection


- Mtodos a implementar
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(@"No se pudo descargar el XML");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
! //Realizar parseo
}

5.Parsing XML
- Veamos un fragmento de lo que contiene un fichero XML y lo que vamos a
parsear

<item>
<title>Entrevista a Atomic Flavor en Baquia TV</title>
<link>
http://www.atomicflavor.com/entrevista-a-atomic-flavor-en-baquia-tv/
</link>
<comments>
http://www.atomicflavor.com/entrevista-a-atomic-flavor-en-baquia-tv/
#comments
</comments>
<pubDate>Wed, 15 Jun 2011 09:28:48 +0000</pubDate>

- Vamos a usar NSXMLParser, que es la librera incluida por defecto en el


SDK de iOS

5.Parsing XML
- 1. Implementar el protocolo NSXMLParserDelegate
- 2. Declarar cadenas del XML
- 3. Sobreescribir los mtodos de parseo
- 4. Invocar comienzo de parseo

5.Parsing XML
- 1. Declarar cadenas de parseo
NSXMLParser * rssParser;
NSMutableData *responseData;
NSMutableArray *items;!
NSMutableDictionary * item;!
NSString * currentElement;
NSMutableString
NSMutableString
NSMutableString
NSMutableString

*
*
*
*

currentTitle;
currentDate;
currentSummary;
currentLink;

5.Parsing XML
- 2. Iniciar parseo
! NSString *str = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding];
! NSData *data= [str dataUsingEncoding:NSUTF8StringEncoding];
items = [[NSMutableArray alloc] init];
!
!
!
!
!
!
!

rssParser = [[[NSXMLParser alloc] initWithData:data] autorelease];


[rssParser setDelegate:self];
[rssParser setShouldProcessNamespaces:NO];
[rssParser setShouldReportNamespacePrefixes:NO];
[rssParser setShouldResolveExternalEntities:NO];
[rssParser parse];!

5.Parsing XML
- 3. Sobreescribir mtodos del delegado NSXMLParserDelegate:
- 3.1 Empieza parseo de elemento
- 3.2 Encontrada cadena
- 3.4 Termina parseo de elemento
- 3.5 Terminado de parsear

5.Parsing XML
- 3.1 Empieza parseo de elemento
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString
*)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName attributes:(NSDictionary *)attributeDict
{
! currentElement = [elementName copy];
!
! if ([elementName isEqualToString:@"item"])
! {
! !
item = [[NSMutableDictionary alloc] init];
! !
currentTitle = [[NSMutableString alloc] init];
! !
currentDate = [[NSMutableString alloc] init];
! !
currentSummary = [[NSMutableString alloc] init];
! !
currentLink = [[NSMutableString alloc] init];
! }
}

5.Parsing XML
- 3.2 Encontrada cadena
!
!
!
!
!
!
!
}

(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{


if ([currentElement isEqualToString:@"title"]) {
!
[currentTitle appendString:string];
} else if ([currentElement isEqualToString:@"link"]) {
!
[currentLink appendString:string];
} else if ([currentElement isEqualToString:@"pubDate"]) {
!
[currentDate appendString:string];
}

5.Parsing XML
- 3.4 Termina parseo de elemento
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString
*)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:
(NSString *)qName{
! if ([elementName isEqualToString:@"item"]) {
! !
[item setObject:currentTitle forKey:@"title"];
! !
[item setObject:currentLink forKey:@"link"];
! !
[item setObject:currentDate forKey:@"pubDate"];
! !
[items addObject:[item copy]];
! }
}

5.Parsing XML
- 3.5 Terminado de parsear
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError
*)parseError {
! NSLog(@"No se pudo parsear el XML");
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
! [[self tableView] reloadData];
}

5.Parsing XML
- Por ltimo modificamos los mtodos de nuestro ListViewController
para que muestren la lista de elementos recuperados
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section{
return [items count];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"UITableViewCell"] autorelease];
}
NSMutableDictionary *i = [items objectAtIndex:indexPath.row];
[[cell textLabel] setText:[i objectForKey:@"title"]];
return cell;
}

5.Parsing XML
- Tambin crearemos un mtodo para que podamos invocar el comienzo
del parseo desde AppDelegate
-(void)comenzarConexion{
responseData = [[NSMutableData data] retain];
NSURL *baseURL = [[NSURL URLWithString:@"http://www.atomicflavor.com/
feed/"] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:baseURL];
[[[NSURLConnection alloc] initWithRequest:request delegate:self]
autorelease];
}

6.A quick tip on logging


- En este ejercicio veremos como se imprime mucha informacin en la
consola de depuracin sobre todo el contenido que recibimos y enviamos
- Lo que vamos a hacer es crear diferentes etiquetas para NSLog en
nuestro fichero Nerdfeed_Prefix.pch que es donde importamos las libreras
del precompilador
#define WSLog NSLog
#define OSLog NSLog
- Cada vez que queramos imprimir informacin relaccionada con los
webservices usaremos WSLog en lugar de NSLog. Para el resto de
informacin usaremos OSLog.
- Despus cuando queramos que la informacin de los webservices no se
imprima deberemos redefinir la etiqueta en nuestra clase:
#define WSLog

7.UIWebView
- Creamos una nueva clase de tipo NSObject y le cambiamos el padre para
que herede de UIViewController
- UIViewController.h :
#import <Foundation/Foundation.h>
@interface WebViewController : UIViewController {
}
@property (nonatomic,readonly) UIWebView *webView;
@end

7.UIWebView
- UIViewController.m :
#import "WebViewController.h"
@implementation WebViewController
@synthesize webView;
- (void) loadView{
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
[wv setScalesPageToFit:YES];
[self setView:wv];
[wv release];
}
-(UIWebView*)webView {
return (UIWebView*)[self view];
}
@end

7.UIWebView
- Crear una propiedad en ListViewController para apuntar a
WebViewController
WebViewController *webViewController;
@property(nonatomic,retain) WebViewController *webViewController;
@synthesize webViewController;

- Instanciarlo desde el AppDelegate

7.UIWebView
- Mtodo para cuando seleccionemos alguna fila de ListViewController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//Desplazar la vista actual a webViewController
[[self navigationController] pushViewController:webViewController animated:YES];
//Obtener el elemento
NSMutableDictionary *i = [items objectAtIndex:indexPath.row];

!
!

//Limpiar cadena de parsitos finales


NSString *cadenaURL = [i objectForKey:@"link"];
WSLog(@"[cadena =%@]",cadenaURL);
cadenaURL = [cadenaURL substringToIndex:[cadenaURL length]-1];
cadenaURL = [cadenaURL stringByReplacingOccurrencesOfString:@" " withString:@""];
cadenaURL = [cadenaURL stringByReplacingOccurrencesOfString:@"\n" withString:@""];
WSLog(@"[cadena =%@]",cadenaURL);
//Crear NSURL
NSURL *url = [NSURL URLWithString:cadenaURL];
//Crear peticin con esa URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
//Decirle a webviewcontroller que cargue esa peticin
[[webViewController webView] loadRequest:req];
//Poner como ttulo del control de navegacin el ttulo de la noticia
[[webViewController navigationItem] setTitle:[i objectForKey:@"title"]];

8.NSXMLParser
- En este ejercicio hemos utilizado NSXMLParser que es el parseador
disponible por defecto en la api del SDK de iOS.
- En internet podremos encontrar otras libreras de terceros que
tambin podremos usar para parsear fichero XML sustituyendo a
NSXMLParser
- Algunas de las libreras de terceros que podremos encontrar disponibles son:
- libxml2
- TBXML
- TouchXML
- KissXML
- TinyXML
- GDataXML

9.The Request Body

- Veamos como es en detalle cada una de las peticiones que realiza nuestro
programa.
- Hay tres partes, la linea de peticin, las cabeceras HTTP y el cuerpo
HTTP

10.Credentials
- Cuando se accede a un servicio web, hay veces que es necesario
identificarse para poder trabajar con dicho servicio.
- (void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
// Se ha fallado 2 veces
if ([challenge previousFailureCount] > 1)
{
//Dar mensaje de aviso
}
else
{
// Responder
NSURLCredential *cred = [[[NSURLCredential alloc]
initWithUser:@"user"
password:@"pass"
persistence:NSURLCredentialPersistenceForSession] autorelease];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
}
}

11.More Data
- Vamos a crear una clase CustomCell que sea subclase de
UTTableViewCell que tenga varios labels, uno para el ttulo y otro para
la fecha.
CustomCell.h:
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell {
UILabel *titulo;
UILabel *hora;
}
@property(nonatomic,retain) UILabel *titulo;
@property(nonatomic,retain) UILabel *hora;
@end

11.More Data
- Mtodo constructor
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString
*)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//Instanciamos los labels
titulo = [[UILabel alloc] initWithFrame:CGRectZero];
hora = [[UILabel alloc] initWithFrame:CGRectZero];
[titulo setBackgroundColor:[UIColor clearColor]];
[hora setBackgroundColor:[UIColor clearColor]];
//Los aadimos a el contenido de la vista
[[self contentView] addSubview:titulo];
[[self contentView] addSubview:hora];
//Liberamos
[titulo release];
[hora release];
}
return self;
}

11.More Data
- Colocacin de SubVistas
-(void)layoutSubviews{
[super layoutSubviews];
CGRect bounds = [[self contentView] bounds];
float inset = 5.0;
float w = bounds.size.width;
float h = bounds.size.height;
CGRect titleFrame = CGRectMake(inset,inset, w, (h/2));
CGRect hourFrame = CGRectMake(inset,inset+h/2, w, (h/2));
[titulo setFrame:titleFrame];
[hora setFrame:hourFrame];
}

11.More Data
- Modificar cellForRowAtIndexPath de ListViewController.m
-(UITableViewCell*)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomCell *cell = (CustomCell*)[tableView
dequeueReusableCellWithIdentifier:@"CustomCell"];
if (cell == nil) {
cell = [[[CustomCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CustomCell"]
autorelease];
}
NSMutableDictionary *i = [items objectAtIndex:indexPath.row];
[[cell titulo] setText:[i objectForKey:@"title"]];
[[cell hora] setText:[i objectForKey:@"pubDate"]];
return cell;
}

12.More UIWebView
- Aadir UIActivityIndicatorView a nuestra clase
WebViewController en el centro de la pantalla
- Hay que implementar UIWebViewDelegate en nuestro controlador
- Vamos a sobreescribir los mtodos de UIWebViewDelegate:
- Cuando la noticia empiece a cargar en el centro de la pantalla deberemos
ver un UIActivityIndicatorView con su animacin activada
- Cuando la noticia se haya terminado la carga, el UIActivityIndicatorView
desaparecer

12.More UIWebView
- Cambios sobre loadView
- (void) loadView{
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
[wv setScalesPageToFit:YES];
[wv setDelegate:self];
activityIndicator = [[UIActivityIndicatorView alloc] init];
[activityIndicator setHidesWhenStopped:TRUE];
[activityIndicator stopAnimating];
[activityIndicator setBackgroundColor:[UIColor clearColor]];
[activityIndicator setColor:[UIColor blackColor]];
[self setView:wv];
[self.view addSubview:activityIndicator];
[activityIndicator setCenter:CGPointMake(self.view.bounds.size.width/
2, self.view.bounds.size.height/2)];
[activityIndicator release];
[wv release];
}

12.More UIWebView
- Mtodos de UIWebViewDelegate:
- (void)webViewDidStartLoad:(UIWebView *)webView{
! [activityIndicator startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
[activityIndicator stopAnimating];
}

24.UISplitViewController

1.Splitting Up Nerdfeed
- Tanto iPhone como iPod Touch tienen un tamao de pantalla bastante
limitado, por eso la manera usual de presentar las vistas es mediante un
UINavigationController.
- En cambio, el iPad tiene una pantalla mucho mayor y puede utilizar clases
predefinidas como UISplitViewController que slo estn disponible
para iPad.
- Para trabajar con UISplitViewController debemos tener dos
controladores, el master y el detail.
- El controlador master ocupar poco en la pantalla y ser una lista que
nos permita elegir que contenido visualizar
- El controlador detail ocupar la mayor parte de la pantalla y mostrar en
detalle el contenido seleccionado en el master

1.Splitting Up Nerdfeed

- Aadiremos un UISplitViewController
a nuestro ejemplo Nerdfeed

1.Splitting Up Nerdfeed
- Partimos de el proyecto anterior
- Realizamos cambios en AppDelegate para instanciar el
UISplitViewController en caso de estar ejecutando el programa en un
iPad
- Configuramos los controladores para que soporten cambios a
orientacin horizontal si el programa se esta ejecutando en un iPad

1.Splitting Up Nerdfeed
- Modificamos el mtodo didFinishLaunchingWithOptions del
fichero AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
autorelease];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
//Instanciar controllador ListViewController
ListViewController *lvc = [[ListViewController alloc]
initWithStyle:UITableViewStylePlain];
[lvc autorelease];
//Instanciar controlador de navegacion
UINavigationController *masterNav = [[UINavigationController alloc]
initWithRootViewController:lvc];
[masterNav autorelease];
WebViewController *wvc = [[[WebViewController alloc] init] autorelease];
[lvc setWebViewController:wvc];
...

1.Splitting Up Nerdfeed
....
if ([[UIDevice currentDevice] userInterfaceIdiom] ==UIUserInterfaceIdiomPad){
//El detalle debe ir en un navigation controller
UINavigationController *detailNav = [[UINavigationController alloc]
initWithRootViewController:wvc];
[detailNav autorelease];
NSArray *vcs = [NSArray arrayWithObjects:masterNav,detailNav, nil];
UISplitViewController *svc = [[[UISplitViewController alloc] init] autorelease];
[svc setDelegate:wvc];
[svc setViewControllers:vcs];
[[self window] setRootViewController:svc];
} else {
//Asignar como rootViewController el control de navegacin
[[self window] setRootViewController:masterNav];
}
[lvc comenzarConexion];
[self.window makeKeyAndVisible];
return YES;
}

1.Splitting Up Nerdfeed
- Aadir el mtodo shouldAutorotateToInterfaceOrientation a
ListViewController.m y WebViewController.m para que la app
soporte orientacin horizontal
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] ==UIUserInterfaceIdiomPad){
return YES;
} else {
return interfaceOrientation == UIInterfaceOrientationPortrait;
}
}

- Solo se realizar el cambio a horizontal en iPad

2.Master-Detail Communication
- Como desde ListViewController tenemos un puntero hacia
WebViewController, podremos seguir indicando a este controlador la
pgina que debe cargar
- Por lo general en el master siempre tendremos un puntero hacia el
detalle para modificar el contenido
- En el caso de estar disponible un splitViewController tendremos
quemodificar la forma de presentar el contenido cuando se seleccione
un elemento de la lista. Para ello realizaremos el siguiente cambio en
didSelectRowAtIndexPath:
if (![self splitViewController]) {
[[self navigationController] pushViewController:webViewController animated:YES];
}

3.Displaying the Master View Controller in Portrait Mode


- Hacemos que nuestro WebViewController implemente
UISplitViewControllerDelegate y sobreescribimos los siguientes
mtodos
- (void)splitViewController:(UISplitViewController*)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem*)barButtonItem
forPopoverController:(UIPopoverController*)pc
{
[barButtonItem setTitle:@"Lista"];
self.navigationItem.leftBarButtonItem = barButtonItem;
}
- (void)splitViewController:(UISplitViewController*)svc
willShowViewController:(UIViewController *)aViewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
self.navigationItem.leftBarButtonItem = nil;
}

4.Universalizing Nerdfeed

- Ahora podemos probar con los diferentes simuladores de iPhone o


iPad para ver como la aplicacin se comporta de forma diferente.

25.Media Playback and


Background Execution

1.Creating the MediaPlayer Application


- Muchas aplicaciones necesitan reproducir audio o video
- En este tema aprenderemos a utilizar la forma mas comn de reproducir
contenido de vdeo y audio utilizando las rutinas que nos ofrece la SDK
de iOS
- Tambin aprenderemos ms sobre multitarea y ejecucin en
segundo plano

1.Creating the MediaPlayer Application

- Aplicacin multimedia
- Reproducir fichero de audio
- Reproducir un sonido del sistema
corto
- Reproducir fichero de video

1.Creating the MediaPlayer Application


- Crear proyecto de tipo Single View Application
- Creamos 3 botones en ViewController.xib y sus correspondientes mtodos
que enlazaremos a estos botones
- Programamos el mtodo para cada uno de los botones

2.System Sounds
- Los llamados sonidos del sistema son sonidos cortos sin comprimir que
se utilizan tpicamente en las interfaces o cuando el usuario realiza alguna
accin
- El framework Auditoolbox nos permite registrar una serie de sonidos en
el servidor de sonidos del sistema. Estos sonidos deben ser:
- Menores a 30 segundos de duracin
- Estar empaquetados en formato PCM o IMA4
- Ser de uno de los siguientes tipos: CAF, WAV o AIFF
- Como pasar de mp3 a caf :
afconvert -f caff -d LEI16@44100 -c 1 sound.mp3 sound.caf

2.System Sounds
- Importar framework de AudioToolbox
- Aadir objeto de tipo SystemSoundID
ViewController.h :
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
@interface ViewController : UIViewController {
SystemSoundID sonidoCorto;
}
-(IBAction)reproducirAudio:(id)sender;
-(IBAction)reproducirSonidoCortoSistema:(id)sender;
-(IBAction)reproducirVideo:(id)sender;
@end

3.Registering system sounds


- Cargamos el sonido en viewDidLoad de ViewController.m
//Puntero a su ruta
NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"caf"];
if (soundPath) {
//Creamos un NSURL y lo cargamos en sonidoCorto
NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &sonidoCorto);
}

4.Playing system sounds


- Para reproducir el sonido
-(IBAction)reproducirSonidoCortoSistema:(id)sender{
AudioServicesPlaySystemSound(sonidoCorto);
}

- Para reproducir el sonido y que vibre el dispositivo


-(IBAction)reproducirSonidoCortoSistema:(id)sender{
AudioServicesPlaySystemSound(sonidoCorto);
AudioServicesPlayAlertSound(sonidoCorto);
}

- Descargar sonido
AudioServicesDisposeSystemSoundID(sonidoCorto);

5.Compressed Audio Files


- Para reproducir sonidos comprimidos de ms de 30 segundos usaremos
AVAudioPlayer
- Primero importamos el framework AVFoundation y creamos un
puntero de tipo AVAudioPlayer
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
@interface ViewController : UIViewController {
SystemSoundID sonidoCorto;
AVAudioPlayer *musica;
}
-(IBAction)reproducirAudio:(id)sender;
-(IBAction)reproducirSonidoCortoSistema:(id)sender;
-(IBAction)reproducirVideo:(id)sender;
@end

5.Compressed Audio Files


- Cargamos la cancin en viewDidLoad de ViewController.m
NSString *musicPath = [[NSBundle mainBundle] pathForResource:@"music"
ofType:@"mp3"];
if (musicPath) {
//Creamos un NSURL y lo cargamos en musica
NSURL *musicURL = [NSURL fileURLWithPath:musicPath];
musica = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:nil];
[musica setDelegate:self];
}

- Implementamos en ViewController el delegado


AVAudioPlayerDelegate para poder capturar eventos

5.Compressed Audio Files


- Reproducimos la cancin
-(IBAction)reproducirAudio:(id)sender{
if ([musica isPlaying]) {
[musica stop];
[sender setTitle:@"Reproducir msica" forState:UIControlStateNormal];
} else {
[musica play];
[sender setTitle:@"Parar msica" forState:UIControlStateNormal];
}
}

5.Compressed Audio Files


- Si queremos hacer cosas ms avanzadas con AVAudioPlayer
sobreescribimos los mtodos de su delegado
-(void)audioPlayerEndInterruption:(AVAudioPlayer *)player
{
[musica play];
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
NSLog(@"Reproduccin terminada");
}

6.Playing Movie Files


- MPMovieplayerController es el responsable de reproducir vdeos en
iOS.
- La aplicacin de YouTube y de Vdeos utilizan esta misma clase para
reproducir vdeos
- Solo reproduce vdeos en dos formatos:
- H264 (Baseline Profile Level 3.0)
- MPEG-4 Part2 video (Simple Profile)
- Para codificar cualquier video en estos formatos podemos utilizar iTunes.
Seleccionando un vdeo y desde el men avanzado.
- Tambin podemos utilizar programas de terceros que nos permitan
realizar este tipo de conversiones

6.Playing Movie Files


- Importar framework de MediaPlayer
- Aadir objeto de tipo MPMoviePlayerController
ViewController.h :
#import
#import
#import
#import

<UIKit/UIKit.h>
<AudioToolbox/AudioToolbox.h>
<AVFoundation/AVFoundation.h>
<MediaPlayer/MediaPlayer.h>

@interface ViewController : UIViewController<AVAudioPlayerDelegate> {


SystemSoundID sonidoCorto;
AVAudioPlayer *musica;
MPMoviePlayerController *video;
}
-(IBAction)reproducirAudio:(id)sender;
-(IBAction)reproducirSonidoCortoSistema:(id)sender;
-(IBAction)reproducirVideo:(id)sender;
@end

6.Playing Movie Files


- Cargamos el video en viewDidLoad de ViewController.m
NSString *moviePath = [[NSBundle mainBundle] pathForResource:@"video" ofType:@"m4v"];
if (moviePath) {
//Creamos un NSURL y lo cargamos en musica
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
video = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
[self.view addSubview:video.view];
float h = self.view.bounds.size.height/2;
float w = self.view.bounds.size.width;
[video.view setFrame:CGRectMake(0, h, w, h)];
}

- Y lo reproducimos
-(IBAction)reproducirVideo:(id)sender{
[video play];
}

7.MPMoviePlayerViewController
- Si queremos presentar un vdeo en pantalla completa usaremos la clase
MPMoviePlayerViewController y despus lanzaremos su
presentacin
MPMoviePlayerViewController *playerViewController =
[[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:playerViewController];

8.Preloading video
- Cuando iniciamos la carga de un vdeo no est disponible de manera
inmediata. Mas an si lo cargamos en streaming desde un servidor
- Podemos aadir a nuestro objeto de vdeo una notificacin apuntando a
un mtodo para que sea llamado cuando el vdeo se haya terminado de
cargar completamente.
NSString *moviePath = [[NSBundle mainBundle] pathForResource:@"video" ofType:@"m4v"];
if (moviePath) {
//Creamos un NSURL y lo cargamos en musica
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
video = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(displayPreloadedVideo:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:video];
}

8.Preloading video
- El mtodo que aadimos para atender a esa notificacin
-(void)displayPreloadedVideo:(NSNotification*)note{
[self.view addSubview:video.view];
float h = self.view.bounds.size.height/2;
float w = self.view.bounds.size.width;
[video.view setFrame:CGRectMake(0, h, w, h)];
}

9.Background Processes
- Una aplicacin puede reproducir audio incluso si no es la aplicacin activa.
- Para configurar este tipo de proceso de segundo plano debemos aadir a el
fichero Info.plist de nuestro proyecto el correspondiente modo de
background. Par a ello aadimos un campo ms con el valor
UIBackgroundModes. La clave que corresponde con la reproduccin de
audio en segundo plano es App plays audio

9.Background Processes
- Para que la aplicacin pueda reproducir audio en segundo plano deberemos
cambiar la categora de AVAudioSession.
- La categora que permite reproducir audio en segundo plano es
AVAudioSessionCategoryPlayback
NSString *musicPath = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
if (musicPath) {
//Creamos un NSURL y lo cargamos en musica
NSURL *musicURL = [NSURL fileURLWithPath:musicPath];
//Cambiamos la categoria para reproducir audio en segundo plano
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
musica = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:nil];
[musica setDelegate:self];
}

10.Guidelines for background execution


- Hay algunas reglas que Apple nos dice que debemos de seguir en el caso de
las aplicaciones que tienen ejecucin en segundo plano. Algunas de estas son:
- No uses OpenGL ES, el sistema operativo termina el proceso por la
elevada carga
- No actualices tus vistas, el usuario no puede verlas
- Libera recursos cuando se produzca una llamada de low-memory
warning

11.Other forms of background execution


- Adems de la reproduccin de audio en segundo plano hay otros dos
modos de ejecucin:
- VOIP (Voice over internet protocol)
- Registers for location updates

12.Low-level APIs
- En este tema hemos visto la forma ms sencilla de reproducir vdeo y
audio utilizando la API de alto nivel
- Si queremos hacer cosas ms avanzadas como recodificar, aplicar filtros,
efectos o lo que necesitemos deberemos utilizar las APIs de bajo nivel
- Usaremos AudioToolbox y CoreAudio para los sonidos
- Usaremos CoreVideo para el vdeo

13.Audio Recording
- Podemos grabar audio utilizando la clase AVAudioRecorder
- Vamos a modificar nuestro ejemplo para aadir:
- Un botn grabar que nos permita grabar
- Un botn play que reproduzca el ltimo archivo grabado

13.Audio Recording
- Punteros necesarios
AVAudioPlayer *grabadoPlayer;
AVAudioRecorder *grabadoRecorder;
bool grabando;

-(IBAction)grabar:(id)sender;
-(IBAction)reproducir:(id)sender;

13.Audio Recording
-(IBAction)grabar:(id)sender{
if (!grabando) {
//Settings de grabar
NSMutableDictionary *recordSettings
[recordSettings setObject:[NSNumber
[recordSettings setObject:[NSNumber
[recordSettings setObject:[NSNumber
[recordSettings setObject:[NSNumber
[recordSettings setObject:[NSNumber
[recordSettings setObject:[NSNumber

= [[NSMutableDictionary alloc] initWithCapacity:10];


numberWithInt: kAudioFormatLinearPCM] forKey: AVFormatIDKey];
numberWithFloat:44100.0] forKey: AVSampleRateKey];
numberWithInt:2] forKey:AVNumberOfChannelsKey];
numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];

//Ponemos la sesion en modo grabacin


AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *recDir = [[paths objectAtIndex:0] stringByAppendingFormat:@"/%@", @"fichero"];
NSURL *url = [NSURL fileURLWithPath:recDir];
if (grabadoRecorder!=nil) {
[grabadoRecorder stop];
[grabadoRecorder release];
}
grabadoRecorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:nil];

if ([grabadoRecorder prepareToRecord] == YES) {


grabando=true;
[sender setTitle:@"Parar grabacin" forState:UIControlStateNormal];
[grabadoRecorder record];
}
} else {
grabando=false;
[sender setTitle:@"Grabar" forState:UIControlStateNormal];
[grabadoRecorder stop];
}

13.Audio Recording
- Mtodo de reproduccin
-(IBAction)reproducir:(id)sender{
//Ponemos la sesion en modo reproduccin
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *recDir = [[paths objectAtIndex:0] stringByAppendingFormat:@"/%@", @"fichero"];
NSURL *url = [NSURL fileURLWithPath:recDir];
if (grabadoPlayer!=nil) {
[grabadoPlayer stop];
[grabadoPlayer release];
}
grabadoPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[grabadoPlayer play];
}

26.Push Notifications and


Networking

1.Push Notifications
- Push Notifications, mecanismo para enviar notificaciones a los
usuarios que tengan instalada nuestra aplicacin
- Podemos mostrar un mensaje corto
- Podemos reproducir un sonido
- Podemos cambiar el badge de el icono de la aplicacin

1.Push Notifications
- Esquema de Push Notification

2.Anatomy of a Push Notification


- Una notificacin bsica
{
"aps":
{
"alert": "Hello, world!",
"sound": "default"
}
}

- Configurando tambin el botn de abrir la notificacin


{

"aps":
{
"alert":
{
"action-loc-key": "Open",
"body": "Hello, world!"
},
"badge": 2
}

- Como lo usaremos
{"aps":{"alert":"Hello, world!","sound":"default"}}

3.Provisioning Profiles
- Para habilitar push notifications en tus aplicaciones, necesitan ser
firmadas con un provisioning profile que est configurado para push.
- Tu servidor necesita firmar las comunicaciones con los servidores
APNS mediante un certificado SSL
- Hay dos tipos de push server certificates:
- Development
- Production

4. Generating the Certificate Signing Request (CSR)


- Abrir keychain
- Solicitar un certificado para una autoridad de certificacin

4. Generating the Certificate Signing Request (CSR)

4. Generating the Certificate Signing Request (CSR)

4. Generating the Certificate Signing Request (CSR)

5. Making App ID and SSL Certificate

5. Making App ID and SSL Certificate

5. Making App ID and SSL Certificate

5. Making App ID and SSL Certificate

5. Making App ID and SSL Certificate


- Una vez descargado el certificado.cer hacer doble click y instalarlo
- Despus abriremos de nuevo KeyChain, buscamos el certificado y le damos
a detalle
- Veremos los dos, el certificado y la clave privada
- Seleccionar los dos y exportamos como un fichero.p12

5. Making App ID and SSL Certificate

5. Making App ID and SSL Certificate


- Convertimos el certificado en un fichero .pem
openssl pkcs12 -in Certificado.p12 -out Certificado.pem -nodes

6. Simple PHP Server


- Subimos los ficheros:
- ck.pem generado
- simplepush.php
- Tendr acceso desde:
http://www.atomicflavor.com/PushNotification/simplepush.php

7. Simplepush.php
<?php
// Put your device token here (without spaces):
$deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78';
// Put your private key's passphrase here:
$passphrase = 'curso';
// Put your alert message here:
$message = 'My first push notification!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'Certificado.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
!
'ssl://gateway.sandbox.push.apple.com:2195', $err,
!
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
!

exit("Failed to connect: $err $errstr" . PHP_EOL);

echo 'Connected to APNS' . PHP_EOL;


// Create the payload body
$body['aps'] = array(
!
'alert' => $message,
!
'sound' => 'default'
!
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
!
echo 'Message not delivered' . PHP_EOL;
else
!
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);

8. Simple iPhone Client


- Nueva single view application
- Hacemos que la app se registre para recibir push notifications
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
!
self.window.rootViewController = self.viewController;
!
[self.window makeKeyAndVisible];

!
// Let the device know we want to receive push notifications
!
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
!
!
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

return YES;
}

8. Simple iPhone Client


- Nueva single view application
- Hacemos que la app se registre para recibir push notifications
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
!
self.window.rootViewController = self.viewController;
!
[self.window makeKeyAndVisible];

!
// Let the device know we want to receive push notifications
!
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
!
!
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

return YES;
}

8. Simple iPhone Client


- Nueva single view application
- Hacemos que la app se registre para recibir push notifications
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
!
self.window.rootViewController = self.viewController;
!
[self.window makeKeyAndVisible];

!
// Para que el dispositivo reciba push notifications
!
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
!
!
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

return YES;
}

8. Simple iPhone Client


- Nos hacen falta algunos mtodos ms
- (void)application:(UIApplication*)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
! NSLog(@"My token is: %@", deviceToken);
}
- (void)application:(UIApplication*)application
didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
! NSLog(@"Failed to get token, error: %@", error);
}

9. Create Provisioning Profile


- Ahora vamos a crear el provisioning profile y a instalarlo en el XCode
- A continuacin podremos ejecutar nuestra app en el dispositivo
- Vemos el token del dispositivo y modificamos el php del servidor para
que la notificacin se enve a ese dispositivo
- Ya podemos enviar nuestra primera push notification desde el servidor
y recibirla en el dispositivo

COMO CONTINUO EL CAMINO


PARA CONVERTIRME EN UN
PROGRAMADOR NINJA?

Objective C
Cocoa
Quartz

HTML5
Javascript
CSS

OpenGL ES 1.5
OpenGL ES 2.0
GLSL

PHP
MySQL
SQLite

LIBROS RECOMENDADOS
EDITORIAL APRESS

CONTACTO

Miguel Jos Garca Corchero


miguel@atomicflavor.com
twitter: @miguelgarciacor
http://www.atomicflavorgames.com
http://www.atomicflavor.com

You might also like