Eu tenho uma classe C objetiva. Nele, criei um método init e configurei um NSNotification nele
//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getData)
name:@"Answer Submitted"
object:nil];
Onde eu defino o [[NSNotificationCenter defaultCenter] removeObserver:self]
nesta classe? Eu sei que para a UIViewController
, posso adicioná-la ao viewDidUnload
método. Então, o que precisa ser feito se eu acabo de criar uma classe c objetiva?
-(void)dealloc
e adicionarremoveObserser:self
. Esta é a forma mais recomendada de colocarremoveObservers:self
dealloc
método no iOS 6?Respostas:
A resposta genérica seria "assim que você não precisar mais das notificações". Obviamente, esta não é uma resposta satisfatória.
Eu recomendo que você adicione um
[notificationCenter removeObserver: self]
métododealloc
de chamada dessas classes, que você pretende usar como observadores, pois é a última chance de cancelar o registro de um observador de forma limpa. Isso, no entanto, apenas o protegerá contra travamentos devido ao centro de notificação notificando objetos mortos. Ele não pode proteger seu código contra o recebimento de notificações, quando seus objetos ainda não estão / não estão mais em um estado em que possam lidar adequadamente com a notificação. Para isso ... Veja acima.Editar (já que a resposta parece atrair mais comentários do que eu pensava) Tudo o que estou tentando dizer aqui é: é realmente difícil dar um conselho geral sobre quando é melhor remover o observador do centro de notificação, porque isso depende:
Portanto, o melhor conselho geral que posso dar: para proteger seu aplicativo. contra pelo menos uma possível falha, faça a
removeObserver:
dançadealloc
, já que esse é o último ponto (na vida do objeto), onde você pode fazer isso de forma limpa. O que isso não significa é: "adie a remoção até quedealloc
seja chamado, e tudo ficará bem". Em vez disso, remova o observador assim que o objeto não estiver mais pronto (ou necessário) para receber notificações . Esse é o momento certo. Infelizmente, por não saber as respostas a nenhuma das perguntas mencionadas acima, não posso nem imaginar quando seria esse momento.Você sempre pode proteger
removeObserver:
um objeto várias vezes (e todas, exceto a primeira chamada com um determinado observador, serão nops). Então: pense em fazer (de novo)dealloc
apenas para ter certeza, mas antes de mais nada: faça no momento apropriado (que é determinado pelo seu caso de uso).fonte
dealloc
é apenas a última linha de defesa contra travar o aplicativo devido a um acesso posterior a um objeto descalocado. Mas o lugar adequado para cancelar o registro de um observador é geralmente em outro lugar (e muitas vezes, muito mais cedo no ciclo de vida do objeto). Não estou tentando dizer aqui "Ei, apenas faça issodealloc
e tudo ficará bem".viewWillDisappear
" O problema em dar um conselho concreto é que realmente depende de que tipo de objeto você registra como observador para que tipo de evento. Ele pode ser a solução certa para cancelar o registro um observador emviewWillDisappear
(ouviewDidUnload
) paraUIViewController
s, mas isso realmente depende do caso de uso.Nota: Isso foi testado e funcionando 100% por cento
Rápido
PresentedViewController
Objective-C
Em
iOS 6.0 > version
, é melhor remover o observador emviewWillDisappear
porque oviewDidUnload
método está obsoleto.Muitas vezes é melhor
remove observer
quando a visão é removida donavigation stack or hierarchy
.PresentedViewController
fonte
viewWillAppear:
removeObserver:self
para qualquer um dosUIViewController
eventos do ciclo de vida quase certamente arruinará sua semana. Mais leitura: subjetivo-objetivo-c.blogspot.com/2011/04/…removeObserver
chamadasviewWillDisappear
conforme indicado é definitivamente o caminho certo se o controlador estiver sendo apresentado viapushViewController
. Se você os colocar,dealloc
entãodealloc
nunca será chamado - na minha experiência, pelo menos ...Desde o iOS 9 não é mais necessário remover observadores.
https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter
fonte
Se o observador for adicionado a um controlador de visualização , recomendo fortemente adicioná-lo
viewWillAppear
e removê-loviewWillDisappear
.fonte
viewWillAppear
eviewWillDisappear
para viewControllers?dealloc
com que seja chamado imediatamente. Voltar para o controlador de visualização pode causar várias notificações se o observador for adicionado aos comandos de inicialização.fonte
self
depois[super dealloc]
me deixa nervoso ... (mesmo que seja improvável que o receptor cancele a referência do ponteiro de alguma forma, bem, nunca se sabe como eles foram implementadosNSNotificationCenter
)[super dealloc]
deve ser sempre a última afirmação do seudealloc
método. Ele destrói seu objeto; depois de executado, você não tem mais um válidoself
. / cc @Dirk[super dealloc]
não é mais necessárioEm geral, eu coloco no
dealloc
método.fonte
Em swift, use deinit porque o dealloc não está disponível:
Documentação do Swift:
fonte
* editar: Este conselho se aplica ao iOS <= 5 (mesmo lá você deve adicionar
viewWillAppear
e removerviewWillDisappear
- no entanto, o conselho se aplica se por algum motivo você adicionou o observador emviewDidLoad
)Se você adicionou o observador em,
viewDidLoad
deve removê-lo em ambosdealloc
eviewDidUnload
. Caso contrário, você acabará adicionando-o duas vezes quandoviewDidLoad
for chamado depoisviewDidUnload
(isso acontecerá após um aviso de memória). Isso não é necessário no iOS 6, ondeviewDidUnload
está obsoleto e não será chamado (porque as visualizações não são mais descarregadas automaticamente).fonte
Na minha opinião, o código a seguir não faz sentido no ARC :
No iOS 6 , também não há sentido em remover observadores
viewDidUnload
, porque ele está obsoleto agora.Para resumir, sempre faço isso em
viewDidDisappear
. Porém, também depende de seus requisitos, assim como disse @Dirk.fonte
Acho que encontrei uma resposta confiável ! Tive de fazê-lo, pois as respostas acima são ambíguas e parecem contraditórias. Procurei livros de receitas e guias de programação.
Primeiro, o estilo de
addObserver:
emviewWillAppear:
eremoveObserver:
emviewWillDisappear:
não funciona para mim (eu testei) porque estou postando uma notificação em um controlador de visão filho para executar código no controlador de visão pai. Eu só usaria esse estilo se estivesse postando e ouvindo a notificação no mesmo controlador de visualização.A resposta na qual mais confiarei, encontrei em iOS Programming: Big Nerd Ranch Guide 4. Eu confio nos caras do BNR porque eles têm centros de treinamento iOS e eles não estão apenas escrevendo outro livro de receitas. É provavelmente do seu interesse serem precisos.
BNR exemplo um:
addObserver:
eminit:
,removeObserver:
emdealloc:
Exemplo dois de BNR:
addObserver:
emawakeFromNib:
,removeObserver:
emdealloc:
... ao remover o observador em
dealloc:
eles não usam[super dealloc];
Espero que isso ajude a próxima pessoa ...
Estou atualizando este post porque a Apple agora quase adotou completamente os Storyboards, então o mencionado acima pode não se aplicar a todas as situações. O importante (e a razão pela qual adicionei este post em primeiro lugar) é prestar atenção se você
viewWillDisappear:
for chamado. Não era para mim quando o aplicativo entrou em segundo plano.fonte
A resposta aceita não é segura e pode causar vazamento de memória. Por favor, deixe o cancelamento de registro em dealloc, mas também cancele o registro em viewWillDisappear (isto é, claro, se você se registrar em viewWillAppear) .... ISSO É O QUE EU FIZ DE QUALQUER MANEIRA E FUNCIONOU BEM! :)
fonte
É importante notar também que
viewWillDisappear
é chamado também quando o controlador de visualização apresenta um novo UIView. Esse delegado simplesmente indica que a visualização principal do controlador de visualização não está visível na tela.Nesse caso, desalocar a notificação em
viewWillDisappear
pode ser inconveniente se estivermos usando a notificação para permitir que o UIview se comunique com o controlador de visualização pai.Como solução, geralmente removo o observador em um destes dois métodos:
Por razões semelhantes, quando eu emito a notificação pela primeira vez, preciso levar em consideração o fato de que sempre que uma exibição aparece acima do controlador, o
viewWillAppear
método é disparado. Isso, por sua vez, irá gerar várias cópias da mesma notificação. Como não há uma maneira de verificar se uma notificação já está ativa, elimino o problema removendo a notificação antes de adicioná-la:fonte
SWIFT 3
Existem dois casos de uso de notificações: - eles são necessários apenas quando o controlador de visualização está na tela; - eles são necessários sempre, mesmo se o usuário abrir outra tela ao longo da corrente.
Para o primeiro caso, o local correto para adicionar e remover o observador é:
para o segundo caso, a maneira correta é:
E nunca colocar
removeObserver
emdeinit{ ... }
- é um erro!fonte
fonte