当我开发KVO行为的时候。
[A addObserver:B forKeyPath:kLAShopRuleObserveKey options:NSKeyValueObservingOptionNew context:nil];
而我把观察者在 [B dealloc]
作为。
[A removeObserver:B forKeyPath:kObserveKey];
它的工作原理很好。
现在我多次添加观察者。
[A addObserver:B forKeyPath:kLAShopRuleObserveKey options:NSKeyValueObservingOptionNew context:nil];
[A addObserver:B forKeyPath:kLAShopRuleObserveKey options:NSKeyValueObservingOptionNew context:nil];
但我只在B中删除了一次KVO。
- (void)dealloc
{
[A removeObserver:self forKeyPath:kObserveKey];
}
在iOS11及以后的版本上工作正常,但在iOS10及以前的版本上就崩溃了,它的表现有何不同?
在 键值观测编程指南。注册成为观察者他们指出,你应该使用 context
参数。
所以,定义你的contexts。
static void *observerContext = &observerContext;
static void *observerContext2 = &observerContext2;
然后在添加观察者时使用这些上下文。
[a addObserver:b forKeyPath:kLAShopRuleObserveKey options:NSKeyValueObservingOptionNew context:observerContext];
[a addObserver:b forKeyPath:kLAShopRuleObserveKey options:NSKeyValueObservingOptionNew context:observerContext2];
然后在删除观察者时使用这些上下文 Then use these contexts when removing the observers:
[a removeObserver:b forKeyPath:kLAShopRuleObserveKey context:observerContext];
[a removeObserver:b forKeyPath:kLAShopRuleObserveKey context:observerContext2];
这样就能消除任何歧义 无论iOS版本如何,它也应该可以工作。
顺便说一下,你的 observeValueForKeyPath
应该检查上下文参数,并调用 super
如果不匹配的话,就会出现渲染。
例如,如果你有单独的处理程序。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == observerContext) {
// handle observer 1
} else if (context == observerContext2) {
// handle observer 2
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
或者,如果两个都在做同样的事情。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == observerContext || context == observerContext2) {
// handle observer
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
这种模式有助于避免可能出现的问题 如果你的键恰好与某个超类使用的键相匹配的话