Dealloc em Swift

145

Gostaria de realizar uma limpeza no final da vida de um controlador de exibição, ou seja, para remover uma NSNotificationCenternotificação. Implementando deallocresultados em um erro do compilador Swift:

Cannot override 'dealloc' which has been marked unavailable

Qual é a maneira preferida de realizar alguma limpeza no final da vida de um objeto no Swift?

Kyle Clegg
fonte

Respostas:

333
deinit {
    // perform the deinitialization
}

Na documentação do Swift :

Um desinicializador é chamado imediatamente antes de uma instância de classe ser desalocada. Você escreve deinitializers com a palavra-chave deinit, semelhante a como os intializers são gravados com a palavra-chave init. Os desinicializadores estão disponíveis apenas em tipos de classe.

Normalmente, você não precisa executar limpeza manual quando suas instâncias são desalocadas. No entanto, quando você estiver trabalhando com seus próprios recursos, poderá ser necessário realizar uma limpeza adicional. Por exemplo, se você criar uma classe personalizada para abrir um arquivo e gravar alguns dados, poderá ser necessário fechar o arquivo antes que a instância da classe seja desalocada.

Kyle Clegg
fonte
45
deinit {
    // perform the deinitialization
}

é a resposta correta para Swift "dealloc".

No entanto, é bom ressaltar que, no iOS 9, o NSNotificationCenter não precisa mais ser limpo!

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Notas

NSNotificationCenter

No OS X 10.11 e iOS 9.0, o NSNotificationCenter e o NSDistributedNotificationCenter não enviarão mais notificações aos observadores registrados que possam ser desalocados. Se o observador puder ser armazenado como uma referência de zeragem fraca, o armazenamento subjacente armazenará o observador como uma referência de zeragem fraca, alternativamente, se o objeto não puder ser armazenado de forma fraca (ou seja, ele possui um mecanismo de retenção / liberação personalizado que impediria o tempo de execução de poder armazenar o objeto de maneira fraca) ele armazenará o objeto como uma referência de zeragem não fraca. Isso significa que os observadores não precisam cancelar o registro em seu método de desalocação. A próxima notificação que seria roteada para esse observador detectará a referência zerada e cancelará o registro automaticamente do observador. Se um objeto puder ser pouco referenciado, as notificações não serão mais enviadas ao observador durante a desalocação; o comportamento anterior de receber notificações durante o desastre ainda está presente no caso de observadores de referência com zeragem não fraca. Observadores baseados em bloco por meio do método - [NSNotificationCenter addObserverForName: object: fila: usingBlock] ainda precisam ser não registrados quando não estiverem mais em uso, pois o sistema ainda mantém uma forte referência a esses observadores. A remoção precoce de observadores (com referência fraca ou com referência a zero) ainda é suportada. CFNotificationCenterAddObserver não está em conformidade com esse comportamento, pois o observador pode não ser um objeto. Observadores baseados em bloco por meio do método - [NSNotificationCenter addObserverForName: object: fila: usingBlock] ainda precisam ser não registrados quando não estiverem mais em uso, pois o sistema ainda mantém uma forte referência a esses observadores. A remoção precoce de observadores (com referência fraca ou com referência a zero) ainda é suportada. CFNotificationCenterAddObserver não está em conformidade com esse comportamento, pois o observador pode não ser um objeto. Observadores baseados em bloco por meio do método - [NSNotificationCenter addObserverForName: object: fila: usingBlock] ainda precisam ser não registrados quando não estiverem mais em uso, pois o sistema ainda mantém uma forte referência a esses observadores. A remoção precoce de observadores (com referência fraca ou com referência a zero) ainda é suportada. CFNotificationCenterAddObserver não está em conformidade com esse comportamento, pois o observador pode não ser um objeto.

mas observe os pontos abaixo sobre referências fortes, para que você possa se preocupar com a limpeza de qualquer maneira ...?

James
fonte
3
A menos que o bloco de notificação tenha uma referência forte, você deve remover o observador.
TigerCoding
+1 por não precisar limpar os observadores. Importante saber! Como todas as referências de captura são fracas, nunca preciso lidar com isso.
n13 26/10/16
2
Os blocos de notificação sempre parecem ser fortemente referenciados de acordo com a documentação. Portanto: se você estiver usando blocos para manipular suas notificações, precisará cancelar o registro delas dentro do Deinit.
Marsbear #
22

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

O Swift desaloca automaticamente suas instâncias quando elas não são mais necessárias, para liberar recursos. Swift lida com o gerenciamento de memória de instâncias por meio da contagem automática de referência (ARC), conforme descrito em Contagem automática de referência. Normalmente, você não precisa executar limpeza manual quando suas instâncias são desalocadas. No entanto, quando você estiver trabalhando com seus próprios recursos, poderá ser necessário realizar uma limpeza adicional. Por exemplo, se você criar uma classe personalizada para abrir um arquivo e gravar alguns dados, poderá ser necessário fechar o arquivo antes que a instância da classe seja desalocada.

As definições de classe podem ter no máximo um desinicializador por classe. O desinicializador não aceita nenhum parâmetro e é gravado sem parênteses:

deinit {
    // perform the deinitialization
}
Varsha Vijayvargiya
fonte
2

é necessário remover o observador antes da desalocação, caso contrário, ocorreria uma falha. Isso pode ser feito usando

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}
Spydy
fonte
-2

Tenha cuidado ao chamar um método em outra classe de desinit , provavelmente ele terminará em falha

Jeba Moses
fonte
1
Votado como esse não deve ser necessariamente o caso. De ref. docs : como uma instância não é desalocada até que seu desinicializador seja chamado, um desinicializador pode acessar todas as propriedades da instância em que é chamado e pode modificar seu comportamento com base nessas propriedades (como procurar o nome de um arquivo que precisa estar fechado).
superjos