2009-09-22 11 views
24

Chiedendosi se qualcuno con esperienza potrebbe spiegarlo un po 'di più. Ho visto esempi di ...iPhone - dealloc - Release vs. nil

[view release]; 

    view = nil; 

.... all'interno del (void) dealloc.

Qual è la differenza e uno è migliore dell'altro? Qual è il modo migliore?

Quando fare test retainCount Personalmente ho visto nulla rilasciare un conteggio 3-0 per me, ma la liberatoria scende solo da 3 a 2.

risposta

36

Quello che avete visto è probabilmente questi:

1) [foo release]; 
2) self.bar = nil; 
3) baz = nil; 
  1. sta rilasciando l'oggetto, accedendo attraverso l'istanza variabili foo. La variabile di istanza diventerà un puntatore pendente. Questo è il metodo preferito in dealloc.

  2. È l'assegnazione di nil a una proprietà bar su sé stessi, che in pratica rilascerà ciò che la proprietà attualmente sta conservando. Fai questo se hai un setter personalizzato per la proprietà, che dovrebbe ripulire più della sola variabile di istanza che supporta la proprietà.

  3. Sovrascrive il puntatore baz facendo riferimento all'oggetto con zero, ma non rilascia l'oggetto. Il risultato è una perdita di memoria. Non farlo mai.

+0

quindi l'utilizzo del numero 3 all'interno di viewDidLoad non rilascerà la memoria di un oggetto alloc? – bbullis21

+0

No, usando 3) non rilascerà mai memoria, a meno che tu non sia in una raccolta di dati obsoleti su obj-C su Mac OS X. – PeyloW

+0

Anche fare self.bar = nil può causare una perdita di memoria. Se la proprietà è definita come @retain, funzionerà come previsto; se lo si definisce come @copy, si ha una perdita di memoria. – AlBlue

0

Penso che utilizzando sia è una specie di rete di sicurezza. Con solo release sul posto si potrebbe incorrere in problemi se si è avvitata la gestione del conteggio dei riferimenti. Rilascerai un oggetto, restituendo la sua memoria al sistema, ma il puntatore sarebbe ancora valido.

Con nil è garantito che il programma non si arresta in modo anomalo poiché l'invio di un messaggio a nil non fa nulla.

+0

Si consiglia di chiamare entrambi? Nil prima del rilascio o viceversa? – bbullis21

+0

Assegnare nil prima del rilascio significa che si sta inviando il rilascio a zero (quindi non si libera l'oggetto). Assegnare a nil è facoltativo (dato che l'oggetto è stato deallocato, la variabile di istanza non dovrebbe mai più essere referenziata) – rpetrich

1

Per quanto riguarda l'utilizzo all'interno del vostro codice, nella vostra dealloc non è necessario l'assegnazione alla proprietà, releas ing è tutto quello che devi fare.

- (void)dealloc { 
    [myProperty release]; // don't need to assign since you won't have the object soon anyway 
    [super dealloc]; 
} 
+1

Aspetta, l'ultima riga non dovrebbe essere [super dealloc]? – zpasternack

+0

Ah, mio ​​errore! –

8

Se non si utilizza proprietà (dove self.property = nil rilascerà anche un oggetto) allora si deve sempre seguire un rilascio dal codice che imposta il riferimento a zero, come profilassi:

[view release]; view = nil; 

Il motivo è che evita la possibilità che un riferimento possa essere utilizzato non valido. È raro e difficile essere successo, ma può accadere.

Questo è ancora più importante in viewDidUnload, se stai liberando IBOutlet - questo è uno scenario più realistico in cui un riferimento potrebbe andare male a causa degli avvisi di memoria che scaricano una vista, e poi qualche altro codice nella vista che prova a fare uso di un riferimento prima che la vista venga ricaricata.

Fondamentalmente è solo una buona pratica e ti farà risparmiare un crash ad un certo punto se prendi l'abitudine di farlo.

+0

quindi essenzialmente per gli ivar con proprietà, possiamo farlo? - (void) dealloc { self.iVar = nil } –

+0

Puoi, anche se in passato hai detto di non usare i setter in dealloc se non ci fossero effetti collaterali ... ma ora che le vars interne di classe possono essere create automaticamente dove devi usare i setter, suppongo che sia considerato OK usare quel metodo per impostare le variabili su zero in dealloc. –

+0

È ancora possibile fare riferimento a variabili di istanza sintetizzate, non è necessario utilizzare il setter in dealloc. –

2

@ bbullis22 hai visto diminuire il numero di giri da 3 a 0 perché hai impostato il riferimento su zero. poi hai chiesto il conto corrente di 'nil' che è zero. tuttavia, l'oggetto a cui si faceva riferimento ha lo stesso numero di ritenzione - 1 (dovuto all'impostazione del riferimento su zero). utilizzando la versione, il riferimento fa ancora riferimento allo stesso oggetto, quindi è per questo che si vede il conteggio dei ritardi da 3 a 2 in questa situazione.

Problemi correlati