2. E tu chi sei?
Mi chiamo Simone Kalb
Socio del GulCh
Junior Software Developer at CRS4 (Open Media Center Lab)
System Administrator
GNU/Linux e MacOS X avid user
3. Chi è iOS?(in numeri)
3° piattaforma mobile venduta al Mondo [IDC]
25% Market share del mercato degli smartphones [IDC]
+0.7% aumento della quota di mercato in un anno [IDC]
16.2M di unità vendute in un anno [IDC]
90M di iPhone venduti da Giugno 2007 [9to5Mac]
4. ...e questo solo per iPhone!
iOS per iPod Touch e iPad
iPod Touch rappresenta il 38% di tutti i dispositivi con iOS [Ai]
7.3M di iPad venduti dal lancio [WaBR]
5. Chi è iOS? (a parole)
Un sistema :
operativo moderno per piattaforme mobili e tablet
ideale per gli sviluppatori
fortemente orientato all’interazione gestuale
6. Chi lo usa?
Tutte le maggiori aziende del settore IT hanno un’app
La maggior parte delle aziende di altri settori
Mercato consumer gigantesco
Comunità di sviluppo fortissima a tutti i livelli
8. Requisiti
Per sviluppare per iOS è necessario:
Tempo (o una persona che te ne dedichi)(Gratis o quasi...)
Un Mac (da €699,00)
Un device con iOS (da €239,00)
iOS Developer Program (da €79,00)
Totale: da € 917,00
9. Ambiente di sviluppo
Leopard (10.5)/Snow Leopard (10.6)/Lion (10.7) Beta
Xcode v.3.2.5/Xcode v.4.0.2/Xcode 4.2 (Beta)
Interface Builder (compreso con Xcode)
Eventualmente documentazione reperibile su http://bit.ly/
mqPaHf
10. Cosa c’è dentro iOS?
Core OS e Core Services
Low-level routines, CFNetwork, CFoundation, SQLite, POSIX
Media Layer
2D, 3D drawing, audio, video, OpenGL ES, Quartz, Core
{Audio, Animation}
Cocoa Touch
High level collections, UIKit, GameKit, iAd, MapKit
12. Cosa vediamo in questo corso?
Connessione di oggetti
Struttura delle applicazioni
I files XIB
La delegation
La gestione della Memoria
Properties
13. Cosa vediamo in questo corso
I view Controller
Il pattern MVC
Esempietto finale
14. Xcode
Scarichiamo Xcode da qui (necessaria registrazione gratuita)
Doppio click sull’icona .pkg
Installiamo anche i tools aggiuntivi
Scarichiamo la documentazione per iOS
16. Iniziamo con la prima App
File ->New Project (Cmd+Maiusc+N)
View-based-Application
Nominatelo Hello
Build-and-Go
Done!
17. Primi passi con IB
Aprite HelloUserViewController.xib
Trascinate una UILabel nella View
Label Size (cmd+3) portando l’altezza a 80.
Carattere (Cmd+t) a 48
Doppio click e scriviamo “Ciao iPhoneâ€
Salvare e Build-and-Go
19. Rotazione
Hardware -> Rotate Left; Il testo non ruoterà .
IB Finestra d’ispezione (Mela+3).
Strut e spring, attiviamo le springs in tutte e quattro le direzioni.
Specificare anche l’allineamento del testo in maniera che risulti
centrato
20. Modifica al codice
HelloViewController.m
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)
interfaceOrientation {
// Return YES for supported orientations
return YES
}
Ora premete Build-and-run
Complimenti avete creato la vostra prima App per iPhone!
21. Due dritte per i Test
Se siete registrati su ADC come iOS Developer potete:
Creare dei certificati per i dispositivi
Creare dei certificati per gli sviluppatori
Diversi certificati per sviluppatori differenti
Testare le applicazioni su device reali
22. Nell’editor
Click sulla barra dell’anteprima del file
Potete saltare alla funzione che più vi interessa
Richiamare la documentazione
Passare dal simulatore al device
24. Objective chi?
Sovrainsieme del C di K&R
Ad esso completamente compatibile ed aderente
È un C completamente ad oggetti ma != dal C++
Agli oggetti sono inviati dei messaggi
Il motore di runtime è incaricato dell’invio o meno dei messaggi
25. Aspetti della sintassi
Parentesi quadre nelle chiamate
mioCarattere = [miaStringa characterAtIndex :3];
I parametri hanno sempre un nome e due punti (keyword)
Le classi hanno un file header e uno d’implementazione
Persona.m/Persona.h
Altro codice utile può essere importato con import nel file header
26. Tipi di classi
Foundation contiene una serie sterminata di classi di largo uso:
NSString (al posto di char*)
NS{Array, Set, Dictionary}/NSMutable{Array, Set,
Dictionary}
NSNumber per numeri di tutti i tipi
UIButton, UITextView,UITableView da UIKit
NSURL che contiene wrapper per file:// e http:// e alt.
28. Modifichiamo la nostra App
Chiudiamo il nostro progetto precedente e creiamone un altro
Anche questa volta scegliamo View-Based Application
Chiamiamolo HelloUser
La nostra App saluterà l’utente col il suo nome precedentemente
scritto
29. Cosa dobbiamo fare?
Dobbiamo creare una label per visualizzare il messaggio
Un campo di testo per il nome dell’utente
Un pulsante per accettare l’input
Un metodo che aggiorni l’etichetta di testo una volta premuto il
pulsante
30. Connessioni
Per fare ciò che abbiamo descritto è necessario
Istruire l’interfaccia grafica con gli elementi
Istruire il codice con i metodi appropriati
Un riferimento dal codice alla UI si chiama outlet
Per definire un oggetto del genere si ricorre ad IBOutlet
Per ogni azione, invece, si usa IBAction
31. IBOutlet e IBAction
IBOutlet è una finta “presa†che fa da ponte tra il codice e l’UI
IBAction gestisce le azioni generate dall’interfaccia
Verranno entrambe dichiarate nel file .h e istanziate nel .m
@interface HelloUserViewController : UIViewController <UITextFieldDelegate> {
!
! IBOutlet UILabel *helloLabel;
! IBOutlet UITextField *nameField;
!
}
-(IBAction)sayHello: (id)sender;
33. IB Disegnare l’interfaccia
Aprire HelloUserViewController.xib
Vedremo due proxy e una view
Inseriamo una UILabel, una UITextField e un UIButton
Per semplicità la UILabel mettiamola vuota
Nella finestra d’ispezione utilizzare un Placeholder nella UIText
Nel bottone utilizziamo la dicitura “Dimmi Ciaoâ€
34. Uno sguardo al File’s Owner
È un proxy alla view
Cliccando col tasto destro si vedono sia gli outlet che le azioni
Ognuno di questi deve essere connesso ad un elemento di UI
In questo caso vedremo helloLabel e nameField
Vedremo la sua importanza nel prosieguo
35. Connettere gli oggetti
Connettiamo gli oggetti dell’UI con File’s Owner
Ogni oggetto della UI viene connesso con un IBOutlet
Il bottone invece verrà connesso ad un IBAction
Unire l’evento TouchUp Inside con IBAction del File’s Owner
In questo caso l’unica scelta disponibile è sayHello:
37. Commentiamo il codice
Otteniamo la stringa inserita dall’utente (proprietà )
Instanza di una stringa a cui aggiungiamo “Helloâ€
%@ è uno specificatore di formato per una stringa di ∀ formato
Impostiamo la proprietà .text per la label con la stringa creata
Ci disfacciamo della stringa non essendo più usata
Reinizializziamo il campo testo della UITextField
38. Due parole sulle Applicazioni
Diamo uno sguardo a main.m
UIApplicationMain è la funzione principale che si occupa del
ciclo di vita dell’applicazione
I due ultimi argomenti sono la classe principale e la sua delegata
La delegata gestisce gli eventi nel ciclo di vita dell’applicazione
In questo caso si carica tutto dai file NIB
39. Andiamo a vedere i NIB
Apriamo i file MainWindows.xib (come ci suggerisce Info.plist)
Icona di Delegato (HelloUserApp Delegate)
ViewController (HelloUserViewController)
Finestra (UIWindow)
File’s Owner
First Responder
40. Application, Life Cycle
Il delegato è connesso all’unica finestra dell’applicazione
Il ViewController carica la sua view da un NIB
Il primo metodo è applicationDidFinishLaunching:
che carica con callback come initWithCoder: e viewDidLoad:
il primo se caricato il NIB l’altro se caricata la view
41. La delegation
La delegation è uno dei pattern più importanti dello sviluppo
Un oggetto chiama il suo unico delegato quando si verificano
determinati eventi
Dal punto di vista del delegato è una callback
“Chiamami quando succede questoâ€
Da quello del delegante è uno scarico di responsabilitÃ
“Non so che fare, pensaci tuâ€
42. Come funziona un delegato?
Objective-C usa un protocollo di delega formale definito in
UIApplicationDelegate
Questo sarebbe come una normale classe
Descrive, però quando i metodi saranno richiamati
Cosa fare quando l’implementatore deve fare quando li richiama
Deve dichiarare che la propria classe implementa il protocollo
44. ..e per il tasto d’invio?
Esaminiamo la classe delegata UITextFieldDelegate
Dovremo prendere in considerazione textFieldShouldReturn:
Quindi dovremo semplicemente overloadare il metodo
E dire alla classe che implementa UITextFieldDelegate
45. Modifichiamo il codice
HelloUserViewController.h
@interface HelloUserViewController : UIViewController <UITextFieldDelegate> {...}
HelloUserViewController.m
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
!
! [textField resignFirstResponder];
! return YES;
!
}
Ora basta un Build and Run.
46. Gestione della memoria
La gestione della memoria su device mobili è fondamentale
È necessario appena possibile liberare quanta più memoria
Ogni applicazione per iPhone deve gestirla correttamente
Tutti gli oggetti sono allocati con conteggio riferimenti pari a 1
retain incrementa il conteggio, release lo decrementa
Quando il valore arriva a zero l’oggetto è pronto per il rilascio
47. Regole d’ingaggio
Le regole auree sono:
se siete proprietari d’un oggetto lo dovete rilasciare
se fate new alloc copy, dovrete fare un release
non rilasciate oggetti non vostri
se volete appropriarvene fate un retain
autorelease serve per metodi che restituiscono oggetti non in
grado di gestire
48. Esempio
La NSString ha un metodo stringWithFormat:
Questo è un metodo a rilascio automatico
Non ha alcuna differenza con alloc e initWithFormat:
Questa chiamata non richiede il rilascio dell’oggetto
49. Rilasciamo gli oggetti
In HelloUserViewController:
- (void)dealloc {
! [textField release];
! [nameField release];
[super dealloc];
}
Così siamo sicuri di rilasciare correttamente tutte le variabili in
gioco
50. Le properties
Variabili istanza con nomi che seguono convenzioni in r/w
Accesso a slot per i getter e setter tramite l’operatore punto
[myLabel setText: myString]; - prima
myLabel.text = myString; - dopo
Le properties vanno definite nel file header fuori dalle parentesi
51. Come si definisce la property
@property (attributi) propType propName;
Vantaggio in termini di leggibilità del codice ma anche:
Gestione della memoria (assign, retain, copy)
Gestione threads (thread-safe, ma nonatomic è più rapido)
@synthesize genera automaticamente i metodi get/set
52. Modifica del codice
HelloUserViewController.h
@property(nonatomic, retain) UILabel *helloLabel;
@property(nonatomic, retain) UITextField *nameField;
HelloUserViewController.m
@synthesize helloLabel, nameField;
Potremo richiamare helloUserViewController.nameField.text
ovunque nel codice anche da altre classi
53. Ricapitoliamo
Le variabili istanza nel .h
se le inseriamo nel .m gli altri non vi possono accedere
Gli oggetti sono creati nel codice o in IB
Gestite le connessioni con IBOutlets e IBAction in IB
<nomeProtocollo> se volete implementare un delegato on in IB
Dichiarare le properties, sintetizzarle e gestire la memoria
55. MVC
Altro paradigma fondamentale in Cocoa
Il View Controller è la “Câ€
Interagisce con la View (“Vâ€)
Per rappresentare un Modello (“Mâ€) astratto
È un modello sul quale si basa gran parte di quel che vedremo
56. Apriamo un nuovo progetto
File->New Project ->View-Based Application
Chiamiamolo Movie
Apriamo MovieViewController.xib
Aggiungiamo un UIButton alla View
Andiamo a modificare il codice
57. Aggiungiamo una Action
In MovieViewController.h:
-(IBAction)done;
Torniamo in IB e facciamo un collegamento tra File’s Owner e il
metodo TouchUp Inside
Ora nel file d’implementazione:
-(IBAction)done {
! NSLog(@"Chiamato il metodo edit");
}
Ora provate a compilare..
58. Creiamo il modello
Add->New File; Objective-C Class;
Chiamiamola Movie come subclass di NSObject e crea anche il .h
@interface Movie : NSObject {
! NSString *title;
! NSNumber *boxOfficeGross;
! NSString *summary;
!
}
-(id)initWithTitle:(NSString *)newTitle
! boxOfficeGross:(NSNumber *)newBoxOfficeGross
! ! summary:(NSString *)newSummary;
@property(nonatomic, copy)NSString *title;
@property(nonatomic, copy)NSNumber *boxOfficeGross;
@property(nonatomic, copy) NSString *summary;
60. Due precisazioni due
self=[super init] serve per gestire i casi in cui la superclasse
restituisca oggetti diversi (alcuni FWs lo fanno)
Serve solo in casi di modelli personalizzati
Abbiamo impostato le properties come copy quindi un dealloc è
necessario
È buona norma mettere a nil le variabili istanza
La classe ha solo un metodo initWithTitle:
61. Aggiunta di outlet e azioni
Nel file MovieViewController.h
#import <UIKit/UIKit.h>
@class Movie;
@interface MovieViewController : UIViewController {
!
! Movie *movie;
! UILabel *titleLabel;
! UILabel *boxOfficeGrossLabel;
! UILabel *summaryLabel;
! MovieEditorViewController *editingViewController;
}
@property(nonatomic, retain) Movie *movie;
@property(nonatomic, retain) IBOutlet UILabel *titleLabel;
@property(nonatomic, retain) IBOutlet UILabel *boxOfficeGrossLabel;
@property(nonatomic, retain) IBOutlet UILabel *summaryLabel;
@property(nonatomic, retain) IBOutlet MovieEditorViewController *editingViewController;
-(IBAction)edit;
@end
Da notare come la @class Movie; sia una dichiarazione forward
62. E nel file .m
Adesso importiamo la classe Movie e sintetizziamo le properties:
#import "MovieViewController.h"
#import "Movie.h"
@implementation MovieViewController
@synthesize titleLabel;
@synthesize boxOfficeGrossLabel;
@synthesize summaryLabel;
@synthesize movie;
Ora siamo pronti alla modifica dell’interfaccia in IB
Apriamo MovieViewController.xib
63. Le modifiche all’interfaccia
Nella nostra view inseriamo ben tre UILabel leggermente
distanziate
Connettete correttamente gli outlets con le labels
Salvate come al solito IB (altrimenti non succede nulla)
Ritorniamo al codice
Implementiamo il controller in modo che visualizzi di dati
64. Inizializzazione della View
Non appena si carica la view vogliamo che appaia qualcosa:
- (void)viewDidLoad {
[super viewDidLoad];
! Movie *newMovie = [[[Movie alloc]
! ! ! ! ! ! initWithTitle:@"Iron Man"
! ! ! ! ! ! boxOfficeGross:[NSNumber numberWithFloat:650000000.00]
! ! ! ! ! ! summary:@"Un tipo sveglio costruisce armi fighe"] autorelease];
! self.movie = newMovie;
}
Succede che quando un controller riceve una richiesta vede se ha
già una view, in caso contrario carica loadView:
Poi viene richiamato viewDidLoad: non appena visualizzata la
view, infine viene chiamato viewWillAppear:
65. Non appena la view è caricata
Ecco il codice per MovieViewController.m
-(void)viewWillAppear:(BOOL)animated {
! [super viewWillAppear:animated];
! self.titleLabel.text = self.movie.title;
! NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
! [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
! self.boxOfficeGrossLabel.text = [formatter stringFromNumber:self.movie.boxOfficeGross];
! [formatter release];
! self.summaryLabel.text = self.movie.summary;
!
}
Il codice aggiunge i dati per gli oggetti Movie nei campi di testo
NSNumberFormatter viene usato per convertire numeri e stringhe
66. Creazione di un nuovo VC
Scegliete Add->NewFile e scegliete UIViewController Subclass
Ricordatevi di NON spuntare with XIB for user interface
MovieEditorViewController sarà il nome del nuovo VC
Andiamo subito a modificare il codice del controller
Partiamo dall’header file
67. MovieEditorViewController.h
@class Movie;
@interface MovieEditorViewController : UIViewController <UITextFieldDelegate> {
! UITextField *titleField;
! UITextField *boxOfficeGrossField;
! UITextField *summaryField;
! Movie *movie;
}
@property(nonatomic, retain) IBOutlet UITextField *titleField;
@property(nonatomic, retain) IBOutlet UITextField *boxOfficeGrossField;
@property(nonatomic, retain) IBOutlet UITextField *summaryField;
@property(nonatomic, retain) Movie *movie;
-(IBAction)done;
@end
Notiamo che implementiamo l’interfaccia UITextFieldDelegate
E un metodo d’interfaccia per quando avremo finito, done:
68. MovieEditorViewController.m
Ricordiamoci di aggiungere #import Movie.h; e @synthesize
per le proprietÃ
-(void)viewWillAppear:(BOOL)animated {
! [super viewWillAppear:animated];
! self.titleField.text = self.movie.title;
! self.summaryField.text = self.movie.summary;
! NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
! [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
! self.boxOfficeGrossField.text = [formatter stringFromNumber:self.movie.boxOfficeGross];
! [formatter release];
!
}
Notiamo come convertiamo una stringa il numero
boxOfficeGross mediante un NSNumerFormatter
69. MovieEditorViewController.m
Dismettiamo l’attuale view modale per l’azione “Doneâ€
-(IBAction)done {
! [[self parentViewController] dismissModalViewControllerAnimated:YES];
!
}
Renderemo in seguito il view controller delegato per
ciascun campo di testo in IB
Come prima vedremo come implementare i metodi
textFielShouldReturn: e textFieldDidEndEditing:
70. textFieldShouldReturn:
-(BOOL)textFieldShouldReturn:(UITextField *)textField; {
! [textField resignFirstResponder];
! return YES;
!
}
Approfittiamo del momento in cui il controllo rilascia il ruolo
di primo risponditore per inserire i dati nell’oggetto:
-(void) textFieldDidEndEditing:(UITextField *)textField {
! if(textField == self.titleField) {
! ! self.movie.title = self.titleField.text;
! } else if(textField == self.boxOfficeGrossField) {
! ! NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
! ! [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
! ! self.movie.boxOfficeGross = [formatter numberFromString:self.boxOfficeGrossField.text];
! ! [formatter release];
! }else if(textField == self.summaryField) {
! ! self.movie.summary = self.summaryField.text;
! }
}
È necessario distinguere i valori digitati nei vari campi
71. Creazione dell’UI
Add->New File da iOS->User Interfaces e scegliete View XIB
Chiamate il tutto MovieEditorViewController.xib
Cambiamo subito il File’s Owner con
MovieEditorViewController
Aggiungete tre campi di testo ed un pulsante
Connettete ciascuno degli outlet dei campi di testo
Connettete infine l’IBAction e i delegati
72. Tenere sempre presente la
tastiera
Pensate sempre alla tastiera che deve apparire per i campi di testo
Password? Numeri? URL? Ad ognuno la sua tastiera
Scegliere l’indicazione corretta del tasto d’invio
L’uso di un segnaposto è talvolta incoraggiato
La funzionalità Clear When Editing Begin va usata con cautela
73. Creazione del MEVC
Abbiamo quasi finito, ci manca solo come arrivare alla nuova view
I passi da seguire sono i seguenti:
Aggiungere un outlet a MVC per l’istanza di MEVC
Aggiornare il metodo edit:
Creare un’istanza di MEVC nel NIB di MVC e effettuare la
connessione
75. Aggiorniamo edit:
Non dimentichiamo di aggiungere l’istruzione #import e i
synthesize per ciascuna proprietà .
Il metodo edit: diventerà il seguente
-(IBAction)edit {
! self.editingViewController.movie = self.movie;
! [self presentModalViewController:self.editingViewController
! ! ! ! ! ! ! animated:YES];
}
Ora aggiungete un view controller al NIB di MVC, impostate
MEVC come classe di questo NIB
Infine connettete all’outlet evc del File’s Owner al nuovo VC
76. Fine!
Finalmente l’applicazione dovrebbe essere pronta
Facciamo click su Build and Run
Verifichiamo che l’app funzioni correttamente
In caso contrario scorriamo tutte le proprietà di IB e del codice
In molti casi l’errore s’annida in un riferimento inesistente in IB
Altre volte mancano le dichiarazioni forward o properties non
sintetizzate
77. Prima di terminare
Alcuni riferimenti
Twitter @simonekalb
LinkedIn Simone Kalb
email: simone@nodelay.org
78. Prima di concludere (ancora..)
Un ringraziamento speciale al Java User Group Sardegna
ONLUS e a Massimiliano Dessì
Un altro ringraziamento particolare a tutti voi che siete
intervenuti qui stasera
Le slides sono disponibili su ºÝºÝߣShare
Per qualsiasi altra cosa chiedete pure..