2013-02-01 16 views
14

Ho recentemente venire attraverso un Apple document che mostra la seguente dichiarazione di proprietà per un blocco:Definizione blocchi di Objective-C come proprietà - le migliori pratiche

@interface XYZObject : NSObject 
@property (copy) void (^blockProperty)(void); 
@end 

Inoltre, questo articolo afferma:

Nota: è necessario specificare la copia come attributo della proprietà, poiché è necessario copiare un blocco per tenere traccia del suo stato acquisito al di fuori dell'ambito originale. Questo non è qualcosa di cui devi preoccuparti quando usi il conteggio dei riferimenti automatici, poiché avverrà automaticamente, ma è meglio che l'attributo property mostri il comportamento risultante. Per ulteriori informazioni, vedere Argomenti di programmazione dei blocchi.

Ho letto anche il suggerito Blocks Programming Topics ma non ho trovato nulla di rilevante lì.

Sono ancora curioso di sapere perché la definizione di una proprietà di blocco come "copia" è la migliore prassi. Se hai una buona risposta, prova a distinguere tra le differenze ARC e MRC, se ce ne sono.

Grazie

+0

NB, per i principianti che sono solo chiedendo come diavolo utilizzare un blocco :) http://stackoverflow.com/a/20760583/294884 – Fattie

risposta

23

Per impostazione predefinita i blocchi vengono creati nello stack. Significa che esistono solo nello scopo in cui sono stati creati.

Nel caso in cui si desideri accedervi in ​​seguito, è necessario copiarli nell'heap inviando un messaggio copy all'oggetto del blocco. ARC farà questo per te non appena rileva un blocco a cui è necessario accedere al di fuori dell'ambito in cui è stato creato. Come best practice si dichiara qualsiasi proprietà di blocco come copia, poiché è così che dovrebbe essere nella gestione automatica della memoria.

Leggi Stack and Heap Objects in Objective-C di Mike Ash per ulteriori informazioni sullo stack rispetto all'heap.

+0

Grazie per la risposta chiara, grande legame BTW – Stavash

+0

non dovrebbero anche essere dichiarato come settimana, nel caso in cui acquisisci te stesso e crei un ciclo di conservazione? – cfischer

+0

Assolutamente no, perché la maggior parte delle volte la proprietà sarebbe l'unico riferimento al blocco, quindi se la proprietà fosse debole, il blocco scomparirebbe immediatamente. – gnasher729

7

I blocchi sono assegnati per impostazione predefinita nello stack. Questa è un'ottimizzazione, poiché l'allocazione dello stack è molto più economica dell'allocazione dell'heap. L'allocazione dello stack significa che, per impostazione predefinita, un blocco cesserà di esistere quando l'ambito in cui è dichiarato esce. Quindi una proprietà di blocco con la semantica retain provocherà un puntatore pendente a un blocco che non esiste più.

Per spostare un blocco dallo stack sull'heap (e quindi dargli una normale semantica di gestione della memoria Objective-C e una durata estesa), è necessario copiare il blocco tramite [theBlock copy], Block_copy(theBlock), ecc. Una volta sul mucchio, il la durata del blocco può essere gestita secondo necessità mantenendola/rilasciandola. (Sì, questo si applica in ARC troppo, basta non c'è bisogno di chiamare -retain/-release te stesso.)

Così si vuole dichiarare la proprietà del blocco con copy la semantica in modo che il blocco viene copiato quando la proprietà è impostata, evitando un puntatore pendente a un blocco basato su stack.

+0

Tuttavia, le due risposte sopra sembrano implicare che questo deve essere fatto, ed è comunque fatto, automaticamente, da ARC - e l'unico motivo ** per includere la copia esplicitamente, è stilistico - "per ricordare a tutti" questo è ciò che sta realmente accadendo. Pensieri?? – Fattie

6

Le "migliori pratiche" a cui ti riferisci semplicemente dicono "Visto che ARC sta per copiare magicamente il tuo blocco, non importa quello che scrivi qui, è meglio che scrivi esplicitamente 'copia' in modo da non confondere le generazioni future guardando il tuo codice."

Spiegazione segue:

In genere, non dovrebbe essere necessario copiare (o mantenere) un blocco. Hai solo bisogno di fare una copia quando ti aspetti che il blocco venga utilizzato dopo la distruzione dell'ambito entro il quale è stato dichiarato.La copia sposta un blocco nell'heap.
-blocks Programmazione Argomenti: Utilizzo dei blocchi, blocchi Copia

Chiaramente, l'assegnazione di un blocco a una proprietà significa che potrebbe essere utilizzato dopo il campo di applicazione è stato dichiarato in è stato distrutto. Pertanto, secondo Blocchi argomenti di programmazione tale blocco deve essere copiato nell'heap con Block_copy.

Ma ARC si prende cura di questo per voi:

Blocks “solo lavoro” quando si passa blocca lo stack in modalità ARC, come ad esempio in un ritorno. Non è necessario chiamare Block Copy più.
- Transitioning to ARC

Si noti che questo non è sui retain semantica di blocco. Non c'è semplicemente alcun modo per il contesto del blocco di esistere senza essere spostato dallo stack (presto a essere spuntato) e su per l'heap. Quindi, indipendentemente da quali attributi si qualificano i tuoi @property con, ARC sta ancora per copiare il blocco.

+0

Nel caso in cui qualcuno sia preoccupato dell'efficienza o della funzionalità, una volta che un blocco è stato copiato, il risultato è immutabile e ulteriori tentativi di copia lo manterranno, come altre istanze immutabili. – gnasher729

+0

Ciao jenmore. Grazie per il post. Come ho chiesto prima, qual è la tua opinione ... "essere assolutamente chiari, infatti è il caso che se ometti completamente la copia, invece di averne una copia, in realtà il risultato, la gestione e l'esecuzione saranno completamente identici ?? " Cosa pensiamo? Saluti! – Fattie

Problemi correlati