什么时候删除自己作为我的钥匙观察员是非法的?

时间:2011-11-03 17:45:45

标签: ios cocoa key-value-observing

我在我的应用中遇到问题。为方便起见,我的应用代表更容易观察自己的属性。但是,当以观察者身份移除app委托时,我收到错误。

我已将其归结为一个小代码示例和结果(稍后显示)。

我的问题是,什么时候删除自己作为我自己的密钥的观察者是非法的,以及典型的可可开发人员如何在下面的示例中解决问题:

来自此代码...

#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]的价值确实发生了变化   keyPath'thing.next'

     

2011-11-03 13:32:02.124 TestKVO [11637:707]无法删除观察者   < NSKeyValueObservance 0x103828250>来自的关键路径“next.value”   < Thing 0x10381d970>,很可能是因为键“next”的值   在没有发送适当的KVO通知的情况下已更改。校验   事物类的KVO合规性。

2 个答案:

答案 0 :(得分:4)

我认为问题在于您注册了两个包含通知的来源。

相反,你应该:

  • 仅注册@"thing.next"
  • 在通知处理方法中,取消注册@"thing.next.value"@"thing.next"值(在change字典中找到),然后在新{@"thing.next.value"上注册@"thing.next" {1}}值(也可在change词典中找到)。

这样,当@"thing.next"密钥路径发生变化时,绑定保持一致。

答案 1 :(得分:2)

夫妻俩:

1)你实施自己的二传手吗?如果是这样,您需要通过恰当地发送willChangeValueForKey:didChangeValueForKey:来确保它们符合KVO。在Apple的Key-Value Observing Programming Guide中查找有关KVO合规性的部分。

编辑:上述内容旨在帮助您检查班级的整体合规情况。 @sam是正确的,除非您已禁用自动通知,否则自定义设置器中不需要willChange...didChange...

2)而不是让你的对象观察它自己的属性(有点奇怪的恕我直言),你可以实现自定义的setter,当值发生变化时,它会在对象中做任何你想做的事。