2010-07-15 19 views
36

Stavo solo pensando, dato che puoi trattare Blocchi come oggetti se ne creo due e poi li aggiungo ad un NSArray c'è un modo per eseguirli dall'array?Esecuzione di blocchi da NSArray?

int (^Block_001)(void) = ^{ return 101; }; 
int (^Block_002)(void) = ^{ return 202; }; 
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil]; 

EDIT: Aggiornamento per la chiarezza Per @ di davedelong eccellente risposta

int (^Block_001)(void) = [^{ return 101; } copy]; 
int (^Block_002)(void) = [^{ return 202; } copy]; 
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil]; 

[Block_001 release]; 
[Block_002 release]; 
+2

Bel set di risposte .... Ho visto il titolo e speravo in alcuni semplici punti Rep. La gente l'ha coperto abbastanza bene. :) – bbum

+0

Solo un rapido punto, se non copi/rilasci il blocco sarà in pila ... Quindi, se lo stack viene distrutto, l'app si bloccherà? – fzaziz

risposta

29

Certo, basta invocare con () come qualsiasi altro blocco, ma è necessario typecast il valore si recuperano da NSArray. Ecco un esempio (con una typedef aggiunto, perché altrimenti la mia testa fa male):

typedef int (^IntBlock)(void); 
IntBlock Block_001 = ^{ return 101; }; 
IntBlock Block_002 = ^{ return 202; }; 
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil]; 
int x = ((IntBlock)[array objectAtIndex:0])(); // now x == 101 
+0

ok, quindi non avendo familiarità con i puntatori di funzione sto ottenendo questo giusto? Il typedef sta definendo "IntBlock" che è un puntatore a un blocco che restituisce un int e non accetta argomenti. Penso di aver capito, e guardando l'alternativa (che sono abbastanza sicuro di sbagliare), apprezzo la tua decisione di andare con il typedef :) Molto apprezzato. – fuzzygoat

+0

Sì, ce l'hai. –

+1

Non è necessario eseguire il cast. Funziona bene per 'int (^ block)() = [array objectAtIndex: 0]'. Un puntatore è un puntatore è un puntatore, dopo tutto, almeno nei linguaggi di basso livello come 'C' e le sue derivate. – aroth

6

Certo che puoi.

int (^x)(void) = [array objectAtIndex:0]; 
printf("%d\n", x()); // prints 101. 
+0

L'ho preso in considerazione, molto interessante. Puoi semplicemente chiarire per me, ho ragione a riferirmi a "int (^ x) (void)" come puntatore a un blocco? Sto solo cercando di assicurarmi che la terminologia sia corretta. – fuzzygoat

60

@KennyTM e @ Davide sono corretti, ma il codice è potenzialmente sbagliato. Ecco perché:

Quando si crea uno NSArray con oggetti, verranno inseriti gli oggetti inseriti in retain. Nel caso dei blocchi, sta utilizzando la funzione Block_retain. Ciò significa che l'array ha mantenuto i blocchi che hai creato, ma che vivono nello stack (i blocchi sono uno degli esempi molto rari di oggetti Objective-C che possono essere creati sullo stack senza scavare trucchi assurdi). Ciò significa che non appena termina questo metodo, la matrice ora punta alla spazzatura, perché i blocchi che stava puntando a non esistono più. Per farlo correttamente, si dovrebbe fare:

int (^Block_001)(void) = [^{ return 101; } copy]; 
int (^Block_002)(void) = [^{ return 202; } copy]; 
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil]; 

[Block_001 release]; 
[Block_002 release]; 

Invocando copy sul blocco, si sta muovendo in modo esplicito il blocco al largo della pila e sul mucchio, dove si può rimanere in modo sicuro dopo che il metodo/uscite di funzione . Quindi, dopo aver aggiunto i blocchi all'array, è necessario bilanciare lo copy (a causa della regola NARC) con una chiamata successiva a release. Ha senso?

+0

Ciao Dave, sì capisco, non ero a conoscenza di blocchi creati nello stack (solo iniziato a guardare i blocchi oggi). Molto apprezzato. – fuzzygoat

+0

Eccellente punto sulla necessità di copiare –

+0

Ciao Dave, ho trovato questa domanda e la risposta accettata di David Gelhar così l'ho implementata e ha funzionato abbastanza bene, ** non ha fatto ** crash. Leggendo ulteriormente, la tua risposta ha avuto un senso ma non spiega perché il codice di david non si blocca (immediatamente?). Hai qualche idea? – Tieme

Problemi correlati