2012-04-09 16 views
7

consideri:proprietà Copia e Block_copy (myBlock)/[copia myBlock]

typedef void (^select_block_t)(UIView *) ; 

(1) @property (copy, nonatomic) select_block_t  myBlockProperty ; 
(2) @property (strong, nonatomic) select_block_t  myBlockProperty ; 
(3) @property (assign, nonatomic) select_block_t  myBlockProperty ; 

e:

(A) self.myBlockProperty = ^(UIView *) {NSLog(@"Hi");} ; 
(B) self.myBlockProperty = [^(UIView *) {NSLog(@"Hi");} copy] ; 

che sto cercando di capire che cosa è il modo corretto per mappare cui dichiarazione di proprietà con la quale semantica blocco copia

ho visto esempi here su S.O. che favorisca [1: B]

012.

Ma poi sono confuso da quanto ridondante è l'operazione di "copia". La mia comprensione limitata è che [1: A] dovrebbe essere corretto, perché voglio il blocco da copiare una volta quando assegno la proprietà, non una volta alla creazione del blocco e poi ancora una volta al momento dell'assegnazione della proprietà.

[3: B] avrebbe anche senso secondo il mio razionale. Quindi, cosa sto fraintendendo?

risposta

9

[1: A] è corretto, sì. [3: B] non è corretto perché:

  1. non è chiaro che la classe possiede la proprietà, quindi dovrebbe rilasciarlo in dealloc (ma dovrebbe)
  2. il setter (B) si presenta come una perdita, e l'analizzatore statico potrebbe contrassegnarlo come tale, poiché il blocco viene copiato, consegnato a una proprietà, quindi lascia l'ambito con il conteggio dei ritegni +1.
  3. utilizzando (3) significa che funziona solo se si imposta un heap-block (un blocco copiato) con un numero di conservazione di uno. Questo lascia un sacco di margine di errore quando si utilizza la proprietà. (1) funziona sia con stack-blocks sia con blocchi-heap e conserverà anche correttamente i blocchi auto-rilasciati.

MODIFICA: vedo che stai usando ARC. In tal caso, non è possibile utilizzare [3: B]. Il compilatore rilascerà un oggetto (anche quando è copy ed) una volta fuori ambito, e questo setter di proprietà non lo avrà mantenuto. Pertanto la proprietà conterrà un puntatore non valido, è un EXC_BAD_ACCESS che aspetta di accadere.

+0

Aspetta, hai appena visto il tuo tag _automatic-ref-counting_, stai usando ARC? – joerick

+0

Sì, sto usando ARC. – verec

+0

@verec Ho aggiornato la mia risposta. Fammi sapere se hai qualche domanda, non sono sicuro di quanto sia stato chiaro! – joerick

Problemi correlati