以下方法中的上下文参数有什么用,用于注册键值通知。文档只是将其表示为任意数据集。
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
有人可以阐明它背后的目的是什么......
最佳答案
我希望这个解释不会太抽象而难以理解。
假设您创建一个类 MyViewController
,它是 UIViewController
的子类.您没有 UIViewController
的源代码.
现在你决定制作MyViewController
使用 KVO 观察 center
的变化self.view
的属性(property).因此,您正式将自己添加为观察员:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view addObserver:self forKeyPath:@"center" options:0 context:NULL];
}
- (void)viewDidDisappear:(BOOL)animated {
[self.view removeObserver:self forKeyPath:@"center"];
[super viewDidDisappear:animated];
}
这里的问题是你不知道UIViewController
也将自己注册为 self.view
的观察者的 center
.如果是这样,那么您可能会遇到两个问题:
- 当 View 的中心发生变化时,您可能会被调用两次。
- 当您删除自己的观察员身份时,您可能还会删除
UIViewController
的 KVO 注册。
您需要一种方法将自己注册为观察者,以区别于 UIViewController
的 KVO 注册。那就是 context
的地方参数进来了。您需要为 context
传递一个值你绝对确定UIViewController
不用作context
争论。注销时,您使用相同的 context
再次这样你只删除你的注册,而不是UIViewController
的注册。在你的 observeValueForKeyPath:ofObject:change:context:
方法,你需要检查context
看看这条消息是给你的,还是给你的父类(super class)的。
确保使用 context
的一种方法没有别的用途是创建一个 static
MyViewController.m
中的变量.注册和注销时使用它,如下所示:
static int kCenterContext;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view addObserver:self forKeyPath:@"center" options:0 context:&kCenterContext];
}
- (void)viewDidDisappear:(BOOL)animated {
[self.view removeObserver:self forKeyPath:@"center" context:&kCenterContext];
[super viewDidDisappear:animated];
}
然后在你的observeValueForKeyPath:...
方法,检查它是这样的:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (context == &kCenterContext) {
// This message is for me. Handle it.
[self viewCenterDidChange];
// Do not pass it on to super!
} else {
// This message is not for me; pass it on to super.
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
现在您可以保证不会干扰父类(super class)的 KVO(如果有的话)。如果有人创建了 MyViewController
的子类也使用 KVO,它不会干扰您的 KVO。
另请注意,您可以为观察到的每个关键路径使用不同的上下文。然后,当系统通知您更改时,您可以检查上下文而不是检查关键路径。测试指针相等性比检查字符串相等性快一点。示例:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (context == &kCenterContext) {
[self viewCenterDidChange];
// Do not pass it on to super!
} else if (context == &kBackgroundColorContext) {
[self viewBackgroundDidChange];
// Do not pass it on to super!
} else if (context == &kAlphaContext) {
[self viewAlphaDidChange];
// Do not pass it on to super!
} else {
// This message is not for me; pass it on to super.
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
关于objective-c - Key value observing中的context参数是做什么用的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11916502/