Curs de desenvolupament d'iOS - Part 2/5

Page 1

Curs de programació d’iOS Novembre de 2011

Organitza


3 Introducció a l’Objective-C • Les aplicacions per iOS es desenvolupen en llenguatge Objective-C • És una extensió simplificada del C • Programació orientada a objectes

• L’SDK es compon d’un conjunt de Frameworks • Tot el conjunt s’anomena Cocoa • En els dispositius tàctils s’empra Cocoa Touch


• Hi ha més de 3000 mètodes i 200 classes disponibles. • En cada nova actualització de l’iOS Apple afegeix noves classes i mètodes. • Cal emprar constantment els exemples i la documentació de referència d’Apple. • http://developer.apple.com/library/ios/navigation/


Frameworks • Un framework és un conjunt de classes relacionades entre si que realitzen tasques similars • Només cal importar al nostre projecte els frameworks necessaris • Per exemple, el framework UIKit s’empra en tots els projectes per iPhone/iPad ja que conté totes les classes relatives a la interfície d’usuari • UIButton, UILabel, UIImageView, UIView, UIScrollView, UISegmentedControl, UISlider, UITextField, UISwitch,... • Etc...


Frameworks


Frameworks


Frameworks


Frameworks • Foundation: Tipus primitius de dades, etc... http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Fou ndation/ObjC_classic/_index.html

• UIKit: Classes de la UI http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Fr amework/_index.html

• CoreGraphics: Motor de renderitzat de la UI http://developer.apple.com/library/ios/#documentation/coregraphics/reference/ coregraphics_framework/_index.html


Frameworks •CoreLocation: GPS/Brúixola/Geolocalització •MapKit: Integració de mapes •CFNetwork: Comunicació/Sockets •AddressBook: Accés agenda de contactes •MediaPlayer: Player de video/audio/streaming? •CoreBluetooth: Ús bluetooth •AudioToolbox: Manipulació d’audio •iAd: Integració publicitat iAd d’Apple •Etc...


Classes • Ens permeten definir tipus d’objectes. • Quan creem un objecte tenim una instància d’aquella classe. • Les classes tenen atributs i mètodes. • Els objectes tenen el seu propi cicle de vida • Es creen. • Envien/reben missatges. • Quan no són necessaris s’han d’eliminar.


Classes • Per crear una instància d’una classe s’empra el constructor alloc NSMutableArray *instancia = [NSMutableArray alloc];

• Després s’ha d’inicialitzar la instància amb el mètode init [NSMutableArray init];

• Aniuant les crides es pot fer en un sol pas. NSMutableArray *instancia = [[NSMutableArray alloc] init];

• Un cop inicialitzada una instància ja podem invocar-hi mètodes. [instancia addObject:altra_instancia]


Classes • Els mètodes poden tenir diversos arguments. [instancia replaceObjectsInRange:rang withObjectsFromArray:array Range:altre_rang];

• En C++ o Java l’exemple tindria aquesta aparença: instancia.replaceObjectsInRangeWithObjectsFromArray(rang, array, altre_rang);

• Per eliminar una instància cal emprar el destructor release. [instancia release];


Classes • Després d’eliminar una instància és recomanable posar el valor de la variable a nil (NULL o null en C i Java respectivament) if(instancia != nil) { [instancia ferQualsevolCosa]; }


Exemple 3 – NSMutableArray • Crear i inicialitzar un NSMutableArray • Afegir-hi instàncies d’NSString • Mostrar-ne el contingut a la cònsola via NSLog NSMutableArray *items = [[NSMutableArray alloc] init]; [items [items [items [items

addObject:@”One”]; addObject:@”Two”]; addObject:@”Three”]; insertObject:@”Zero” atIndex:0];

for(int i = 0; i < [items count]; i++) { NSLog(@”%@”, [items objectAtIndex:i]); }


Subclasses • Cada classe té una superclasse de la qual n’hereda atributs i mètodes. La classe arrel és NSObject i tota la resta en són subclasses.

• Les classes d’Objective-C es defineixen mitjançant dos fitxers: un fitxer de capçalera amb extensió .h que defineix l’interfície de la classe i un fitxer d’implementació amb extensió .m que inclou la implementació de la classe. #import <Foundation/Foundation.h> @interface Cotxe : NSObject {

} @end


Subclasses • Cotxe.h #import <Foundation/Foundation.h> @interface Cotxe : NSObject { NSString *marca; NSString *model; int preu; NSDate *dataFabricacio; } @end

• Cotxe.m #import “Cotxe.h” @implementation Cotxe @end


Subclasses – Descriptors d’accés i propietats • Per accedir i editar els valors dels atributs de les classes s’empren els descriptors d’accés i propietats. @property int any;

• Amb els atributs de propietat es defineix la manera en què s’accedeix o s’assigna el valor als atributs de la classe. @property @property @property @property @property @property

(nonatomic, (nonatomic, (nonatomic, (nonatomic, (nonatomic) (nonatomic,

copy) NSString *nom; copy) NSString *cognom; retain) FitxaUsuari *pare; retain) FitxaUsuari *mare; int numeroGermans; readonly) NSDate *dataNaixement;


Subclasses • Amb els descriptors d’accés es defineixen els mètodes getters i setters que obtenen i/o assignen valors als atributs de la classe. • readonly permet només la lectura de l’atribut de la classe @property (nonatomic, readonly) NSDate *dataNaixement;

• readwrite és el valor per defecte i permet la lectura/escriptura de l’atribut de la classe @property (nonatomic) int numeroGermans;

• copy fa una còpia de l’objecte i n’assigna el punter a l’atribut. @property (nonatomic, copy) NSString *nom;


Subclasses • retain no fa còpia de l’objecte. Copia el punter i l’assigna a l’atribut de la classe. @property (nonatomic, retain) FitxaUsuari *pare;

• Finalment cal sintetitzar les propietats al fitxer d’implementació. @synthesize nom, cognom, pare, mare, numeroGermans, dataNaixement;


Exemple 4 – Classe Cotxe • Cotxe.h #import <Foundation/Foundation.h> @interface Cotxe : NSObject { NSString *marca; NSString *model; int preu; NSDate *dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) int preu; @property (nonatomic, copy) NSDate *dataFabricacio; @end


Exemple 4 • Cotxe.m #import “Cotxe.h” @implementation Cotxe @synthesize marca, model, preu, dataFabricacio; [...] @end #import “Cotxe.h” Cotxe *cotxe = [[Cotxe alloc] init]; [cotxe setMarca:@”Seat”]; [cotxe setModel:@”Ibiza”]; NSLog(@”Marca: %@. Model: %@”, [cotxe marca], [cotxe model]);


Subclasses – Inicialitzadors • La classe NSObject implementa el mètode init que s’encarrega d’inicialitzar la instància de la classe. En aquest cas és únic, però les classes poden tenir múltiples inicialitzadors.

• Per conveni tots els inicialitzadors han de començar per init. - (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p;

• Els mètodes inicialitzadors han d’invocar sempre l’inicialitzador de la classe superior que hereten . self = [super init];


Exemple 5 – Inicialitzador classe Cotxe • Cotxe.h #import <Foundation/Foundation.h> @interface Cotxe : NSObject { NSString *marca; NSString *model; int preu; NSDate *dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) int preu; @property (nonatomic, copy) NSDate *dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p; @end


Exemple 5 • Cotxe.m #import “Cotxe.h” @implementation Cotxe @synthesize marca, model, preu, dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p { self = [super init]; [self setMarca:ma]; [self setModel:mo]; [self setPreu:p]; dataFabricacio = [[NSDate alloc] init];

return self; } @end

#import “Cotxe.h” Cotxe *cotxe = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000]; NSLog(@”Marca: %@. Model: %@”, [cotxe marca], [cotxe model]);


Subclasses – Mètodes de classe • Els mètodes de classe es diferencien dels mètodes comuns (mètodes d’instància) pel fet que no tenen efecte sobre les instàncies de la classe. • Els mètodes de classe no poden accedir als atributs de la instància. • Un clar exemple és el mètode alloc. • Es diferencien sintàcticament dels mètodes d’instància durant la declaració. Empren el signe + enlloc del signe – • S’invoquen sobre la pròpia classe i mai a una instància de la classe. + (NSMutableArray) obtenirCotxesFamiliars;


Exemple 6 – Mètodes de classe • Cotxe.h #import <Foundation/Foundation.h> @interface Cotxe : NSObject { NSString *marca; NSString *model; int preu; NSDate *dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) int preu; @property (nonatomic, copy) NSDate *dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p; + (NSMutableArray) obtenirCotxesFamiliars; @end


Exemple 6 – Mètodes de classe • Cotxe.m #import “Cotxe.h” @implementation Cotxe @synthesize marca, model, preu, dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p { self = [super init]; [self setMarca:ma]; [self setModel:mo]; [self setPreu:p]; dataFabricacio = [[NSDate alloc] init]; return self; } + (NSMutableArray) obtenirCotxesFamiliars { Cotxe *cotxe1 = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500]; Cotxe *cotxe2 = [[Cotxe alloc] initWithMarca:@” Volkswagen” model:@”Passat” preu:23000]; Cotxe *cotxe3 = [[Cotxe alloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500]; return [ [ [ NSMutableArray alloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease ]; } @end


Exemple 6 – Mètodes de classe #import “Cotxe.h” Cotxe *cotxe = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000]; NSLog(@”Marca: %@. Model: %@”, [cotxe marca], [cotxe model]);

NSMutableArray *cotxes = [[Cotxe obtenirCotxesFamiliars] retain]; for (int i = 0; i < [cotxes count]; i++) NSLog(@” Cotxe %d: Marca: %@. Model: %@”, i, [cotxe marca], [cotxe model]); [cotxes release];


4 Gestió de la memòria • A diferència de l’Objective-C per Mac (Cocoa), l’Objective-C per iOS (Cocoa Touch) no disposa de recolector d’elements no utilitzats (garbaje collector de Java). • És responsabilitat del programador fer-se càrrec d’alliberar la memòria. • Els objectes que no són necessaris s’han d’alliberar sempre.


4 Gestió de la memòria • Els dos principals problemes d’una mala gestió de la memòria són: • Premature deallocation: Alliberar la memòria ocupada per un objecte quan aquest encara pot ser utilitzat durant l’execució de l’App. • Memory leaks: Memòria que es perd. Objectes que han quedat en desús i que no s’han alliberat. El dispositiu es queda sense memòria per a altres objectes.


Gestió de la memòria en llenguatge C • Malloc: En el llenguatge C es necessari solicitar de forma explícita la quantitat de memòria per a cada estructura o variable. • Free: Quan ja no és necessari aquest espai cal alliberar-lo. punter = malloc(100);

strcpy(punter, “abbbccc”);

Memòria disponible

Memòria disponible

100 Bytes

punter free(punter); Memòria disponible

100 Bytes “abbbccc”

punter punter = NULL; Memòria disponible

?

punter

punter = 0


Gestió de la memòria orientada a objectes • En Objective-C es treballa amb objectes. Per tant no cal especificar la quantitat de memòria que s’ha de reservar per als objectes, d’això se n’encarrega el sistema. • Alloc: Després de crear un objecte n’obtenim el seu punter i és suficient en saber que apunta a l’objecte creat i prou. • Dealloc: Tots els objectes implementen el mètode dealloc. Quan un objecte rep aquest missatge allibera la memòria que ocupa.

• Mai hem d’invocar manualment el mètode dealloc als objectes. Són els propis objectes els encarregats de d’invocar-se aquests mètodes ells mateixos. • ¿En quin moment els objectes saben que han d’eliminar-se? • Mitjançant un recompte de referències: reference counting.


Gesti贸 de la mem貌ria orientada a objectes

Assignaci贸 de mem貌ria a un objecte


Recompte de referències (retain count) • En Cocoa Touch, Apple ha optat per la tècnica de recompte manual de referències, reference counting, per realitzar la gestió de la memòria i evitar així els problemes de premature deallocation (alliberar massa d’hora) i memory leaks (memòria perduda no alliberada). • Els objectes mai saben quins són els seus propietaris (altres objectes que apunten a ells). • Els objectes disposen d’una informació anomenada retain count.


Recompte de referències (retain count) • Quan es crea un objecte aquest té un propietari, i per tant, el seu retain count és igual a 1. Cada vegada que l’objecte te un nou propietari s’incrementa el valor de retain count. • Quan l’objecte perd un propietari, el valor del seu retain count disminueix. • Quan el retain count arriba a zero aleshores l’objecte s’envia a si mateix el missatge dealloc i s’allibera la memòria que ocupa. • Per incrementar i disminuir el retain count d’empren els mètodes retain i release respectivament. - (id) retain { retainCount++; return self; }

- (id) release { retainCount--; if (retainCount == 0) [self dealloc]; }


Recompte de referències (retain count) - (void) crearEntregarLlistaDeLaCompra { // Crear una llista de la compra GroceryList *g = [[GroceryList alloc] init]; // (El valor retain count de g es 1) // Ho compartim amb el nostre amic, el qual la conservarà [smartFriend entregarLlistaDeLaCompra:g]; // (El valor retain count de g es 2) // La llista deixa de sér nostra [g release];

// (El valor retain count de g es 1) // No ens preocupa, ja que ja no es responsabilitat d’aquest mètode }


Recompte de referències (retain count) • El codi del nostre amic serà el següent

- (void) entregarLlistaDeLaCompra: (GroceryList *)x { // Accepta la propietat de la llista i per tant incrementa el retain count [x retain]; // Conserva un punter a l’objecte myList = x;

}


Alliberació automàtica (autorelease) • L’alliberació automàtica permet alliberar (fer release) objectes que hem creat però que no volem emprar, sinó que volem entregar a altres objectes. • El següent mètode de classe entrega un array de Cotxes a l’objecte que el crida. La classe que implementa aquest mètode no emprarà l’array i per tant cal fer release.

+ (NSMutableArray) obtenirCotxesFamiliars { Cotxe *cotxe1 = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500]; Cotxe *cotxe2 = [[Cotxe alloc] initWithMarca:@” Volkswagen” model:@”Passat” preu:23000]; Cotxe *cotxe3 = [[Cotxe alloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500]; return [ [ [ NSMutableArray alloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease ]; }


Alliberació automàtica (autorelease) • L’autorelease ens permetrà alliberar de forma segura, i en diferit, objectes que no volem utilitzar. + (NSMutableArray) obtenirCotxesFamiliars { Cotxe *cotxe1 = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500]; Cotxe *cotxe2 = [[Cotxe alloc] initWithMarca:@”Volkswagen” model:@”Passat” preu:23000]; Cotxe *cotxe3 = [[Cotxe alloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500]; NSMutableArray *cotxes = [[NSMutableArray alloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ]; // Si alliberem l’objecte cotxes aquí desassignaríem l’objecte abans de retornar-lo. return cotxes;

//Podem alliberar l’objecte aquí, però aquest codi no s’executaria mai. }

return [[[NSMutableArray alloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease];


Gestió de memòria en descriptors d’accés i propietats • Els descriptors d’accés són mètodes que tenen la capacitat de, o bé captar, get, el valor de la variable d’una instància, o bé d’establir, set, aquest valor. • En els mètodes captadors, o getters, no cal aplicar cap gestió de memòria. - (Dog *)pet { return pet; }

• Els mètodes assignadors, o setters, pel contrari s’han d’encarregar de retindre els nous valors i alliberar els antics. - (void)setPet: (Doc *)d { [d retain]; [pet release]; pet = d; }

// Reté el valor nou // Allibera el valor antic // Canvia la direcció del punter per la del valor nou


Gestió de memòria en descriptors d’accés i propietats • Per fer que el compilador generi un descriptor d’accés que pugui, de forma automàtica, alliberar i retenir els objectes, cal utilitzar l’atribut retain en el moment de declarar les propietats al fitxer de definició d’interfície de la classe .h @property (nonatomic, retain) Dog *pet;

• En el fitxer d’implementació cal sintetizar el mètode. @synthesize pet;


Regles del retain count • Quan es crea un objecte amb el mètode alloc, la instància obtinguda tindrà un valor d’1 en el comptador retain count. El desenvolupador s’ha d’encarregar d’alliberar-ho emprant release. • Si invoquem el mètode copy (o mutableCopy) a una instància, la instància obtinguda tindrà un valor d’1 en el comptador retain count. El desenvolupador s’ha d’encarregar d’alliberar-ho emprant release. • S’ha d’assumir que un objecte obtingut fent una crida a un objecte tindrà un valor d’1 en el comptador retain count i està marcat com autorelease. • Si un objecte vol conservar un altre objecte emprant un punter ha d’emprar retain sobre l’objecte a conservar.

• Si un objecte vol alliberar un altre objecte li ha d’enviar el missatge release.


Exemple 7 – Array d’objectes Cotxe • Cotxe.h #import <Foundation/Foundation.h> @interface Cotxe : NSObject { NSString *marca; NSString *model; int preu; NSDate *dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) int preu; @property (nonatomic, copy) NSDate *dataFabricacio;

- (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p; + (NSMutableArray *) obtenirCotxesFamiliars; + (Cotxe *) obtenirCotxeEsportiu; - (Cotxe *) clonar; @end


Exemple 7 – Array d’objectes Cotxe • Cotxe.m #import “Cotxe.h” @implementation Cotxe @synthesize marca, model, preu, dataFabricacio;

- (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p { self = [super init]; [self setMarca:ma]; [self setModel:mo]; [self setPreu:p]; dataFabricacio = [[NSDate alloc] init]; return self;

}

+ (NSMutableArray *) obtenirCotxesFamiliars { Cotxe *cotxe1 = [[[Cotxe alloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500] autorelease]; Cotxe *cotxe2 = [[[Cotxe alloc] initWithMarca:@” Volkswagen” model:@”Passat” preu:23000] autorelease]; Cotxe *cotxe3 = [[[Cotxe alloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500] autorelease]; return [ [ [ NSMutableArray alloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease ]; }


Exemple 7 – Array d’objectes Cotxe • Cotxe.m + (Cotxe *) obtenirCotxeEsportiu { Cotxe *cotxe = [[Cotxe alloc] initWithMarca:@”Volkswagen” model:@”Golf GTI” preu:24500]; return [cotxe autorelease ]; } - (Cotxe *) clonar { Cotxe *cotxe = [[Cotxe alloc] init]; [cotxe setMarca:[self marca]]; [cotxe setModel:[self model]]; [cotxe setPreu:[self preu]]; [cotxe setDataFabricacio:[self dataFabricacio]]; return [cotxe autorelease];

} - (void) dealloc { [marca release]; [model dealloc]; [dataFabricacio dealloc]; [super dealloc]; } @end


Exemple 7 – Array d’objectes Cotxe #import “Cotxe.h” Cotxe *cotxe = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000]; // (El valor retain count de cotxe es 1) NSLog(@”Marca: %@. Model: %@”, [cotxe marca], [cotxe model]);

Cotxe *cotxe_clonat = [[cotxe clonar] retain]; // (El valor retain count de cotxe_clonat es 1) NSLog(@”Marca: %@. Model: %@”, [cotxe_clonat marca], [cotxe_clonat model]);

NSMutableArray *cotxes = [[Cotxe obtenirCotxesFamiliars] retain]; // (El valor retain count de cotxes es 1) [cotxes addObject:cotxe]; // Quan es fa un addObject s’aplica un retain sobre de l’objecte // (El valor retain count de cotxe es 2) for (int i = 0; i < [cotxes count]; i++) NSLog(@” Cotxe %d: Marca: %@. Model: %@”, i, [cotxe marca], [cotxe model]); [cotxes release]; [cotxe release]; [cotxe_clonat release];

//Envia un release a tots els seus objectes (El valor retain count de cotxe torna a sér 1) // (El valor retain count de cotxe és 0, i per tant el sistema l’hi envia el missatge dealloc) // (El valor retain count de cotxe_clonat és 0, i per tant el sistema l’hi envia el missatge dealloc)


Exemple 7 – Array d’objectes Cotxe


5 Model Vista Controlador (MVC) • UIViewController (Model-View-Controller) • View: Objectes visibles per a l’usuari. • • • • •

UILabel UIButton UIImageView UITextField Etc...

• Model: Objectes per guardar dades • • • •

NSArray NSDictionary SQLite Etc...

• Controller: Enllaça i controla la vista i el model.


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.