Por que eu tenho que chamar superdealloc por último, e não primeiro?

exemplo correto:

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

exemplo errado:

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

Embora em quase todos os outros casos, ao replace um método, eu primeiro chamaria a implementação do método do super, neste caso, apple sempre chama [super dealloc] no final. Por quê?

É apenas uma diretriz. Você pode ligar para outras instruções após [super dealloc] . no entanto, você não pode mais acessar as variables ​​da superclass porque elas são liberadas quando você chama [super dealloc] . É sempre seguro chamar a superclass na última linha.

Também as chaves KVO e dependentes (acionadas) podem produzir efeitos colaterais, se dependerem de variables ​​de membros já liberadas.

Eu não sei nada sobre programação para o iPhone, mas eu diria que é pela mesma razão que os destruidores precisam ser chamados na ordem inversa. Você quer ter certeza de que todo o seu ‘lixo’ está limpo antes de chamar sua superclass. Se você fizer o contrário, as coisas podem ficar confusas. Por exemplo, se o seu destruidor precisar acessar a memory que o super-destrutor já liberou:

 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(); } } } 

Você não pode encontrar esse problema em seu código, porque “você sabe o que está fazendo”, mas é uma prática melhor e mais segura geral não fazer essas coisas.

[super dealloc] está liberando a memory usada pelo seu object, incluindo os pointers para viewController e window. Referir-se a variables ​​depois de liberá-las é perigoso, na melhor das hipóteses.

Veja esta resposta .

Aqui está o exemplo real onde [super dealloc] deve ser o último, caso contrário, a chamada para removeFromRunLoop causará falha. Eu não tenho certeza do que acontece dentro de removeFromRunLoop do NSOutputStream, mas parece que ele acessa ‘self’ nesse caso.

Configuração:

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

Você praticamente tem quase [super dealloc] no final porque libera as variables ​​da superclass e elas não podem mais ser acessadas.

Uma exceção é se você tiver uma subclass de UITableViewController que esteja usando outra class como seu representante de exibição de tabela. Nesse caso, você deve liberar o delegado de exibição de tabela após [super dealloc] porque a visualização de tabela está [super dealloc] referência ao delegado de exibição de tabela e a exibição de tabela deve ser liberada primeiro.

[até o último post] O tableView referenciando o delegado não seria responsável por liberar seu próprio delegado? Eu acho que é mantido quando definido (para que você possa liberar ou autorelease) e ele iria cuidar de si mesmo?

Quanto à questão do OP, eu sempre chamarei o super primeiro se estou construindo e telefono para o último se estou destruindo. Eu penso nisso como “eu quero ter super construir o que ele quer para que eu possa construir sobre isso, e eu quero super derrubar por último depois de limpar depois de mim.” Praticamente todas as chamadas que eu uso estão sendo construídas, exceto o dealloc, então é por isso que você o veria por último no meu código dealloc sempre.