在以下用于注册键值通知的方法中,上下文参数的用途是什么。文档只是将其表示为任意数据集。
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
有人可以阐明它背后的目的是什么...
在以下用于注册键值通知的方法中,上下文参数的用途是什么。文档只是将其表示为任意数据集。
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
有人可以阐明它背后的目的是什么...
我希望这个解释不是太抽象而无法理解。
假设您创建了一个类MyViewController
,它是 的子类UIViewController
。你没有源代码UIViewController
。
现在您决定MyViewController
使用 KVO 来center
观察self.view
. 所以你适当地将自己添加为观察者:
- (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
's的观察者center
。如果是这样,那么您可能会遇到两个问题:
UIViewController
的 KVO 注册。您需要一种将自己注册为观察者的方法,该方法与UIViewController
的 KVO 注册不同。这就是context
参数的来源。您需要传递一个您绝对context
确定不用作参数的值。当您取消注册时,您会再次使用相同的内容,这样您只会删除您的注册,而不是' 注册。在您的方法中,您需要检查消息是否适合您或您的超类。UIViewController
context
context
UIViewController
observeValueForKeyPath:ofObject:change:context:
context
确保您使用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];
}
}
现在,您可以保证不会干扰超类的 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];
}
}