我怎么知道一个对象是否有一个关键值观察者附加

如果你告诉一个客观的c对象移除观察者:对于一个关键path而且这个关键path还没有被注册,它就会破坏sads。 喜欢 –

'不能删除关键path“theKeyPath”的观察者,因为它没有注册为观察者。

有没有办法确定一个对象是否有注册的观察者,所以我可以这样做

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

尝试围绕你的removeObserver调用

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

真正的问题是为什么你不知道你是否在观察它。

如果你正在观察的对象的类中这样做,停止。 无论观察如何,都期望继续观察。 如果你在不知情的情况下切断了观察者的通知,那么期望事情会被打破。 更具体地说,期望观察者的状态变得陈旧,因为它不接收来自先前观察的对象的更新。

如果你在观察对象的类中这样做,只要记住你正在观察的对象(或者,如果你只观察一个对象,是否观察它)。 这是假设观察是dynamic的,在两个不相关的对象之间; 如果观察者拥有所观察到的,只要在创build或保留观察者之后添加观察者,并在释放观察者之前移除观察者。

添加和删​​除一个对象作为观察者通常应该发生在观察者的类,而不是在观察对象的。

FWIW, [someObject observationInfo]似乎是nil如果someObject没有任何观察者。 我不相信这种行为,但是,因为我没有看到它的logging。 另外,我不知道如何阅读observationInfo来获得具体的观察者。

当你添加一个观察者到一个对象时,你可以像下面这样将它添加到一个NSMutableArray

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

如果你不想观察对象,你可以做如下的事情:

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

请记住,如果您_observedObjects单个对象,请将其从_observedObjects数组中移除:

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

唯一的方法是在添加观察者时设置一个标志。

在我看来 – 这种工作类似于retainCount机制。 你目前无法确定你有观察者。 即使你检查: self.observationInfo – 你不能确定你将来是否有观察者。

retainCount一样。 也许observerInfo方法不完全是那种无用的,但我只用于debugging目的。

因此,你只需要像内存pipe理一样做。 如果您添加了观察者,只需在不需要的时候将其删除即可。 就像使用viewWillAppear / viewWillDisappear等方法。 例如:

 -(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:@""]; } 

而且你需要一些特定的检查 – 实现你自己的类来处理观察者数组,并将其用于检查。

[someObject observationInfo]如果没有观察者,则返回nil

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

观察者模式的重点在于让被观察的阶级“被封闭” – 不知道或不在乎是否被观察到。 你明确地试图打破这种模式。

为什么?

你遇到的问题是,当你不在的时候,你正在假设你正在被观察。 这个对象并没有开始观察。 如果你想让你的class级掌握这个过程,那么你应该考虑使用通知中心。 这样,你的class级就可以完全控制何时可以观察到数据。 因此,它并不关心谁在看。

我不是那种尝试捕捉解决scheme的粉丝,所以我大部分时间做的是我为该类中的特定通知创build了订阅和取消订阅方法。 例如,这两种方法将对象标记或取消订阅到全局键盘通知:

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

在这些方法中,我使用一个私有属性,根据订阅状态设置为true或false,如下所示:

 @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 

除了亚当的回答,我想build议像这样使用macros

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

使用的例子

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