如果您告诉一个目标c对象removeObservers:对于一个关键路径而该关键路径尚未注册,这将使您难过。喜欢 -
“无法从中删除键路径“ theKeyPath”的观察者,因为它没有注册为观察者。
有没有一种方法可以确定一个对象是否具有注册的观察者,所以我可以这样做
if (object has observer){
remove observer
}
else{
go on my merry way
}
如果您告诉一个目标c对象removeObservers:对于一个关键路径而该关键路径尚未注册,这将使您难过。喜欢 -
“无法从中删除键路径“ theKeyPath”的观察者,因为它没有注册为观察者。
有没有一种方法可以确定一个对象是否具有注册的观察者,所以我可以这样做
if (object has observer){
remove observer
}
else{
go on my merry way
}
Answers:
试一下您的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
才能获得特定的观察者。
objectAtIndex:
不会产生预期的结果。)
NSKeyValueObserving.h
唯一的方法是在添加观察者时设置标志。
当您将观察者添加到对象时,可以将其添加到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
数组中将其删除:
- (void)removeObservedObject:(id)object {
if ([_observedObjects containsObject:object]) {
[_observedObjects removeObject:object];
}
}
NSHashTable
/ NSMapTable
保留弱引用。
我认为-这与keepCount机制类似。您无法确定当前是否有观察员。即使您检查:self.observationInfo-您也无法确定将来是否会有观察者。
就像keepCount一样。也许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:@""];
}
而且,您需要进行一些特定的检查-实现自己的类,该类可以处理一组观察者并将其用于检查。
[self removeObserver:nil forKeyPath:@""];
需要走之前: [super viewWillDisappear:animated];
- (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
[someObject observationInfo]
nil
如果没有观察者,则返回。
if ([tableMessage observationInfo] == nil)
{
NSLog(@"add your observer");
}
else
{
NSLog(@"remove your observer");
}
我不是那种尝试捕获解决方案的粉丝,所以我大部分时间都在为该类中的特定通知创建订阅和取消订阅方法。例如,以下两种方法将对象订阅或取消订阅全局键盘通知:
@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
addObserver:
的viewWillAppear:
,相应removeObserver:
的viewWillDisappear:
,该电话都正确配对。我必须进行快速修复,因此我将实现try-catch解决方案,并发表评论以进一步调查原因。