Lavorando con Interface Builder può venire spontaneo usare un oggetto UIImageView per impostare lo sfondo del nostro view controller. In alternativa è possibile eliminare questo oggetto, risparmiando così un po’ di memoria, e sfruttare la view associata al view controller. Basta inserire nel nostro view controller:
Articoli con Tag ‘Interface Builder’
Very short snippet: la UIView per visualizzare un’immagine
Objective-C: come ruotare un’immagine nello spazio 3D
La classe UIView espone un puntatore al layer (CALayer), un oggetto di più basso livello con innumerevoli potenzialità. Il layer mette a disposizione tutta una serie di metodi e proprietà legati alla visualizzazione del contenuto della view. Ad esempio è possibile manipolare il contenuto di una view nello spazio tridimensionale. Nell’esempio che riporto è interessante notare che il codice è semplice, e il tutto è realizzato sfruttando Interface Builder:

Come localizzare immagini e viste di Interface Builder
Dopo aver illustrato come localizzare le nostre stringhe in Xcode, vediamo adesso quanto risulta semplice – applicando la medesima tecnica – localizzare immagini e viste/interfacce realizzate con Interface Builder.
Localizzare risorse grafiche
Il processo, come accennato, è il medesimo; se abbiamo un’immagine già inserita nelle nostre risorse, o ne inseriamo una nuova, e vogliamo “localizzarla” – cioè gestire due o più immagini in base alle lingue supportate – basterà cliccare con il tasto destro sull’immagine (Adium.png in questo esempio) e selezionare Get Info:

Clicchiamo Make File Localizable in basso a sinistra.

Clicchiamo su Add Localization e inseriamo Italian:

In modo da ottenere:

La nostra immagine viene spostata (fisicamente, una delle rare volte in cui quello che accade nell’alberatura Xcode si riflette sul filesystem) sotto le cartelle virtuali English.lproj e Italian.lproj esattamente come accadeva con il testo:

A questo punto ognuna delle cartelle English.lproj e Italian.lproj contiene una stessa versione dell’immagine. Questa immagine è manipolabile all’interno di Interface Builder, dove ne vedremo – per default – la versione inglese.
Arrivati a questo punto, basta sovrascrivere uno (o entrambi i file Adium.png) per ottenere una localizzazione delle immagini “lampo”.
Localizzare i file XIB
Anche le interfacce costruite con Interface Builder possono essere localizzate nella loro interezza, quando lo si ritiene necessario. Il procedimento è identico a quello svolto con le risorse grafiche: aggiungiamo un ViewController (ad esempio infoViewController) con interfaccia XIB, lo selezioniamo, scegliamo Get Info dal menu contestuale, rendiamo il file localizzabile, aggiungiamo la localizzazione in italiano:

Cliccando su English o su Italian si aprirà Interface Builder! Questa volta, sul filesystem, noteremo che sono state create due cartelle (English.lproj e Italian.lproj) all’interno della classica cartella Classes. Entrambe avranno il loro file infoViewController.xib. La comodità, in questo, risolta evidente nel codice; quando andremo ad istanziare il nostro controller si avrà un codice “pulito” di questo tipo:
1 2 | InfoViewController *info = [InfoViewController alloc]; [self.view addSubview:info.view]; |
Come vedete non c’è traccia di nessuna dichiarazione relativa alla localizzazione, totalmente gestita da sistema. Le due interfacce, ovviamente, possono essere completamente differenti, in quanto risultano a tutti gli effetti come due file XIB separati.
iPhone SecondApp: indovina il numero – parte 2
Come anticipato in iPhone FirstApp: indovina il numero – parte 1 vediamo come realizzare un’applicazione per Apple iPhone senza usare Interface Builder! Anzi, elimineremo fisicamente i file di Interface Builder creati dal wizard di Xcode. Alla fine di questo post, quindi, avremo un’applicazione identica, in tutto e per tutto, a quella realizzata nella parte prima, con la differenza che realizzeremo tutti i nostri componenti visivi, compresa la Window principale, completamente da codice.
L’applicazione già fatta, se volete solo scaricarla, è disponibile sul mio Google Code repository:
Vorrei far notare da subito come lo ZIP di questo esempio pesi meno di quello della scorsa volta!
Creiamo il progetto
Iniziamo creando il nostro progetto SecondApp (per distinguerlo da FirstApp), anche se questa volta sceglieremo Window-based Application:

Adesso andiamo ad eliminare tutto ciò che riguarda Interface Builder. Eliminiamo il file MainWindow.xib, situato nella cartella Resources: eliminatelo anche dal file system, quindi selezionate Also Move to Trash. Selezionate, poi, il file SecondoApp-info.plist ed eliminate il riferimento alla MainWindow nella casella Main nib file base name:

A questo punto non abbiamo più nessuna Window, almeno tramite Interface Builder. Quindi apriamo il file main.m, situato in Other Sources, e modifichiamo la funzione main() in questo modo:
1 2 3 4 5 6 7 8 9 10 11 | int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // avendo eliminato il file .xib abbiamo perso il puntamento // all'app delegate, quindi lo passiamo a "mano" int retVal = UIApplicationMain(argc, argv, nil, @"SecondAppAppDelegate"); [pool release]; return retVal; } |
Apriamo quindi SecondAppAppDelegate.m e creiamo la Window principale via codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | - (void)applicationDidFinishLaunching:(UIApplication *)application { // ottiene le dimensioni delle schermo (320, 480) CGRect windowRect = [[UIScreen mainScreen] applicationFrame]; // creiamo una finestra - visto che abbiamo fatto bye bye a Interface Builder UIWindow *mainWindow = [[UIWindow alloc] initWithFrame:windowRect]; // impostiamo il background della Window a giallo, per differenziarlo // dalla precedente applicazione FirstApp [mainWindow setBackgroundColor:[UIColor yellowColor]]; [self setWindow:mainWindow]; [window makeKeyAndVisible]; [mainWindow release]; } |
Potete già provare l’applicazione; se appare una window gialla avete fatto tutto bene!
Nel file SecondAppAppDelegate.h possiamo eliminare IBOutlet, necessario solo se si usa Interface Builder. Inoltre aggiungiamo qui le nostre variabili globali che, nella scorsa volta, avevamo inserito nel Controller. Modifichiamo quindi il file SecondAppAppDelegate.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #import <UIKit/UIKit.h> @interface SecondAppAppDelegate : NSObject <UIApplicationDelegate> { UIWindow *window; UITextField *numero; UIButton *bottone; int numeroACaso; } @property (nonatomic, retain) UIWindow *window; - (void)controllaNumero; @end |
Anche in questo caso abbiamo preparato la definizione del metodo controllaNumero, come la scorsa volta, ma abbiamo eliminato l’indicazione IBAction, in quanto non stiamo usando Interface Builder.
Costruiamo l’interfaccia da codice
E’ giunto il momento di creare tramite codice tutti i componenti della nostra interfaccia. Torniamo nel file SecondAppAppDelegate.m, posizioniamoci prima del [mainWindow release] ed inseriamo il seguente codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | // crea la barra del titolo UINavigationBar *myNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)]; myNavigationBar.barStyle = UIBarStyleDefault; UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"Indovina un numero"]; [myNavigationBar pushNavigationItem:navigationItem animated:NO]; [window addSubview:myNavigationBar]; // crea la label UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 50, 300, 80)]; myLabel.backgroundColor = [UIColor clearColor]; myLabel.numberOfLines = 2; myLabel.text = @"iPhone ha pensato un numero da 1 a 10, prova ad indovinarlo?"; [window addSubview:myLabel]; // crea il text input numero = [[UITextField alloc] initWithFrame:CGRectMake(10, 120, 300, 30)]; numero.borderStyle = UITextBorderStyleRoundedRect; numero.textAlignment = UITextAlignmentCenter; numero.keyboardType = UIKeyboardTypeNumberPad; numero.placeholder = @"Inserisci il numero"; [window addSubview:numero]; // crea il bottone bottone = [UIButton buttonWithType:UIButtonTypeRoundedRect]; bottone.frame = CGRectMake(10, 180, 300, 30); [bottone setTitle:@"Premi qui" forState:UIControlStateNormal]; [bottone addTarget:self action:@selector(controllaNumero) forControlEvents:UIControlEventTouchUpInside]; [window addSubview:bottone]; [myLabel release]; [navigationItem release]; [myNavigationBar release]; |
Dato che l’applicationDidFinishLaunching corrisponde alla viewDidLoad della scorsa volta, subito dopo il [mainWindow release]; inseriamo:
1 | numeroACaso = 1 + arc4random() % 10; |
Ora non ci rimane che implementare il metodo controllaNumero, che sarà identico (a parte il prototipo) a quello usato la scorsa volta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | - (void) controllaNumero { NSLog(@"Premuto bottone di controlla numero"); int numeroInserito = [numero.text integerValue]; NSString *message; NSLog(@"Il numero inserito è %d", numeroInserito ); if( numeroInserito <numeroACaso ) { message = @"Troppo basso..."; } else if (numeroInserito> numeroACaso ) { message = @"Troppo alto..."; } else if (numeroInserito == numeroACaso ) { message = @"Bravo hai indovinato"; numeroACaso = 1 + arc4random() % 10; NSLog(@"Numero pensato %d", numeroACaso); } UIAlertView *alertMessaggio = [[UIAlertView alloc] initWithTitle:@"Responso" message: message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertMessaggio show]; [alertMessaggio release]; numero.text = @""; } |
Abbiamo finito!
Conclusioni e considerazioni
Questo esempio non fa uso diretto di una UIView o di un UIViewController, proprio perchè volevo lasciarlo il più semplice e snello possibile e, anche, per dimostrare che non sono elementi sempre necessari. Tuttavia inserire gli oggetti direttamente nella window può avere un qualche senso in questo esempio ed in altri sporadici contesti. L’uso delle UIView e dei UIViewController portano comunque benefici in tantissimi altri casi, ein alcuni sono praticamente indispensabili; come avremo modo di vedere in futuro.
iPhone FirstApp: indovina il numero – parte 1
Il primo sorgente che mi è passato tra le mani era scritto in Basic e consisteva in poche righe di codice, per me illuminanti. Era un semplice giochino che generava un numero casuale da 1 a 10 e, tramite l’input da tastiera, verificava che il numero inserito era maggione, minore o uguale al numero casuale. Nonostante la sua rozza semplicità rimane, per me, uno dei migliori esempi – semplici, divertenti e pratici – per spiegare a chi non sa nulla di programmazione cosa s’intenda effettivamente per “programma per computer”. Così ho pensato di riproporlo per Apple iPhone, magari aiuterà qualcuno…
Hi phone
Da oggi inauguro una nuova sezione (categoria per essere corretti) dedicata allo sviluppo di applicazioni su Apple iPhone! Premetto da subito che molti degli articoli che pubblicherò avranno un “taglio” in linea con lo spirito di questo blog, cioè saranno in maggioranza per utenti avanzati. Tuttavia, come ho già fatto per altri argomenti, cercherò di essere il più chiaro possibile e, dove necessario, inserire qualche “concetto base” utile ad un pubblico più ampio.






Ultimi Commenti
Marco: Ti ringrazio moltissimo, mi hai illuminato
ho risolto impostando [cc_objc] //OptionViewController.m -...
Giovambattista Fazioli: @Marco: Ti consiglio un approccio credo più corretto. Se hai eseguito il subclass del tab...
Marco: Scusa lo spam.. ho notato che c’è un errore.. ecco la correzione [cc_objc] /** PrimaClasse.h **/ #import...
Marco: dimenticato.. in [cci]OptionViewController[/cci ] il [cci]@syntetize[/cci] del delegato l’ho messo
luigi: molto chiaro e semplice devo ammettere che anche scrivendo da un pà difficilmente uso delegati creati da...