2009-05-26 13 views
29

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

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

mal ejemplo:

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

Althoug en alsmost todos los demás casos, cuando sustituir un método me gustaría llamar primero implementación del método de los súper, en este caso la manzana siempre llama dealloc súper [ ] en el final. ¿Por qué?

Respuesta

54

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 al [super dealloc]. Siempre es seguro llamar a la superclase en la última línea.

También KVO y teclas dependientes (activadas) pueden producir efectos secundarios si dependen de las variables de miembros ya publicadas.

+5

Con ARC, no tiene que llamar '' super dealloc] 'en absoluto, produce un error de compilación cuando lo hace. – teradyl

12

No sé nada de programación para el iPhone, pero supongo que es por la misma razón 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 destructor súper 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(); 
     } 
    } 
} 

Es posible que no encontrará 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 hacer tales cosas.

+1

¿Alguien se preocupa de explicar por qué esto fue downvoted? – n3rd

+4

¿Alguien se preocupa por explicar por qué esto fue votado a favor? –

+0

Mi suposición es porque respondió la pregunta, al menos parcialmente. Por otro lado, un voto negativo comúnmente implica que la respuesta no fue útil o simplemente errónea. Si estaba mal, me gustaría saber por qué para aprender de mi error. ¿O solo estabas siendo polémico? – n3rd

5

[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.

Ver this answer.

1

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 hace referencia al delegado de la vista de tabla y la vista de tabla debe liberarse primero.

+1

¿Puede dar un poco más de detalles de su excepción? Suena un poco malo para mí. –

+1

@Mark: también me suena mal. Normalmente ni siquiera retendrías al delegado en primer lugar para evitar retener los ciclos. –

2

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.

Configuración:

[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! 
} 
1

[al último mensaje] No sería la tableView referencia el delegado sea responsable de la liberación de 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é superprime 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.

Cuestiones relacionadas