2010-11-02 12 views
72

Vorrei archiviare il blocco objective-c in una proprietà per un uso successivo. Non ero sicuro di come farlo, quindi ho cercato un po 'su google e ci sono pochissime informazioni sull'argomento. Ma alla fine sono riuscito a trovare la soluzione e ho pensato che potesse valere la pena di condividerlo con altri neofiti come me.Come memorizzare i blocchi nelle proprietà in Objective-C?

Inizialmente ho pensato che avrei dovuto scrivere manualmente le proprietà per utilizzare Block_copy & Block_release.

Per fortuna ho scoperto che blocks are NSObjects e - copy/- release equivale a Block_copy/Block_release. Quindi posso usare @property (copy) per generare automaticamente setter & getter.

+1

Eventuali duplicati di [? Posso usare blocchi di Objective-C come proprietà] (http://stackoverflow.com/questions/3935574/can-i-use-objective-c-blocks-as-properties) Questa domanda è più recente di quella lì. –

+1

Codice di esempio completo, aggiornato fino alla data, spiegato semplicemente per i principianti: http://stackoverflow.com/a/20760583/294884 – Fattie

+1

Per i nuovi lettori, questa domanda estremamente vecchia è ora felicemente estremamente passata. Devi solo dire ** @ property (copy) void (^ doStuff) (void); ** con niente più o meno della copia. ora questo è spiegato chiaramente in cristallo (compreso il perché) in un certo numero di punti nella mela doco. non potrebbe essere più semplice; questa è l'intera risposta. In effetti, l'intera questione è di valore solo storico poiché ora usi solo Swift. – Fattie

risposta

130

Edit: aggiornato per ARC

typedef void(^MyCustomBlock)(void); 

@interface MyClass : NSObject 

@property (nonatomic, copy) MyCustomBlock customBlock; 

@end 

@implementation MyClass 

@end 

MyClass * c = [[MyClass alloc] init]; 
c.customBlock = ^{ 
    NSLog(@"hello....."); 
} 

c.customBlock(); 
+4

Qualcuno sa perché per i blocchi si dovrebbe usare (non anatomici, copia) e non (non anatomici, conservare)? Tipicamente viene usato retain e non riesco a trovarlo da nessuna parte che spieghi perché usare la copia per i blocchi. –

+0

@StevePotter davvero? Ho trovato un paio di domande rilevanti qui su SO in pochi secondi. Ad esempio: http://stackoverflow.com/a/4667422/115730 e i commenti su http://stackoverflow.com/a/3935677/115730 –

+27

Sì, Dave, davvero. Posso anche cercare e vedere quelli. Le spiegazioni erano vaghe come se usassi la copia "per far sì che sopravvivessero allo stack frame". Ho pensato che mantenere l'oggetto avrebbe fatto anche quello. Nessuno ha spiegato in che modo i blocchi sono allocati allo stack. Tuttavia, un commento si collegava a un articolo - http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html che lo spiegava bene. Vedi sotto "I blocchi sono oggetti un po 'strani". Quindi grazie! –

95

In alternativa, senza il typedef

@property (copy, nonatomic) void (^selectionHandler) (NSDictionary*) ;

+16

Per chiarire, poiché la sintassi è così opaca, questa è una proprietà di blocco denominata "selectionHandler" che accetta un argomento NSDictionary * e restituisce void. –

+0

Non penso sia così difficile da leggere, ma sono d'accordo che sembra più carino con typedef. Tendo a scrivere una serie di typedef per i parametri che di solito voglio passare: PFObjectBlock, PFStringBlock, PFArrayBlock, PFErrorBlock, ecc. – Besi

+0

id, SEL, IMP consentono ulteriori semplificazioni? – dklt

9

È possibile trovare una buona spiegazione di questo WWDC 2012 sessione di 712 a partire dal Pagina 83 Il modo corretto di salvare un blocco sotto ARC è il seguente:

@property(strong) my_block_type work; 

Fare attenzione ai cicli di mantenimento. Un buon modo per risolvere è impostato il blocco a zero quando non serve più:

self.work = nil; 
+2

solo con ARC. Sotto MRC questo è sbagliato. Ma 'copy' funziona correttamente sia con MRC che con ARC – newacct

+0

Non penso che la copia funzionerà bene in tutti i casi in MRC ma forse nella maggior parte di essi –

+0

' copy' è esattamente il modo giusto per farlo in MRC. – newacct

Problemi correlati