¿Por qué tengo que llamar a superdedeloc último y no primero?

ejemplo correcto:

- (void)dealloc { [viewController release]; [window release]; [super dealloc]; } 

ejemplo incorrecto:

 - (void)dealloc { [super dealloc]; [viewController release]; [window release]; } 

Aunque en casi todos los demás casos al anular un método, primero llamaría a la implementación del método de super, en este caso apple siempre llama [super dealloc] al final. ¿Por qué?

Es solo una guía. Puede llamar a otras instrucciones después de [super dealloc] . sin embargo, ya no puede acceder a las variables de la superclase porque se liberan cuando llama a [super dealloc] . Siempre es seguro llamar a la superclase en la última línea.

Además, KVO y las claves dependientes (desencadenadas) pueden producir efectos secundarios si dependen de las variables de miembros ya publicadas.

No sé nada sobre progtwigción para el iPhone, pero supongo que es por la misma razón por la que los destructores deben llamarse en orden inverso. Desea asegurarse de que toda su “basura” se limpia antes de llamar a su superclase. Si lo haces al revés, las cosas pueden complicarse. Por ejemplo, si su destructor necesita acceder a la memoria que el super destructor ya ha liberado:

 class X { private Map foo; function __construct() { foo = new Map(); } function __destruct() { foo.free; } } class Y extends X { function __construct() { super.__construct(); map.put("foo", 42); } function __destruct() { super.__destruct(); if (map.containsKey("foo")) { // boooooooooom! doSomething(); } } } 

Puede que no encuentre este problema en su código, porque “usted sabe lo que está haciendo”, pero es una práctica mejor y más segura que no haga tales cosas.

[super dealloc] está liberando la memoria utilizada por su objeto, incluidos los punteros para ver el controlador y la ventana. Hacer referencia a las variables después de haberlas liberado es, en el mejor de los casos, peligroso.

Vea esta respuesta .

Aquí está el ejemplo real donde [super dealloc] debe ser el último, de lo contrario la llamada a removeFromRunLoop causará la falla. No estoy seguro de qué sucede dentro de removeFromRunLoop de NSOutputStream, pero parece que accedo a ‘self’ en este caso.

Preparar:

 [outputStream setDelegate:self]; [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

Dealloc:

 - (void)dealloc { if (outputStream) { [outputStream close]; [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [outputStream release]; outputStream = nil; } delegate = nil; [super dealloc]; // must be last! } 

Prácticamente casi tiene [super dealloc] al final porque libera las variables de la superclase y ya no se puede acceder a ellas.

Una excepción es si tiene una subclase de UITableViewController que está utilizando otra clase como delegado de la vista de tabla. En ese caso, debe liberar el delegado de la vista de tabla después de [super dealloc] porque la vista de tabla está haciendo referencia al delegado de la vista de tabla y la vista de tabla debe liberarse primero.

[a la última publicación] ¿No se responsabilizaría la publicación de mesa que hace referencia al delegado de liberar su propio delegado? Pensaría que se conserva cuando se establece (para que pueda liberarlo o soltarlo) y se solucionará solo.

En cuanto a la pregunta de OP, siempre llamaré súper primero si estoy construyendo y llamo super último si estoy destruyendo. Pienso en ello como “Quiero tener una súper construcción que quiera para poder construir sobre eso, y quiero que súper se rompa al final después de limpiarlo después de mí”. Sin embargo, prácticamente todas las llamadas que uso están construyendo, excepto dealloc, así que es por eso que siempre lo verías en mi código dealloc.