如果你告诉一个目标C对象removeObservers:一键路径和关键路径没有被注册,裂缝SADS。 喜欢 -
“不能从,因为它未注册为观察员的关键路径‘theKeyPath’删除的观察员。”
有没有一种方法来确定对象是否注册的观察者,这样我就可以做到这一点
if (object has observer){
remove observer
}
else{
go on my merry way
}
如果你告诉一个目标C对象removeObservers:一键路径和关键路径没有被注册,裂缝SADS。 喜欢 -
“不能从,因为它未注册为观察员的关键路径‘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
}
真正的问题是,为什么你不知道你是否正在观察与否。
如果你在课堂上被观察的对象这样做,停下来。 无论真实观察,预计将继续观察它。 如果切断观察者的通知,没有它的知识,期望事情打破; 更具体地说,期望观察者的状态去过时,因为它没有从以前观测的对象接收更新。
如果你在观察对象的类这样做,只是记得你观察的对象(或者,如果你只看到过一个对象,无论你观察它)。 这是假设的观测是动态的,两个原本无关物体之间; 如果观察者拥有观察到,只需添加观察者创建后或保留观察,并删除观察者松开观察之前。
在观察对象的添加和删除的对象作为观察员应在观察者的类通常发生,从来没有。
FWIW, [someObject observationInfo]
似乎是nil
,如果someObject
没有任何观察员。 我不相信这样的行为,但是,因为我还没有看到它记录在案。 另外,我不知道如何读observationInfo
得到具体观察员。
当您添加一个观察者的对象,你可以把它添加到NSMutableArray
是这样的:
- (void)addObservedObject:(id)object {
if (![_observedObjects containsObject:object]) {
[_observedObjects addObject:object];
}
}
如果你想unobserve的对象,你可以这样做:
for (id object in _observedObjects) {
if ([object isKindOfClass:[MyClass class]]) {
MyClass *myObject = (MyClass *)object;
[self unobserveMethod:myObject];
}
}
[_observedObjects removeAllObjects];
记住,如果你unobserve单个对象从删除_observedObjects
阵:
- (void)removeObservedObject:(id)object {
if ([_observedObjects containsObject:object]) {
[_observedObjects removeObject:object];
}
}
要做到这一点的唯一方法是,当你添加一个观察者设置一个标志。
在我看来 - 类似以retainCount机制。 你不能确保在当前时刻你有你的观察者。 即使你检查:self.observationInfo -你不能确切知道你将有/不会有未来的观察员。
像retainCount。 也许observationInfo方法是不完全的那种无用的,但我只在调试目的使用它。
因此,作为一个结果 - 你必须要做到像在内存管理。 如果添加一个观察者 - 只是删除它时,你不需要它。 如使用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");
}
观察者模式的整点是允许观察类是“密封” - 不知道或不关心是否被观测到它。 你被明确试图打破这种格局。
为什么?
您所遇到的问题是,我们假定你是当你是不是你正在观察。 这个对象没有启动的观察。 如果你希望你的类有这个过程的控制,那么你应该考虑使用通知中心。 这样,你的类时,有可观察数据的完全控制权。 因此,它并不关心是谁在看。
我不是试图捕捉解决方案的粉丝所以我做什么的大部分时间是我创建一个订阅,并为该类内特定通知退订方法。 例如这两种方法SUBCRIBE或取消的对象为全球键盘通知:
@interface ObjectA : NSObject
-(void)subscribeToKeyboardNotifications;
-(void)unsubscribeToKeyboardNotifications;
@end
里面那些方法我用它设置为依据,像这样的预约状态真或假的私有财产:
@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
除了亚当的答案,我想建议使用宏这样
#define SafeRemoveObserver(sender, observer, keyPath) \
@try{\
[sender removeObserver:observer forKeyPath:keyPath];\
}@catch(id anException){\
}
例如用法
- (void)dealloc {
SafeRemoveObserver(someObject, self, somePath);
}