2009-06-16 13 views
9

He visto código (probablemente el código de muestra propio de Apple) escrito de tal manera que libera el ivar en dealloc y establece la propiedad en viewDidUnload.¿Es necesario liberar el ivar y establecer el ivar sintetizado en cero al mismo tiempo?

p. Ej.

- (void)viewDidUnload 
{ 
    self.navigationController = nil; 
} 

- (void)dealloc 
{ 
    [_navigationController release]; 
} 

¿Por qué hacerlos en dos lugares? Además, ¿por qué establecer nil en uno y liberar en otro. Parece que self.property = nil simplemente se ocuparía de todo, ya que liberaría y establecería el ivar en nil.

Respuesta

5

Tiene razón: de hecho puede hacer self.property = nil en todas partes, incluido dealloc. El único inconveniente es que si el método setter hace algo más complicado que simplemente soltar el ivar, puede terminar tratando de acceder a otros campos que ya han sido liberados, etc.

En cuanto a por qué también lanzas la toma en viewDidUnload , eso es una optimización de memoria. Dado que las cosas que suelta en viewDidUnload son cosas que se volverán a instalar cuando la vista se cargue nuevamente, liberarlas allí libera la memoria en situaciones de poca memoria.

+0

Gracias, por lo que en ese caso el código viewDidUnload podría haber utilizado el mismo código que dealloc para liberar el objeto, es decir, [_navigationController release] en lugar de configurarlo a cero, ¿verdad? – Boon

+1

Sí, pero no es así. Utilice el accesorio en todas partes excepto en -dealloc. El uso de accesadores en -dealloc es controvertido por las razones que dio Daniel (Apple no está claro en lo que recomiendan, también). Adquiera el hábito de liberar todos sus ivars retenidos en -dealloc. No apueste por otra cosa para hacerlo por usted. Y cada vez que suelte algo, configúrelo en cero. Gran parte de ObjC no tiene una red de seguridad; los buenos hábitos son los que mantienen sus programas en funcionamiento porque el compilador no lo salvará. (OK, tal vez Clang finalmente nos salvará, pero solo usará su poder para siempre.) –

0

Si confía en la recolección de basura (disponible en Objective-C 2.0), establecer el ivar en nil y llamando al release logrará el mismo fin.

Supongo que el código que está buscando es administrar la memoria con release y solo establecerlo en nil para que luego no intente acceder a un objeto que ya no está allí. El nil es más contabilidad que gestión de memoria cuando no se depende del GC.

+0

No del todo - - [un lanzamiento de objeto] no hará nada (es un nop) bajo GC, mientras que establecer en cero permitirá al recolector de basura para eventualmente liberar el objeto (es eliminar una referencia), a menos que el ivar se defina como una referencia débil. – xtophyr

1

Apple recomienda que no llame a setters en las rutinas init y especialmente dealloc.

Esto se debe al hecho de que el objeto está parcialmente configurado en este momento, y los instaladores podrían tener observadores unidos, o podrían ser reemplazados por subclases, y tener efectos indeseables durante el desalojo, o podrían confundirse durante init con un objeto parcialmente configurado.

Por lo tanto, se utiliza normalmente:

_navigationController = [[NavController alloc] init]; 

código de estilo en su rutina de inicio, el código

[_navigationController release]; 

estilo en su dealloc y setters en otro código donde el objeto es conocido por ser totalmente completar.

algunos casos a considerar:

  • Subclase anula setNavigationController y hace referencia a sus propias Ivars asignados por init. Crash en init.
  • La subclase anula setNavigationController y hace referencia a sus propios ivars publicados en dealloc. Crash en dealloc.
  • La subclase anula setNavigationController y vuelve a dibujar algunas partes de la pantalla. El desperdicio de ciclos sin sentido, o la pantalla glitchy.
  • Otros objetos que se cancela la asignación al mismo tiempo observar navigationController y los observadores fuego durante dealloc
  • etc
Cuestiones relacionadas