se você disser a um objeto c objetivo que removeObservers: para um caminho-chave e esse caminho-chave não foi registrado, ele quebrará os tristes. gostar -
'Não é possível remover um observador para o caminho da chave "theKeyPath" porque ele não está registrado como observador.'
existe uma maneira de determinar se um objeto tem um observador registrado, para que eu possa fazer isso
if (object has observer){
remove observer
}
else{
go on my merry way
}
objective-c
cocoa
key
key-value-observing
Aran Mulholland
fonte
fonte
addObserver:
emviewWillAppear:
e, correspondentemente,removeObserver:
emviewWillDisappear:
, as chamadas foram correctamente emparelhados. Eu tenho que fazer uma correção rápida para implementar a solução try-catch e deixar um comentário para investigar a causa.Respostas:
Experimente a sua chamada removeObserver
fonte
A verdadeira questão é por que você não sabe se está observando ou não.
Se você estiver fazendo isso na classe do objeto que está sendo observado, pare. O que quer que esteja observando, espera continuar observando. Se você interromper as notificações do observador sem o seu conhecimento, espere que as coisas quebrem; mais especificamente, espere que o estado do observador fique obsoleto, pois não recebe atualizações do objeto anteriormente observado.
Se você estiver fazendo isso na classe de objeto de observação, simplesmente lembre-se de quais objetos você está observando (ou, se você apenas observar um objeto, esteja observando). Isso pressupõe que a observação seja dinâmica e entre dois objetos não relacionados; se o observador possuir o observado, basta adicioná-lo após criar ou reter o observado e remover o observador antes de liberar o observado.
Adicionar e remover um objeto como observador geralmente deve ocorrer na classe do observador, e nunca na classe observada.
fonte
FWIW,
[someObject observationInfo]
parece sernil
sesomeObject
não tiver nenhum observador. No entanto, eu não confiaria nesse comportamento, pois não o vi documentado. Além disso, não sei lerobservationInfo
para conseguir observadores específicos.fonte
objectAtIndex:
não deu resultado desejado).NSKeyValueObserving.h
A única maneira de fazer isso é definir um sinalizador quando você adiciona um observador.
fonte
Quando você adiciona um observador a um objeto, pode adicioná-lo da
NSMutableArray
seguinte maneira:Se você deseja desobservar os objetos, pode fazer algo como:
Lembre-se, se você não observar um único objeto, remova-o da
_observedObjects
matriz:fonte
NSHashTable
/NSMapTable
para manter as referências fracas.Na minha opinião - isso funciona semelhante ao mecanismo reterCount. Você não pode ter certeza de que, no momento atual, você tem seu observador. Mesmo se você marcar: self.observationInfo - você não pode ter certeza de que terá ou não observadores no futuro.
Como reterCount . Talvez o método observaçãoInfo não seja exatamente esse tipo de inútil, mas eu o uso apenas para fins de depuração.
Então, como resultado - você só precisa fazer isso como no gerenciamento de memória. Se você adicionou um observador - basta removê-lo quando não precisar. Como usar os métodos viewWillAppear / viewWillDisappear etc. Por exemplo:
E você precisa de algumas verificações específicas - implemente sua própria classe que lida com uma série de observadores e use-a para suas verificações.
fonte
[self removeObserver:nil forKeyPath:@""];
precisa ir antes:[super viewWillDisappear:animated];
- (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
[someObject observationInfo]
retornenil
se não houver observador.fonte
O objetivo principal do padrão observador é permitir que uma classe observada seja "selada" - não saber ou se importar se está sendo observada. Você está tentando explicitamente quebrar esse padrão.
Por quê?
O problema que você está tendo é que você está assumindo que está sendo observado quando não está. Este objeto não iniciou a observação. Se você deseja que sua turma tenha controle sobre esse processo, considere usar o centro de notificação. Dessa forma, sua classe tem controle total sobre quando os dados podem ser observados. Portanto, não importa quem está assistindo.
fonte
Como não sou fã dessa solução try catch, o que faço na maioria das vezes é que crio um método de inscrição e cancelamento de inscrição para uma notificação específica dentro dessa classe. Por exemplo, esses dois métodos assinam ou cancelam a inscrição do objeto na notificação global do teclado:
Dentro desses métodos, uso uma propriedade privada configurada como true ou false, dependendo do estado da assinatura, da seguinte maneira:
fonte
Além da resposta de Adam, gostaria de sugerir o uso de macro como esta
exemplo de uso
fonte