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…

In questo post realizzeremo una particolare versione di “Indovina il numero” e la chiameremo FirstApp. Più avanti riscriveremo la stessa applicazione con metodi diversi, ad esempio creando manualmente un UIView o lasciando da parte Interface Builder.

L’applicazione già fatta, se volete solo scaricarla, è disponibile sul mio Google Code repository:

1 – Iniziamo

Apriamo XCode, dal menu File selezioniamo New Project e scegliamo, per questa versione, di partire dal classico View-Based Application (la prossima volta partiremo da Window-Based Application ottenendo lo stesso identico risultato). Chiamate il progetto FirstApp e salvatelo dove più vi fa comodo.

XCode New Project

Come noterete sto usando ancora la versione di XCode per le SDK 2.2.1, in quanto le SDK 3.0 non sono ancora “molto” stabili. Tenete bene a mente quest’immagine in quanto con la nuova versione di XCode alcuni template non saranno proprio identici e alcune cose cambieranno. Tuttavia per ora non vi dovete preoccupare di questo a meno che non state già utilizzando l’ultima release di XCode.

viewcontrollerIn questa versione useremo Interface Builder quindi, per prima cosa, andremo a disegnare la nostra interfaccia utente. Apriamo dunque la cartella Resources e fate doppio click su FirstAppViewController.xib. Questo file è proprio di Interface Builder, come il file MainWindow.xib (vedi anche l’estensione del file X Interface Builder).
Eventuali altri controller saranno posizionati sempre in questa cartella. Le restanti cartelle contengono tutti gli altri file della nostra applicazione e, in particolare, noi lavoreremo molto su quelli presenti nella cartella Classes.
Tornando ad Interface Builder ci troveremmo davanti ad una schermata vuota che rappresenta la nostra View, il contenitore dove saranno posizionati gli oggetti UIKit della nostra interfaccia utente. Questo oggetto visivo che stiamo guardando tramite Interface Builder è collegato al file FirstAppViewController.m (e .h) presente nella cartella Classes.

library Nella finestra Library troviamo tutti i componenti visivi per creare interfacce standard, piacevoli ed accessibili sul nostro Apple iPhone.
Questi sono comodamente ordinati per tipologia (vedi cartelle azzurre in alto). Per inserirli nella nostra View è sufficiente selezionare il componente dalla fienstra Library e trascinarlo all’interno della nostra finestra View, dove potremmo posizionarlo, ridimensionarlo e configurarlo a nostro piacimento (tutte cose fattibili anche da codice, come vedremo prossimamente).
Prima di proseguire, se è la prima volta che lavorate con Interface Builder, divertitevi un po’ provando i vari componenti e, quando ne avrete abbastanza, fate in modo di ottenere qualcosa di simile all’immagine mostrata qui sotto, ovvero un titolo realizzato con il componente UINavigationBar, un testo introduttivo (UILabel), un campo testo per l’inserimento del numero da indovinare (UITextField) e – finalmente – un semplice bottone (UIButton) per verificare se abbiamo indovinato:

view

L’impostazione dei componenti in Interface Builder avviene tramite una particolare finestra divisa sempre in quattro schede: attributes, connections, size e identity, una sorta di “ispettore” dei componenti. In base al componente selezionato la finestra Identity si configura con le appropriete caratteristiche relative al componente. Se selezioniamo la UINavigationBar, ad esempio, avremmo a disposizioni tutte le impostazioni possibili per questo tipo di componente.

ispettore

2 – Codice

Adesso che abbiamo stabilito e posizionato i nostri componenti visivi per l’interfaccia, andiamo a scrivere un po’ di codice per manipolarli. Prima di tutto apriamo il file FirstAppViewController.h e facciamolo diventare così:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//
//  FirstAppViewController.h
//  FirstApp
//
//  Created by Giovambattista Fazioli on 19/06/09.
//  Copyright Saidmade srl 2009. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface FirstAppViewController : UIViewController {
    IBOutlet UITextField        *numero;
    IBOutlet UIButton           *bottone;
    int                         numeroACaso;
}

-(IBAction)controllaNumero;
 
@end

Le righe 12, 13 e 14 definiscono le “variabili” del nostro Game. Le prime due sono dei puntatori ai nostri oggetti grafici inseriti con Interface Builder: il campo testo e il bottone. IBOutlet, davati al tipo, serve a creare un link, una referenza, verso l’interfaccia .xib di Interface Builder. Infatti, nel caso volessimo creare i nostri componenti esclusivamenti tramite codice, senza passare per Interface Builder, basta eliminare la IBOutlet, in quanto inutile. La riga 17, invece, definisce un metodo (un messaggio-evento) che vogliamo far scattare quando si clicca il bottone. In questo file .h (header file) abbiamo eseguito solo definizioni. L’implementazione del codice vero e proprio avviene nel corrispettivo file .m: FirstAppViewController.m. Cliccando si CMD+ALT+FRECCIA SU si passa alternativamente dal file .h al file .m. Andiamo quindi ad editare FirstAppViewController.m. Prima di tutto eliminiamo i commento al meotdo viewDidLoad (33 esima riga circa) e facciamolo diventare:

1
2
3
4
5
6
7
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
   
    numeroACaso = 1 + arc4random() % 10;
    NSLog(@"Numero pensato %d", numeroACaso);
}

viewDidLoad è uno dei metodo richiamati all’avvio dell’applicazione. Se volete corrisponde un po’ al document onload di Javascript o al $(document).ready() di jQuery. Le righe che ho aggiunto sono la 5 e la 6. La 5, in particolare, crea un numero casuale compreso da 1 a 10! La riga numero 6, invece, è solo per debug e stampa sulla console il numero generato. Adesso scriviamo il codice (l’impementazione) del metodo controllaNumero() che abbiamo definito nel file FirstAppViewController.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-(IBAction)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 = @"";
}

Questo codice, l’ultimo che scriveremo prima di passare nuovamente a Interface Builder, possiamo definirlo come il cuore del sistema, o meglio del gioco. Esso, infatti, verifica se il numero inserito nel campo testo (UITextField) è minore, maggiore o uguale al numero “pensato” dal nostro iPhone. In base all’esito mostra un alert. La riga 2, come sempre, è solo per debug e stampa sulla console un messaggio quando clicchiamo il bottone. La riga 4, invece, è interessante; questa trasforma il contenuto testuale del nostro campo testo in un intero numerico. Questo è necessario per confrontare il numero casuale numeroACaso con il numero inserito dall’utente. In Objective-C, come nel C, non esistono conversioni di tipo implicite, come il altri linguaggi ad alto livello che non supportano la tipizazzione delle variabili in senso strict. In alcuni linguaggi, infatti, si possono confrontare stringhe e interi senza eseguire nessuna conversione esplicita o casting.

La riga 5 prepara un puntatore ad un stringa message che conterrà la risposta da visualizzare nell’alert. Le righe dalla 9 alla 17 controllano il numero inserito dall’utente con il numero casuale e ne traggono le dovute conseguenze. Ho inserito appositamente queste “if” brutali per rendere il più chiaro possibile il codice. In alternativa avremmo potuto usare:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int decisione = ( (numeroInserito - numeroACaso) < 0 ) ? -1 : ( (numeroInserito - numeroACaso) ? 1 : 0 );

switch( decisione ) {
    case -1:
        message = @"Troppo basso...";
        break;
    case 1:
        message = @"Troppo alto...";
        break;
    case 0:
        message = @"Bravo hai indovinato";
        // ricominciamo...
        numeroACaso = 1 + arc4random() % 10;
        NSLog(@"Numero pensato %d", numeroACaso);
        break;
}

Uniamo il code con Interface Builder

Torniamo adesso su Interface Builder, cliccando sempre il file FirstAppViewController.xib. Quello che andremo a fare ora permetterà di linkare l’interfaccia visiva preparata con Interface Builder e il codice che abbiamo scritto, in particolare con i componenti evidenziati con IBOutlet. I componenti che dobbiamo linkare al nostro codice sono il campo testo e il bottone, definiti nella definizione dell’interfaccia nel file FirstAppViewController.h. A questi gli avevamo dato il nome rispettivamente di numero e bottone. Da Interface Builder abbiamo vari modi per linkare i componenti visivi con il codice, uno dei più semplici è quello di cliccare con il tasto destro del mouse sul nostro componente visivo, ad esempio il campo testo (UITextField):

iboutlet

Questa finestra, diversa per ogni componente, ci mostre tutto quello che possiamo “linkare” con il codice. In particolare a noi interessa l’ultima voce, quella nella sezione Referencing Outlets: New Referencing Outlet. Clicchiamo sul “cerchietto” posto a destra e – mantenendo premuto il tasto del mouse – trascinatelo nella finestra princiaple FirstAppViewController.xib sopra l’icona FirstAppViewController (File’s Owner):

viewcontroller-link

Rilasciando il tasto del mouse apparirà un menu con l’elenco di tutte le “variabili” (properties) IBOutlet e definite come UITextField:

menu-outlet

Nel nostro caso selezioniamo numero. Ripetiamo lo stesso identico procedimento anche per il bottone, con l’aggiunta che per quest’ultimo avevamo definito anche un evento: - (IBAction) controllaNumero;. Alla fine otteremo:

ibaction

Conclusioni

Se avete fatto tutto in modo corretto abbiamo finito! Il nostro giochino è pronto. In caso potete scaricare il sorgente completo qui. Ovviamente questo è solo un esempio e mancano alcuni dettagli per farlo diventare una vera applicazione; dalle icone 57×57 ai controlli sul numero inserito e altri dettagli ancora. Il processo di sviluppo qui illustrato può essere variato, passando ad esempio per Interface Builder una volta sola, cioè alla fine: prima si scrive tutto il codice e poi si va su Interface Builder a linkare gli oggetti. In questo esempio siamo passati subito su Interface Builder per disegnare la bozza della nostra interfaccia, essendo l’applicativo semplice.

La prossima volta vedremo come realizzare il medisimo “giochino” senza usare Interface Builder.

Non ci sono commenti per questo Post

Lascia un commento

TAG XHTML PERMESSI: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> INSERIMENTO CODICE:
<pre></pre> // blocco generico
                   <code></code> // blocco generico
                   [cc_actionscript][/cc_actionscript] // Actionscript
                   [cc_actionscript3][/cc_actionscript3] // Actionscript 3
                   [cc_css][/cc_css] // CSS Style Sheet
                   [cc_html][/cc_html] // HTML
                   [cc_js][/cc_js] // Javascript
                   [cc_objc][/cc_objc] // Objective-C
                   [cc_php][/cc_objc] // PHP
                   [cc_sql][/cc_sql] // SQL