2012-11-27 6 views
11

Nei documenti Apple: Un blocco letterale (ovvero,^{...}) è l'indirizzo di un struttura dati stack-locale che rappresenta il blocco. Il campo di applicazione della struttura di dati stack locale è quindi l'istruzione composta racchiude, si consiglia di evitare gli schemi riportati nei seguenti esempi:Non so quali schemi di blocco dovrei evitare per lo scope letterale nell'obiettivo-c

void dontDoThis() { 

    void (^blockArray[3])(void); // an array of 3 block references 

    for (int i = 0; i < 3; ++i) { 

     blockArray[i] = ^{ printf("hello, %d\n", i); }; 

     // WRONG: The block literal scope is the "for" loop. 
    } 

    //for example I invoke the block here 
    blockArray[1](); 
    } 


void dontDoThisEither() { 

    void (^block)(void); 

    int i = random(): 

    if (i > 1000) { 

     block = ^{ printf("got i at: %d\n", i); }; 

     // WRONG: The block literal scope is the "then" clause. 

    } 

    // ... 

    } 

Non so quali modelli devo evitare. Sembra che potrei invocare il blocco in cui ha lo stesso ambito letterale della definizione di blocco, ad esempio dietro l'istruzione "if" o "for". Potresti per favore aiutarmi a spiegarlo?

Qui è il link https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1

risposta

9

Penso un'analogia con puntatori è la seguente.

void foo() { 
    int *block = NULL; 
    { 
    int a; 
    block = &a; 
    } 
    // `block`, even though defined here, points to 
    // an invalid memory address. 
} 

In generale, il blocco letterale in sé esiste solo nel blocco è definito, in modo al momento di lasciare che il blocco, le scompare letterali (come la variabile a fatto nell'esempio di cui sopra), e si è lasciato con un puntatore penzolante.

Per questo motivo, i blocchi vengono solitamente copiati nell'heap per un utilizzo futuro. Il codice non ARC utilizza block_copy e gli amici. La copia nell'heap cattura anche tutte le variabili rilevanti utilizzate dal blocco (che potrebbero creare cicli di conservazione).

In pratica, tutto ciò è completamente evitato dall'uso di ARC, proprietà e classi. Definisci una proprietà copy nella tua classe, quindi assegna solo blocchi ad essa. Se si lascia che il compilatore generi getter/setter, il letterale del blocco verrà automaticamente copiato nell'heap.

+0

Grazie. E vuoi dire che il blocco dovrebbe essere dichiarato come una proprietà copiata, invece di una variabile stack nel metodo? –

+0

o posso dichiarare un blocco come variabile globale? In realtà, dovrebbe essere memorizzato anche nello stack locale, visto ovunque. –

+0

Trovato! Grazie mille. L'istruzione composta di blocchi ha un valore intero sostanzialmente simile all'indirizzo di una struttura dati locale stack. –

0

Stavo leggendo la documentazione di Apple sui blocchi e ho fatto un po 'più di ricerche su questa parte. Mi sembra che con ARC il secondo codice di esempio sia perfetto. Non ho provato il primo esempio. L'idea generale nella risposta accettata è corretta. Tuttavia, con ARC, quando si assegna il blocco letterale (NSStackBlock) a una variabile locale, il blocco viene copiato nell'heap e, se si ispeziona il blocco, si noterà che è un NSMallocBlock. Ho anche fatto riferimento a questo blog su questo argomento https://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

Problemi correlati