Salve a tutti, in questo mio primo articolo vi propongo un argomento molto interessante: parleremo dei blocchi e della programmazione “block-based”. Vedremo a breve (più avanti nell’articolo) a cosa serve e come può essere sfruttata una programmazione di questo tipo, prima di tutto, però, occorre rispondere ad una domanda: cos’è un blocco?
Un blocco non è nient’altro che una porzione di codice racchiusa tra parentesi graffe {codice} e preceduta dal simbolo ^ (caret).
Queste porzioni di codice definiscono delle vere e proprie funzioni dichiarate “on the fly” ed eseguite poi in un certo momento durante il run loop. Nel Foundation Kit vi sono diversi metodi che utilizzano nella loro sintassi i blocchi. Prendiamone uno ad esempio dalla classe NSDictionary:
- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block
Questo metodo serve ad enumerare le chiavi e gli oggetti contenuti in un’istanza della classe NSDictionary applicando ad essi la funzione definita nel blocco (block) dichiarato dopo i due punti.
Esaminiamo la sintassi della dichiarazione:
- il ( ^ ) ci dice che si tratta di un blocco;
- a precederlo è la definizione del tipo di dato che la funzione definita nel blocco restituisce (in questo caso void ad indicare che non vi è alcun dato restituito dalla funzione);
- a seguire, tra le parentesi, vi sono gli argomenti forniti alla funzione (nel nostro caso la chiave e il corrispondente oggetto nel dizionario più un puntatore ad una variabile di tipo BOOL (*stop) che, se settata a YES nella funzione, interromperà l’iterazione).
Nella definizione del blocco sia il tipo del dato restituito, che gli argomenti, sono opzionali, per cui se non ci sono argomenti si può utilizzare la sintassi ^{ }.
Quindi se volessimo dichiarare e definire un blocco di nome “quadrato” che effettua il quadrato di un numero dovremmo scrivere:
double (^quadrato) (double numero) = ^(double numero) { return numero * numero};
Se vogliamo invece racchiudere un blocco in una variabile dobbiamo usare la funzione typedef e definire quella variabile in questo modo:
typedef double (^operazione_t) (double numero);
e quindi:
operazione_t quadrato = ^(double numero) { return numero * numero};
Per comprendere ancora meglio:
typedef void (^enumeratingBlock) (id key, id obj, BOOL *stop);
sarebbe la definizione di una variabile che può contenere il blocco dichiarato nel metodo preso ad esempio.
Ci sono altri due aspetti interessanti da considerare.
Il primo è che i blocchi possono essere considerati dei veri e propri oggetti con le stesse regole di gestione della memoria (un blocco è rilasciato dopo la sua esecuzione oppure quando un oggetto che lo ritiene è a sua volta deallocato). Possiamo ad esempio inserire i blocchi in un’array o in un dizionario (come ho fatto nel codice che vi allego).
Il secondo è che le variabili locali dichiarate prima del blocco possono essere usate all’interno del blocco, ma come variabili read-only:
double stopValue = 55.8;
[aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
NSLog(@“value for key %@ is %@”, key, value);
if ([value doubleValue] == stopValue) {
*stop = YES;
}
}];
a meno che non siano precedute da _block o non si tratti di una variabile di istanza, in questi casi rimangono variabili read-write.
Le variabili dichiarate prima del blocco e da esso utilizzate sono automaticamente ritenute e rilasciate quando il blocco stesso è rilasciato.
A cosa servono i blocchi?
Ma a cosa servono i blocchi? Non potreste mai immaginare a quante cose possono servire! Vi faccio un piccolo elenco:
- Enumerazione (come nel caso preso ad esempio)
- Animazione delle View
- Ordinamento (ordina questi oggetti utilizzando questo blocco come metodo di comparazione)
- Error handling (se si verifica questo errore esegui questo blocco)
- Notifiche (quando qualcosa succede esegui questo blocco)
- Completion handling (quando questa operazione è terminata esegui questo blocco).
Qui trovate un programmino con il quale ho realizzato una calcolatrice che esegue solo tre operazioni. Ciò che è interessante è che la definizione di queste operazioni è fatta con blocchi inseriti in un dizionario di operazioni possibili, estendibile in modo semplice in qualsiasi momento.
Nel prossimo articolo, vedremo con un esempio veloce quanto possa essere comodo utilizzare questo tipo di sintassi durante lo sviluppo di applicazioni iPhone e iPad.
Alla prossima!











5 Responses to “L#015 – Programmazione “block-based”: i blocchi in Objective-C”
14 Marzo 2011
danieleCarino,
sarebbe ancora meglio con un esempio di block per animare una view.
14 Marzo 2011
MuffaSi, articolo utile.
Sarebbe comodo anche un’esempio (oltre a quello di animare una view come suggeriva Daniele) per creare una coda FIFO di operazioni.
14 Marzo 2011
Francesco GuidaSarete presto accontentati 😉
15 Marzo 2011
LorenzoQuesti articoli guida son sempre più interessanti e ben descritti. Complimenti davvero 🙂
20 Marzo 2011
spaccaSolo una correzione… quando vuoi utilizzare delle variabili esterne al block per read/write devi utilizzare __block. Non so se l’underscore non viene visualizzato bene sul sito o cosa ma volevo solo precisare che ce ne sono 2 di underscores prima della parola block, no uno.
__block int i = 0; per esempio…