iOS如何删除同一对象上的多个观察者?

问题描述 投票:0回答:1

当我开发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及以前的版本上就崩溃了,它的表现有何不同?

ios key-value-observing
1个回答
0
投票

键值观测编程指南。注册成为观察者他们指出,你应该使用 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];
    }
}

这种模式有助于避免可能出现的问题 如果你的键恰好与某个超类使用的键相匹配的话

© www.soinside.com 2019 - 2024. All rights reserved.