Come eseguire codice in background o in un secondo thread

Objective-C

Quando il device esegue del nostro codice viene fatto all’interno del processo chiamato MainLoop e che viene eseguito contemporaneamente a molte altre cose, una di queste è l’aggiornamento dell’interfaccia grafica.
Per questo quando eseguite del codice pesante, la UI si blocca.

Per evitarlo e fare in modo che l’app non vada neanche in crash dobbiamo eseguire questo codice in background, cioè in un processo che viene eseguito in un altro thread.

E’ importante specificare da subito che non è consentito di eseguire codice sugli elementi dell’interfaccia grafica in un processo diverso da MainLoop. Se ci provate l’app andrà in crash.

Il metodo più veloce e semplice per eseguire del codice in background (ne esistono anche altri ma per adesso vediamo questo) è utilizzare Grand Central Dispatch (GCD), tecnologia sviluppata da Apple per ottimizzare l’esecuzione del codice.

Assumiamo di avere un array di molti elementi e di dover eseguire del codice molto pensante su ogni elemento. Solitamente scriveremo:

- (void)viewDidLoad {
	[super viewDidLoad];
	NSArray* objects = [NSArray new];
	[objects makeObjectsPerformSelector:@selector(doHeavyCalculations)];

	NSLog(@"Code executed");
}

Il metodo -makeObjectsPerformSelector: di NSArray permette di eseguire un selettore su tutti gli oggetti al suo interno. Ovviamente questi oggetti devono obbligatoriamente rispondere a quel metodo.

In questo modo però, se l’esecuzione del codice è molto pensante, vi ritroverete con l’applicazione che rimane bloccata finché non ha finito di eseguire tutto.

Con GCD invece possiamo fare:

- (void)viewDidLoad {
	[super viewDidLoad];
	
	NSArray* objects = [NSArray new];
	
	1.
	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
		
		2.
		[objects makeObjectsPerformSelector:@selector(doHeavyCalculations)];
		
		dispatch_async(dispatch_get_main_queue(), ^{
			
			NSLog(@"Code executed");
		
		});
	});
}

1.

Questa parte verrà eseguita in background. Quando avrà finito passerà avanti.

2.
Questa parte di codice viene eseguita nel MainLoop solo dopo aver finito la parte precedente.

E’ importante ricordarsi che ogni blocco eseguito in background deve avere un blocco che fa eseguire del codice nel MainLoop alla fine del processo:

dispatch_async(dispatch_get_main_queue(), ^{}.

Adesso potrete finalmente avere l’app veloce e snella!

Scritto il