Comment puis-je savoir si un object a un observateur de valeur clé attaché

Si vous indiquez à un object c objective de supprimerObservers: pour un chemin de clé et que ce chemin de clé n’a pas été enregistré, cela provoque des problèmes. comme –

‘Impossible de supprimer un observateur pour le chemin de clé “theKeyPath” car il n’est pas enregistré en tant qu’observateur.’

existe-t-il un moyen de déterminer si un object a un observateur enregistré, alors je peux le faire

if (object has observer){ remove observer } else{ go on my merry way } 

Mettez un essai sur votre appel removeObserver

 @try{ [someObject removeObserver:someObserver forKeyPath:somePath]; }@catch(id anException){ //do nothing, obviously it wasn't attached because an exception was thrown } 

La vraie question est pourquoi vous ne savez pas si vous l’observez ou non.

Si vous le faites dans la classe de l’object observé, arrêtez. Quoi qu’il en soit, il s’attend à continuer à l’observer. Si vous coupez les notifications de l’observateur à son insu, attendez-vous à ce que les choses se cassent; plus précisément, attendez-vous à ce que l’état de l’observateur devienne obsolète car il ne reçoit pas de mises à jour de l’object précédemment observé.

Si vous faites cela dans la classe de l’object d’observation, rappelez-vous simplement quels objects vous observez (ou, si vous observez un seul object, observez-le). Cela suppose que l’observation est dynamic et entre deux objects sans rapport entre eux. Si l’observateur possède l’observé, ajoutez simplement l’observateur après avoir créé ou conservé l’observé, et retirez l’observateur avant de libérer l’observé.

Ajouter et supprimer un object en tant qu’observateur devrait généralement se produire dans la classe de l’observateur et jamais dans l’object observé.

FWIW, [someObject observationInfo] semble être nil si someObject n’a pas d’observateur. Je ne ferais pas confiance à ce comportement, car je ne l’ai pas vu documenté. De plus, je ne sais pas lire l’ observationInfo pour obtenir des observateurs spécifiques.

Lorsque vous ajoutez un observateur à un object, vous pouvez l’append à un NSMutableArray comme ceci:

 - (void)addObservedObject:(id)object { if (![_observedObjects containsObject:object]) { [_observedObjects addObject:object]; } } 

Si vous voulez observer les objects, vous pouvez faire quelque chose comme:

 for (id object in _observedObjects) { if ([object isKindOfClass:[MyClass class]]) { MyClass *myObject = (MyClass *)object; [self unobserveMethod:myObject]; } } [_observedObjects removeAllObjects]; 

N’oubliez pas que si vous ne _observedObjects object, supprimez-le du tableau _observedObjects :

 - (void)removeObservedObject:(id)object { if ([_observedObjects containsObject:object]) { [_observedObjects removeObject:object]; } } 

La seule façon de faire est de définir un indicateur lorsque vous ajoutez un observateur.

À mon avis, cela fonctionne de la même manière que le mécanisme keepCount. Vous ne pouvez pas être sûr qu’au moment présent vous avez votre observateur. Même si vous vérifiez: self.observationInfo – vous ne pouvez pas savoir avec certitude que vous aurez / n’aura plus d’observateurs à l’avenir.

Comme retainCount . La méthode observationInfo n’est peut-être pas tout à fait inutile, mais je l’utilise uniquement à des fins de débogage.

Donc, il vous suffit de le faire comme dans la gestion de la mémoire. Si vous avez ajouté un observateur, retirez-le simplement lorsque vous n’en avez pas besoin. Comme utiliser les méthodes viewWillAppear / viewWillDisappear, etc. Par exemple:

 -(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self addObserver:nil forKeyPath:@"" options:NSKeyValueObservingOptionNew context:nil]; } -(void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self removeObserver:nil forKeyPath:@""]; } 

Et vous avez besoin de vérifications spécifiques – implémentez votre propre classe qui gère un tableau d’observateurs et l’utilisez pour vos vérifications.

[someObject observationInfo] renvoie nil s’il n’y a pas d’observateur.

 if ([tableMessage observationInfo] == nil) { NSLog(@"add your observer"); } else { NSLog(@"remove your observer"); } 

Le but de l’observateur est de permettre à une classe observée d’être “scellée” – de ne pas savoir si elle est observée ou de s’en soucier. Vous essayez explicitement de briser ce modèle.

Pourquoi?

Le problème que vous rencontrez est que vous supposez que vous êtes observé lorsque vous n’êtes pas. Cet object n’a pas commencé l’observation. Si vous souhaitez que votre classe contrôle ce processus, vous devriez alors envisager d’utiliser le centre de notification. De cette façon, votre classe a le contrôle total sur le moment où les données peuvent être observées. Par conséquent, il ne se soucie pas de qui regarde.

Je ne suis pas un fan de cette solution, alors 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 dans cette classe. Par exemple, ces deux méthodes permettent de souscrire ou de désabonner l’object à la notification clavier globale:

 @interface ObjectA : NSObject -(void)subscribeToKeyboardNotifications; -(void)unsubscribeToKeyboardNotifications; @end 

Dans ces méthodes, j’utilise une propriété privée définie sur true ou false en fonction de l’état de l’abonnement comme suit:

 @interface ObjectA() @property (nonatomic,assign) BOOL subscribedToKeyboardNotification @end @implementation -(void)subscribeToKeyboardNotifications { if (!self.subscribedToKeyboardNotification) { [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardHide:) name:UIKeyboardWillHideNotification object:nil]; self.subscribedToKeyboardNotification = YES; } } -(void)unsubscribeToKeyboardNotifications { if (self.subscribedToKeyboardNotification) { [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil]; self.subscribedToKeyboardNotification = NO; } } @end 

En plus de la réponse d’Adam, je voudrais suggérer d’utiliser la macro comme ceci

 #define SafeRemoveObserver(sender, observer, keyPath) \ @try{\ [sender removeObserver:observer forKeyPath:keyPath];\ }@catch(id anException){\ } 

exemple d’utilisation

 - (void)dealloc { SafeRemoveObserver(someObject, self, somePath); }