curs de programació d ’ ios
DESCRIPTION
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 - PowerPoint PPT PresentationTRANSCRIPT
Curs de programació d’iOSNovembre 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/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
•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...
Frameworks
• 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
Classes
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]
• Els mètodes poden tenir diversos arguments.
Classes
[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];
• 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)
Classes
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 addObject:@”One”];[items addObject:@”Two”];[items addObject:@”Three”];[items insertObject:@”Zero” atIndex:0];
for(int i = 0; i < [items count]; i++) {NSLog(@”%@”, [items objectAtIndex:i]);
}
• 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.
Subclasses
#import <Foundation/Foundation.h>
@interface Cotxe : NSObject {
}
@end
• 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 {NSString *marca;NSString *model;int preu;NSDate *dataFabricacio;
}@end
• Cotxe.h
Subclasses
#import “Cotxe.h”@implementation Cotxe@end
• Cotxe.m
• Per accedir i editar els valors dels atributs de les classes s’empren els descriptors d’accés i propietats.
Subclasses – 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 (nonatomic, copy) NSString *nom;@property (nonatomic, copy) NSString *cognom;@property (nonatomic, retain) FitxaUsuari *pare;@property (nonatomic, retain) FitxaUsuari *mare;@property (nonatomic) int numeroGermans;@property (nonatomic, readonly) NSDate *dataNaixement;
Subclasses
@property (nonatomic) int numeroGermans;
• 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.
@property (nonatomic, readonly) NSDate *dataNaixement;
• readonly permet només la lectura de l’atribut de la classe
• readwrite és el valor per defecte i permet la lectura/escriptura de l’atribut de la classe
@property (nonatomic, copy) NSString *nom;
• copy fa una còpia de l’objecte i n’assigna el punter a l’atribut.
Subclasses
@property (nonatomic, retain) FitxaUsuari *pare;
• retain no fa còpia de l’objecte. Copia el punter i l’assigna a l’atribut de la classe.
• Finalment cal sintetitzar les propietats al fitxer d’implementació.
@synthesize nom, cognom, pare, mare, numeroGermans, dataNaixement;
#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
• Cotxe.h
Exemple 4 – Classe Cotxe
#import “Cotxe.h”
@implementation Cotxe@synthesize marca, model, preu, dataFabricacio;
[ . . . ]
@end
• Cotxe.m
Exemple 4
#import “Cotxe.h”
Cotxe *cotxe = [[Cotxe alloc] init];[cotxe setMarca:@”Seat”];[cotxe setModel:@”Ibiza”];NSLog(@”Marca: %@. Model: %@”, [cotxe marca], [cotxe model]);
• 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.
Subclasses – Inicialitzadors
- (id) initWithMarca: (NSString *)ma model: (NSString *)mo preu: (int)p;
• Per conveni tots els inicialitzadors han de començar per init.
self = [super init];
• Els mètodes inicialitzadors han d’invocar sempre l’inicialitzador de la classe superior que hereten .
#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
• Cotxe.h
Exemple 5 – Inicialitzador classe Cotxe
#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
• Cotxe.m
Exemple 5
#import “Cotxe.h”
Cotxe *cotxe = [[Cotxe alloc] initWithMarca:@”Seat” model:@”Ibiza” preu:18000];NSLog(@”Marca: %@. Model: %@”, [cotxe marca], [cotxe model]);
• 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.
Subclasses – Mètodes de classe
+ (NSMutableArray) obtenirCotxesFamiliars;
• 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.
#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
• Cotxe.h
Exemple 6 – Mètodes de classe
#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
• Cotxe.m
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];
Exemple 6 – Mètodes de classe
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.
• 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.
Gestió de la memòria en llenguatge C
100Bytes
100 Bytes“abbbccc”
Memòria disponible Memòria disponible
Memòria disponible Memòria disponible
?
punter punter
punter punter = 0
punter = malloc(100); strcpy(punter, “abbbccc”);
free(punter); punter = NULL;
• 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
Gestió de la memòria orientada a objectes
Assignació de memòria a un objecte
• 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.
Recompte de referències (retain count)
- (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 compraGroceryList *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)
- (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;}
• El codi del nostre amic serà el següent
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.
+ (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 ];}
• 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.
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]; // 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 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
#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
• Cotxe.h
#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 ];
}
• Cotxe.m
Exemple 7 – Array d’objectes Cotxe
+ (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
• Cotxe.m
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]; //Envia un release a tots els seus objectes (El valor retain count de cotxe torna a sér 1)[cotxe release]; // (El valor retain count de cotxe és 0, i per tant el sistema l’hi envia el missatge dealloc)[cotxe_clonat release]; // (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
Exemple 7 – Array d’objectes Cotxe
• 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.
5 Model Vista Controlador (MVC)