Ios 什么时候将自己作为密钥的观察者移除是非法的?
我的应用程序遇到问题。为了方便起见,my app delegate更容易观察自己的属性。但是,当作为观察者删除应用程序委托时,我收到一个错误 我将其归结为一个小代码示例和结果(稍后显示) 我的问题是,什么时候删除自己作为自己密钥的观察者是非法的,在下面的示例中,典型的cocoa开发人员如何解决这个问题: 从这个代码Ios 什么时候将自己作为密钥的观察者移除是非法的?,ios,cocoa,key-value-observing,Ios,Cocoa,Key Value Observing,我的应用程序遇到问题。为了方便起见,my app delegate更容易观察自己的属性。但是,当作为观察者删除应用程序委托时,我收到一个错误 我将其归结为一个小代码示例和结果(稍后显示) 我的问题是,什么时候删除自己作为自己密钥的观察者是非法的,在下面的示例中,典型的cocoa开发人员如何解决这个问题: 从这个代码 #import "AppDelegate.h" @interface Thing : NSObject @property (nonatomic, strong) Thing *
#import "AppDelegate.h"
@interface Thing : NSObject
@property (nonatomic, strong) Thing * next;
@property (nonatomic, strong) id value;
@end
@implementation Thing
@synthesize next,value;
+(Thing*)thing
{
return [[Thing new] autorelease];
}
@end
@interface AppDelegate ()
@property (strong, nonatomic) Thing * thing;
@end
@implementation AppDelegate
@synthesize window = _window, thing;
- (void)dealloc
{
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
Thing * thing2 = [Thing thing];
thing2.value = @"hello";
Thing * thing1 = [Thing thing];
thing1.next = thing2;
self.thing = thing1;
[self addObserver:self forKeyPath:@"thing.next.value" options:0 context:NULL];
[self addObserver:self forKeyPath:@"thing.next" options:0 context:NULL];
Thing * thing3 = [Thing thing];
thing3.value = @"goodbye";
self.thing.next = thing3;
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"value did change for keyPath '%@'", keyPath);
[self removeObserver:self forKeyPath:@"thing.next.value"];
[self removeObserver:self forKeyPath:@"thing.next"];
}
@end
我得到这个结果
2011-11-03 13:32:02.123 TestKVO[11637:707]的值确实发生了变化
关键路径“下一个”
2011-11-03 13:32:02.124 TestKVO[11637:707]无法删除观察者
对于来自的键路径“next.value”
,很可能是因为键“next”的值
已更改,但未发送适当的KVO通知。检查
对象类的KVO遵从性
两件事:
1) 您正在实现自己的setter吗?如果是这样,您需要通过适当地发送willChangeValueForKey:
和didChangeValueForKey:
来确保它们符合KVO。在苹果的《关键价值观察编程指南》中查找有关KVO合规性的部分
编辑:上面的内容是为了让你检查你的班级的整体合规性@sam是正确的,您不需要在自定义setter中使用willChange…
和didChange…
,除非您禁用了自动通知
2) 与其让对象观察它自己的属性(IMHO有点奇怪),不如实现自定义设置器,在值更改时在对象中执行任何您想要的操作。我认为问题在于,您注册了两个包含在内的通知源 相反,你应该:
- 只注册
@“thing.next”
- 在通知处理方法中,在旧的
上注销@“thing.next.value”
值(可在@“thing.next.value”
字典中找到),然后在新的更改
值(也可在@“thing.next.value”
字典中找到)上注册更改
@“thing.next.value”
这样,当
@“thing.next”
键路径更改时,绑定保持一致。我同意重写setter可能是更好的方法,但他不必调用willChangeValueForKey:
/didChangeValueForKey:
。事实上,如果他这样做了,他可能会让他的方法触发两次,因为kvo是自动的,除非你关闭它,即使你自己编写setter。请参阅和automaticallynotifiesobsersforkey:
@sam关于自动KVO是正确的。我的意思是说我的评论是为了检查全班的合规性。我将编辑我的答案。这很可能是正确的。当您注册thing.next.value
时,您的应用程序保留了对thing.next
的弱引用(即未保留)。然后更改thing.next
使KVO感到困惑,因为thing.next
已更改,因此更改了thing.next.value
但没有为thing.next.value
更改发送KVO通知。呸。这可能会让人困惑。