si vous dites à un objet objectif c de removeObservers: pour un chemin de clé et que le chemin de clé n'a pas été enregistré, il craque les tristes. comme -
'Impossible de supprimer un observateur pour le chemin de clé "theKeyPath" car il n'est pas enregistré en tant qu'observateur.'
y a-t-il un moyen de déterminer si un objet a un observateur enregistré, donc je peux le faire
if (object has observer){
remove observer
}
else{
go on my merry way
}
objective-c
cocoa
key
key-value-observing
Aran Mulholland
la source
la source
addObserver:
dansviewWillAppear:
et en conséquenceremoveObserver:
dansviewWillDisappear:
, les appels ont été jumelés correctement. Je dois faire une solution rapide, donc je vais mettre en œuvre la solution try-catch et laisser un commentaire pour enquêter davantage sur la cause.Réponses:
Mettez un crochet autour de votre appel removeObserver
la source
La vraie question est de savoir pourquoi vous ne savez pas si vous l'observez ou non.
Si vous faites cela dans la classe de l'objet observé, arrêtez. Quoi qu'il en soit, il s'attend à le continuer à l'observer. Si vous coupez les notifications de l'observateur à son insu, attendez-vous à ce que les choses se cassent; plus spécifiquement, attendez-vous à ce que l'état de l'observateur devienne périmé car il ne reçoit pas les mises à jour de l'objet précédemment observé.
Si vous faites cela dans la classe de l'objet d'observation, rappelez-vous simplement les objets que vous observez (ou, si vous n'observez qu'un seul objet, si vous l'observez). Cela suppose que l'observation est dynamique et entre deux objets autrement sans rapport; si l'observateur est propriétaire de l'observé, ajoutez simplement l'observateur après avoir créé ou conservé l'observateur, et supprimez l'observateur avant de relâcher l'observé.
L'ajout et la suppression d'un objet en tant qu'observateur devraient généralement se produire dans la classe de l'observateur, et jamais dans celle de l'objet observé.
la source
FWIW,
[someObject observationInfo]
semble êtrenil
sisomeObject
n'a pas d'observateurs. Je ne ferais pas confiance à ce comportement, cependant, car je ne l'ai pas vu documenté. De plus, je ne sais pas lireobservationInfo
pour avoir des observateurs spécifiques.la source
objectAtIndex:
ne donne pas le résultat souhaité.)NSKeyValueObserving.h
La seule façon de procéder est de définir un indicateur lorsque vous ajoutez un observateur.
la source
Lorsque vous ajoutez un observateur à un objet, vous pouvez l'ajouter à un
NSMutableArray
comme ceci:Si vous souhaitez annuler l'observation des objets, vous pouvez faire quelque chose comme:
N'oubliez pas que si vous désobservez un seul objet, supprimez-le du
_observedObjects
tableau:la source
NSHashTable
/NSMapTable
pour conserver les références faibles.À mon avis - cela fonctionne de manière similaire au mécanisme de retentionCount. Vous ne pouvez pas être sûr qu'en ce moment vous avez votre observateur. Même si vous vérifiez: self.observationInfo - vous ne pouvez pas savoir avec certitude que vous aurez / n'aurez pas d'observateurs à l'avenir.
Comme keepCount . Peut-être que la méthode observationInfo n'est pas vraiment inutile, mais je ne l'utilise qu'à des fins de débogage.
Donc, en conséquence - il vous suffit de le faire comme dans la gestion de la mémoire. Si vous avez ajouté un observateur, supprimez-le simplement lorsque vous n'en avez pas besoin. Comme utiliser les méthodes viewWillAppear / viewWillDisappear etc. Par exemple:
Et si vous avez besoin de vérifications spécifiques - implémentez votre propre classe qui gère un tableau d'observateurs et utilisez-la pour vos vérifications.
la source
[self removeObserver:nil forKeyPath:@""];
doit y aller avant:[super viewWillDisappear:animated];
- (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
[someObject observationInfo]
retournenil
s'il n'y a pas d'observateur.la source
L'intérêt du modèle d'observateur est de permettre à une classe observée d'être "scellée" - de ne pas savoir ou de se soucier de savoir si elle est observée. Vous essayez explicitement de briser ce modèle.
Pourquoi?
Le problème que vous rencontrez est que vous supposez que vous êtes observé alors que vous ne l'êtes pas. Cet objet n'a pas démarré l'observation. Si vous souhaitez que votre classe contrôle ce processus, vous devez envisager d'utiliser le centre de notification. De cette façon, votre classe a un contrôle total sur le moment où les données peuvent être observées. Par conséquent, peu importe qui regarde.
la source
Je ne suis pas fan de cette solution try catch, donc ce que je fais la plupart du temps, c'est que je crée une méthode d'abonnement et de désabonnement pour une notification spécifique à l'intérieur de cette classe. Par exemple, ces deux méthodes abonnent ou désabonnent l'objet à la notification clavier globale:
À l'intérieur de ces méthodes, j'utilise une propriété privée qui est définie sur true ou false en fonction de l'état de l'abonnement, comme suit:
la source
En plus de la réponse d'Adam, je voudrais suggérer d'utiliser une macro comme celle-ci
exemple d'utilisation
la source