Come creare e utilizzare i blocchi

Objective-C

Con l’ultima versione di Objective-C e iOS7 Apple ha aggiunto la possibilità di utilizzare i famosi “blocks”, in italiano Blocchi.

Questo tipo di oggetto contiene dentro di se una porzione di codice che può quindi essere eseguita o trasportata tra altri oggetti, passata come argomento dei metodi ed altro.
In realtà è qualcosa di un po’ più complesso ma per iniziare può andare bene.

La sintassi per la dichiarazione e l’utilizzo dei blocks è un po’ particolare tanto che hanno creato questo simpaticissimo sito per ricordarcela, vediamo quindi come si dichiara e si implementa un blocco:

returnType (^blockName)(parameterTypes) = ^returnType(parameters) { };

Sì, è molto particolare.

Adesso facciamo un esempio pratico di dichiarazione ed utilizzo:

- (void)viewDidLoad {
	[super viewDidLoad];
	
	NSInteger (^blockTest)(NSInteger, NSInteger) = ^NSInteger(NSInteger numberOne, NSInteger numberTwo){
		
		NSInteger result = numberOne + numberTwo;
		return result;
		
	};
}

Abbiamo creato un blocco chiamato “blockTest” che ritorna un NSInteger e vuole come parametri due NSInteger.

Per utilizzarlo possiamo ci basta scrivere quindi:

NSInteger result = blockTest(2, 3);

Possiamo passare anche il blocco come parametro di un metodo:

- (NSInteger)testBlock:(NSInteger (^)(NSInteger, NSInteger))block
{
	NSInteger numberOne = 2;
	NSInteger numberTwo = 3;
	
	return block(numberOne, numberTwo);
}

UIKit utilizza i blocchi ormai per moltissimi scopi, ad esempio UIView li utilizza per eseguire le animazioni.
Ci viene molto utile  quando vogliamo eseguire una porzione di codice prima di un’altra e quindi solo alla fine far eseguire del codice specifico (i famosi completion blocks).

Facciamo un altro esempio. Assumiamo di voler scaricare un file e solo dopo averlo scaricato, volerlo aprire.
Creiamo quindi un metodo che scarica il file da un URL e un blocco che accetta come parametro una stringa, il path finale del file scaricato:

- (void)downloadFileAtURL:(NSURL*)url withCompletion:(void(^)(NSString* filePath))completion
{
	//	codice per scaricare il file
	
	NSString* finalFilePath = @"...";
	
	if (completion)
	{
		completion(finalFilePath);
	}
}

Quindi, il file viene scaricato e poi, quando finito viene passato il path finale al completion block.

Quando andiamo ad utilizzare questo metodo scriveremo semplicemente:

[self downloadFileAtURL:[NSURL URLWithString:@"http://www.example.com/file.zip"] withCompletion:^(NSString *filePath) {
		
	NSLog(@"file downloaded at %@", filePath);
		
}];

Le possibilità ovviamente sono infinite, il limite è la nostra fantasia e alle nostre necessità.

Curiosità

Quando passate un blocco ad un metodo ricordatevi di controllare che il blocco esista, altrimenti se passate “nil” invece che un blocco esistente l’app andrà in crash.

Scritto il