480 likes | 654 Views
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
E N D
Curs de programació d’iOS Novembre de 2011 Organitza
3 Introducció a l’Objective-C • Les aplicacions per iOS es desenvolupen en llenguatgeObjective-C • És una extensió simplificada del C • Programació orientada a objectes • L’SDK es compond’unconjunt de Frameworks • Tot el conjunts’anomenaCocoa • En elsdispositiustàctilss’empraCocoaTouch
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 • Foundation: Tipusprimitius de dades, etc... • http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/ObjC_classic/_index.html • UIKit: Classes de la UI • http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Framework/_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ésagenda de contactes • MediaPlayer: Player de video/audio/streaming? • CoreBluetooth: Úsbluetooth • AudioToolbox: Manipulaciód’audio • iAd: IntegraciópublicitatiAdd’Apple • Etc...
Classes • Enspermeten definir tipusd’objectes. • Quancreem un objectetenim una instànciad’aquellaclasse. • Les classestenenatributs i mètodes. • Elsobjectestenen el seu propi cicle de vida • Es creen. • Envien/rebenmissatges. • Quan no sónnecessariss’hand’eliminar.
Classes • Per crear una instància d’una classe s’empra el constructor alloc NSMutableArray *instancia = [NSMutableArrayalloc]; • Després s’ha d’inicialitzar la instància amb el mètode init [NSMutableArrayinit]; • Aniuantles crides es potfer en un sol pas. NSMutableArray *instancia = [[NSMutableArrayalloc] init]; • Un cop inicialitzada una instància ja podem invocar-hi mètodes. [instanciaaddObject:altra_instancia]
Classes • Elsmètodes poden tenirdiversos arguments. [instanciareplaceObjectsInRange: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ésd’eliminar una instànciaésrecomanable posar el valor de la variable a nil(NULL o null en C i Java respectivament) if(instancia!= nil) { [instanciaferQualsevolCosa]; }
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 = [[NSMutableArrayalloc] init]; [itemsaddObject:@”One”]; [itemsaddObject:@”Two”];[itemsaddObject:@”Three”]; [itemsinsertObject:@”Zero” atIndex:0]; for(int i = 0; i < [itemscount]; i++) { NSLog(@”%@”, [itemsobjectAtIndex:i]); }
Subclasses • Cada classeté una superclasse de la qualn’heredaatributs i mètodes. La classearrelésNSObject i tota la resta en sónsubclasses. • Les classesd’Objective-C es defineixenmitjançant dos fitxers: un fitxer de capçaleraambextensió .h que defineixl’interfície de la classe i un fitxerd’implementacióambextensió .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; intpreu; 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; • Ambelsatributs de propietat es defineix la manera en quès’accedeix o s’assigna el valor alsatributs de la classe. @property (nonatomic, copy) NSString *nom; @property (nonatomic, copy) NSString *cognom; @property (nonatomic, retain) FitxaUsuari *pare; @property (nonatomic, retain) FitxaUsuari *mare; @property (nonatomic) intnumeroGermans; @property (nonatomic, 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) intnumeroGermans; • copy fa una còpiade l’objecte i n’assigna el punter a l’atribut. @property (nonatomic, copy) NSString *nom;
Subclasses • retain no fa còpiade 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; intpreu; NSDate*dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) intpreu; @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 = [[Cotxealloc] init]; [cotxesetMarca:@”Seat”]; [cotxesetModel:@”Ibiza”]; NSLog(@”Marca: %@. Model: %@”, [cotxemarca], [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; intpreu; NSDate*dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) intpreu; @property (nonatomic, copy) NSDate *dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mopreu: (int)p; @end
Exemple 5 • Cotxe.m #import “Cotxe.h” @implementation Cotxe @synthesize marca, model, preu, dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mopreu: (int)p { self = [super init]; [self setMarca:ma]; [self setModel:mo]; [self setPreu:p]; dataFabricacio = [[NSDatealloc] init]; return self; } @end #import “Cotxe.h” Cotxe *cotxe = [[Cotxealloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000]; NSLog(@”Marca: %@. Model: %@”, [cotxemarca], [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’invoquensobre la pròpiaclasse 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; intpreu; NSDate*dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) intpreu; @property (nonatomic, copy) NSDate *dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mopreu: (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 *)mopreu: (int)p { self = [super init]; [self setMarca:ma]; [self setModel:mo]; [self setPreu:p]; dataFabricacio = [[NSDatealloc] init]; return self; } + (NSMutableArray) obtenirCotxesFamiliars { Cotxe *cotxe1 = [[Cotxealloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500]; Cotxe *cotxe2 = [[Cotxealloc] initWithMarca:@” Volkswagen” model:@”Passat” preu:23000]; Cotxe *cotxe3 = [[Cotxealloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500]; return [ [ [ NSMutableArrayalloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease ]; } @end
Exemple 6 – Mètodes de classe #import “Cotxe.h” Cotxe *cotxe = [[Cotxealloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000]; NSLog(@”Marca: %@. Model: %@”, [cotxemarca], [cotxe model]); NSMutableArray *cotxes = [[CotxeobtenirCotxesFamiliars] retain]; for (inti = 0; i < [cotxes count]; i++) NSLog(@” Cotxe %d: Marca: %@. Model: %@”, i, [cotxemarca], [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 (CocoaTouch) no disposa de recolector d’elements no utilitzats (garbajecollector de Java). • Ésresponsabilitat del programador fer-se càrrecd’alliberar la memòria. • Elsobjectes que no sónnecessariss’hand’alliberarsempre.
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 100 Bytes “abbbccc” punter punter free(punter); punter = NULL; Memòria disponible Memòria disponible ? punter = 0 punter
Gestió de la memòria orientada a objectes • En Objective-C es treballa ambobjectes. Per tant no cal especificar la quantitat de memòria que s’ha de reservar per alsobjectes, d’això se n’encarrega el sistema. • Alloc: Després de crear un objecten’obtenim el seupunter i éssuficient en saber que apunta a l’objectecreat i prou. • Dealloc: Totselsobjectes implementen el mètodedealloc. Quan un objecterepaquestmissatgeallibera la memòria que ocupa. • Maihemd’invocarmanualment el mètodedeallocalsobjectes. Sónels propis objecteselsencarregats de d’invocar-se aquestsmètodesellsmateixos. • ¿En quinmomentelsobjectes saben que han d’eliminar-se? • Mitjançant un recompte de referències: referencecounting.
Gestió de la memòria orientada a objectes Assignació de memòria a un objecte
Recompte de referències (retain count) • En CocoaTouch, Apple ha optat per la tècnica de recompte manual de referències, referencecounting, per realitzar la gestió de la memòria i evitar aixíelsproblemes de prematuredeallocation(alliberarmassad’hora) i memoryleaks(memòriaperduda no alliberada). • Elsobjectesmai saben quinssónelsseuspropietaris (altresobjectes que apunten a ells). • Elsobjectesdisposend’unainformacióanomenadaretaincount.
Recompte de referències (retain count) • Quan es crea un objecteaquest té un propietari, i per tant, el seuretaincountés igual a 1. Cada vegada que l’objecte te un noupropietaris’incrementa el valor de retaincount. • Quanl’objecteperd un propietari, el valor del seuretaincountdisminueix. • Quan el retaincountarriba a zeroaleshoresl’objectes’envia a si mateix el missatgedealloc i s’allibera la memòria que ocupa. • Per incrementar i disminuir el retaincountd’emprenelsmètodesretain i releaserespectivament. - (id) retain { retainCount++; return self; } - (id) release { retainCount--; if (retainCount == 0) [self dealloc]; }
Recompte de referències (retain count) - (void) crearEntregarLlistaDeLaCompra { // Crearunallista de la compra GroceryList *g = [[GroceryListalloc] init]; // (El valor retain count de g es 1) // Ho compartimamb el nostreamic, el qual la conservarà [smartFriendentregarLlistaDeLaCompra:g]; // (El valor retain count de g es 2) // La llistadeixa de sér nostra [g release]; // (El valor retain count de g es 1) // No enspreocupa, jaqueja no esresponsabilitatd’aquestmè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 llistai per tantincrementa 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 = [[Cotxealloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500]; Cotxe*cotxe2 = [[Cotxealloc] initWithMarca:@” Volkswagen” model:@”Passat” preu:23000]; Cotxe*cotxe3 = [[Cotxealloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500]; return [ [ [ NSMutableArrayalloc ] 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 = [[Cotxealloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500]; Cotxe*cotxe2 = [[Cotxealloc] initWithMarca:@”Volkswagen” model:@”Passat” preu:23000]; Cotxe*cotxe3 = [[Cotxealloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500]; NSMutableArray*cotxes = [[NSMutableArrayalloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ]; // Si allibereml’objectecotxesaquídesassignaríeml’objecteabans de retornar-lo. return cotxes; //Podemalliberarl’objecteaquí, peròaquestcodi no s’executariamai. } return [[[NSMutableArrayalloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease];
Gestió de memòria en descriptors d’accés i propietats • Elsdescriptorsd’accéssónmètodes que tenen la capacitat de, o bécaptar, get, el valor de la variable d’unainstància, o béd’establir, set, aquest valor. • En elsmètodescaptadors, o getters, no cal aplicar capgestió 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]; // Reté el valor nou [pet release]; // Allibera el valor antic pet = d; // 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 retenirelsobjectes, cal utilitzarl’atributretain 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 objecteamb el mètodealloc, la instànciaobtingudatindrà un valor d’1 en el comptadorretaincount. El desenvolupadors’had’encarregard’alliberar-hoemprantrelease. • Si invoquem el mètodecopy (o mutableCopy) a una instància, la instànciaobtingudatindrà un valor d’1 en el comptadorretaincount. El desenvolupadors’had’encarregard’alliberar-hoemprantrelease. • S’had’assumir que un objecteobtingutfent una crida a un objectetindrà un valor d’1 en el comptadorretaincounti estàmarcatcomautorelease. • Si un objectevol conservar un altreobjecteemprant un punterha d’emprarretain sobre l’objecte a conservar. • Si un objectevolalliberar un altreobjecte li ha d’enviar el missatgerelease.
Exemple 7 – Array d’objectes Cotxe • Cotxe.h #import <Foundation/Foundation.h> @interface Cotxe : NSObject { NSString*marca; NSString*model; intpreu; NSDate*dataFabricacio; } @property (nonatomic, copy) NSString *marca; @property (nonatomic, copy) NSString *model; @property (nonatomic) intpreu; @property (nonatomic, copy) NSDate *dataFabricacio; - (id) initWithMarca: (NSString *)ma model: (NSString *)mopreu: (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 *)mopreu: (int)p { self = [super init]; [self setMarca:ma]; [self setModel:mo]; [self setPreu:p]; dataFabricacio = [[NSDatealloc] init]; return self; } + (NSMutableArray *) obtenirCotxesFamiliars { Cotxe *cotxe1 = [[[Cotxealloc] initWithMarca:@”Seat” model:@”Exeo” preu:22500] autorelease]; Cotxe *cotxe2 = [[[Cotxealloc] initWithMarca:@” Volkswagen” model:@”Passat” preu:23000] autorelease]; Cotxe *cotxe3 = [[[Cotxealloc] initWithMarca:@”Ford” model:@”Mondeo” preu:23500] autorelease]; return [ [ [ NSMutableArrayalloc ] initWithObjects: cotxe1, cotxe2, cotxe3, nil ] autorelease ]; }
Exemple 7 – Array d’objectes Cotxe • Cotxe.m + (Cotxe *) obtenirCotxeEsportiu { Cotxe *cotxe= [[Cotxealloc] initWithMarca:@”Volkswagen” model:@”Golf GTI” preu:24500]; return [cotxeautorelease ]; } - (Cotxe *) clonar { Cotxe *cotxe = [[Cotxealloc] init]; [cotxesetMarca:[self marca]]; [cotxesetModel:[self model]]; [cotxesetPreu:[self preu]]; [cotxesetDataFabricacio:[self dataFabricacio]]; return [cotxeautorelease]; } - (void) dealloc { [marca release]; [model dealloc]; [dataFabricaciodealloc]; [super dealloc]; } @end
Exemple 7 – Array d’objectes Cotxe #import “Cotxe.h” Cotxe *cotxe = [[Cotxealloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000]; // (El valor retain count de cotxees 1) NSLog(@”Marca: %@. Model: %@”, [cotxemarca], [cotxe model]); Cotxe *cotxe_clonat = [[cotxeclonar] retain]; // (El valor retain count de cotxe_clonates1) NSLog(@”Marca: %@. Model: %@”, [cotxe_clonatmarca], [cotxe_clonat model]); NSMutableArray *cotxes = [[CotxeobtenirCotxesFamiliars] retain]; // (El valor retain count de cotxeses 1) [cotxesaddObject:cotxe]; // Quanesfa un addObjects’aplica un retain sobre de l’objecte // (El valor retain count de cotxees 2) for (inti = 0; i < [cotxes count]; i++) NSLog(@” Cotxe %d: Marca: %@. Model: %@”, i, [cotxemarca], [cotxe model]); [cotxes release]; //Envia un release a tots elsseusobjectes(El valor retain count de cotxetorna a sér 1) [cotxe release]; // (El valor retain count de cotxeés 0, i per tant el sistemal’hienvia el missatgedealloc) [cotxe_clonat release]; // (El valor retain count de cotxe_clonatés0, i per tant el sistemal’hienvia el missatgedealloc)
5Model 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.