objective-c 如何判断对象是否附加了键值观察器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1582383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can i tell if an object has a key value observer attached
提问by Aran Mulholland
if you tell an objective c object to removeObservers: for a key path and that key path has not been registered, it cracks the sads. like -
如果你告诉一个客观的 c 对象 removeObservers: for a key path 并且该 key path 尚未注册,它会破解悲伤。喜欢 -
'Cannot remove an observer for the key path "theKeyPath" from because it is not registered as an observer.'
'无法从中删除关键路径“theKeyPath”的观察者,因为它没有注册为观察者。
is there a way to determine if an object has a registered observer, so i can do this
有没有办法确定一个对象是否有一个注册的观察者,所以我可以这样做
if (object has observer){
remove observer
}
else{
go on my merry way
}
回答by Adam
Put a try catch around your removeObserver call
在您的 removeObserver 调用中尝试捕获
@try{
[someObject removeObserver:someObserver forKeyPath:somePath];
}@catch(id anException){
//do nothing, obviously it wasn't attached because an exception was thrown
}
回答by Peter Hosey
The real question is why you don't know whether you're observing it or not.
真正的问题是为什么你不知道你是否在观察它。
If you're doing this in the class of the object being observed, stop. Whatever's observing it expects to keep observing it. If you cut off the observer's notifications without its knowledge, expect things to break; more specifically, expect the observer's state to go stale as it doesn't receive updates from the formerly-observed object.
如果你在被观察对象的类中这样做,停止。无论观察到什么,它都希望继续观察它。如果您在观察者不知情的情况下切断观察者的通知,则预计事情会中断;更具体地说,期望观察者的状态变得陈旧,因为它没有从以前观察到的对象接收更新。
If you're doing this in the observing object's class, simply remember which objects you're observing (or, if you only ever observe one object, whether you're observing it). This is assuming that the observation is dynamic and between two otherwise-unrelated objects; if the observer owns the observed, just add the observer after you create or retain the observed, and remove the observer before you release the observed.
如果您在观察对象的类中执行此操作,只需记住您正在观察哪些对象(或者,如果您只观察一个对象,是否正在观察它)。这是假设观察是动态的并且在两个不相关的对象之间;如果观察者拥有被观察者,只需在创建或保留被观察者后添加观察者,并在释放被观察者之前移除观察者。
Adding and removing an object as an observer should usually happen in the observer's class, and never in the observed object's.
作为观察者添加和删除对象通常应该发生在观察者的类中,而不是在被观察对象的类中。
回答by ma11hew28
FWIW, [someObject observationInfo]seems to be nilif someObjectdoesn't have any observers. I wouldn't trust this behavior, however, as I haven't seen it documented. Also, I don't know how to read observationInfoto get specific observers.
FWIW,[someObject observationInfo]似乎nil如果someObject没有任何观察员。但是,我不会相信这种行为,因为我还没有看到它的记录。另外,我不知道如何阅读observationInfo以获取特定的观察者。
回答by Oritm
When you add an observer to an object you could add it to a NSMutableArraylike this:
当您将观察者添加到对象时,您可以将其添加到NSMutableArray这样的:
- (void)addObservedObject:(id)object {
if (![_observedObjects containsObject:object]) {
[_observedObjects addObject:object];
}
}
If you want to unobserve the objects you can do something like:
如果您想取消观察对象,您可以执行以下操作:
for (id object in _observedObjects) {
if ([object isKindOfClass:[MyClass class]]) {
MyClass *myObject = (MyClass *)object;
[self unobserveMethod:myObject];
}
}
[_observedObjects removeAllObjects];
Remember, if you unobserve a single object remove it from the _observedObjectsarray:
请记住,如果您未观察到单个对象,请将其从_observedObjects数组中删除:
- (void)removeObservedObject:(id)object {
if ([_observedObjects containsObject:object]) {
[_observedObjects removeObject:object];
}
}
回答by Leibowitzn
The only way to do this is to set a flag when you add an observer.
唯一的方法是在添加观察者时设置一个标志。
回答by quarezz
In my opinion - this works similar to retainCount mechanism. You can't be sure that at the current moment you have your observer. Even if you check: self.observationInfo- you can't know for sure that you will have/won't have observers in future.
在我看来 - 这类似于 retainCount 机制。你不能确定目前你有你的观察者。即使你检查:self.observationInfo- 你也不能确定你将来会有/不会有观察者。
Like retainCount. Maybe the observationInfomethod is not exactly that kind of useless, but I only use it in debug purposes.
像retainCount。也许observationInfo方法并不是那种没用的,但我只在调试目的中使用它。
So as a result - you just have to do it like in memory management. If you added an observer - just remove it when you don't need it. Like using viewWillAppear/viewWillDisappear etc. methods. E.g:
因此,您只需像在内存管理中一样进行操作即可。如果您添加了观察者 - 只需在不需要时将其删除。像使用 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:@""];
}
And it you need some specific checks - implement your own class that handles an array of observers and use it for your checks.
并且您需要一些特定的检查 - 实现您自己的类来处理观察者数组并将其用于您的检查。
回答by Anupama
[someObject observationInfo]return nilif there is no observer.
[someObject observationInfo]nil如果没有观察者则返回。
if ([tableMessage observationInfo] == nil)
{
NSLog(@"add your observer");
}
else
{
NSLog(@"remove your observer");
}
回答by adonoho
The whole point of the observer pattern is to allow an observed class to be "sealed" -- to not know or care whether it is being observed. You are explicitly trying to break this pattern.
观察者模式的全部意义在于允许被观察的类被“密封”——不知道或不关心它是否被观察。您明确地试图打破这种模式。
Why?
为什么?
The problem you are having is that you are assuming you are being observed when you aren't. This object did not start the observation. If you want your class to have control of this process, then you should consider using the notification center. That way your class has full control on when data can be observed. Hence, it doesn't care who is watching.
您遇到的问题是,您假设自己正在被观察,而实际上却没有。这个对象没有开始观察。如果你想让你的班级控制这个过程,那么你应该考虑使用通知中心。这样你的班级就可以完全控制何时可以观察数据。因此,它不在乎谁在看。
回答by Sebastian Boldt
I am not a fan of that try catch solution so what i do most of the time is that i create a subscribe and unsubscribe method for a specific notification inside that class. For example these two methods subcribe or unsubscribe the object to the global keyboard notification:
我不喜欢 try catch 解决方案,所以我大部分时间做的是为该类中的特定通知创建订阅和取消订阅方法。例如这两个方法订阅或取消订阅对象到全局键盘通知:
@interface ObjectA : NSObject
-(void)subscribeToKeyboardNotifications;
-(void)unsubscribeToKeyboardNotifications;
@end
Inside those methods i use a private property which is set to true or false depending on the subscription state like so:
在这些方法中,我使用了一个私有属性,它根据订阅状态设置为 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
回答by wattson
In addition to Adam's answer I would like to suggest to use macro like this
除了亚当的回答,我想建议使用这样的宏
#define SafeRemoveObserver(sender, observer, keyPath) \
@try{\
[sender removeObserver:observer forKeyPath:keyPath];\
}@catch(id anException){\
}
example of usage
用法示例
- (void)dealloc {
SafeRemoveObserver(someObject, self, somePath);
}

