在用于注册关键值通知的以下方法中,上下文参数有什么用处。文件只是将其表示为任意数据。关键值观察中的上下文参数的重要性
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
有人可以提供一些线索什么是其背后的目的...
感谢
在用于注册关键值通知的以下方法中,上下文参数有什么用处。文件只是将其表示为任意数据。关键值观察中的上下文参数的重要性
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
有人可以提供一些线索什么是其背后的目的...
感谢
我希望这个解释是不是太过抽象理解。
假设您创建了一个类MyViewController
,它是UIViewController
的一个子类。您没有源代码UIViewController
。
现在您决定让MyViewController
使用KVO观察对self.view
的center
财产的更改。所以,你正式加入自己作为观察员:
- (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
的观察员。如果是这样,那么你可能有两个问题:
UIViewController
的KVO注册。您需要一种方法将自己注册为与UIViewController
的KVO注册不同的观察者。这就是context
的论点。你需要传递一个值为context
,你绝对相信UIViewController
是而不是使用作为context
参数。当您取消注册时,您再次使用相同的context
,以便您只删除注册,而不是UIViewController
的注册。在observeValueForKeyPath:ofObject:change:context:
方法中,您需要检查context
以查看该消息是针对您还是针对您的超类。
确保使用context
的其中一种方法是,在MyViewController.m
中创建一个static
变量。当你注册和注销,像这样使用它:在您的observeValueForKeyPath:...
方法
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];
}
然后,检查它像这样:
- (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。
还要注意,您可以为您观察的每个关键路径使用不同的上下文。然后,当系统通知您有更改时,您可以检查上下文而不是检查关键路径。测试指针相等性比检查字符串相等性要快一些。例如:
- (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];
}
}
[参数从observeValueForKeyPath:ofObject变化:背景:]的
感谢很多关于你的详细解释真的很感激。一段时间以来,我一直困惑着为什么这个参数很重要,并且你的回答能够澄清它。 :) – rustylepord 2012-08-12 08:19:24
你好我可以使用上下文来设置一些对象,稍后当通知来检索它时o根据存储在上下文中的值执行一些特定的任务。 – Sandeep 2012-11-26 15:06:34
+1精彩的解释。 (一个单独的警告:'UIView'的属性不符合KVO,不能观察'view.center'。) – 2013-10-08 15:48:59
可能重复(http://stackoverflow.com/questions/1625575/parameters-from-observevalueforkeypathofobjectchangecontext) – 2012-08-11 19:06:23