キー値通知の登録に使用される次のメソッドでのコンテキストパラメーターの使用は何ですか。ドキュメントは、それを任意のデータセットとして示しているだけです。
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
誰かがその背後にある目的が何であるかを明らかにすることができますか...
キー値通知の登録に使用される次のメソッドでのコンテキストパラメーターの使用は何ですか。ドキュメントは、それを任意のデータセットとして示しているだけです。
addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil
誰かがその背後にある目的が何であるかを明らかにすることができますか...
この説明が抽象的すぎて理解できないものではないことを願っています。
MyViewController
のサブクラスであるクラスを作成するとしますUIViewController
。のソースコードがありませんUIViewController
。
ここで、 KVOを使用してのプロパティのMyViewController
変更を監視することにしました。したがって、オブザーバーとして自分自身を適切に追加します。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
オブザーバーとして登録するかどうかがわからないことです。もしそうなら、あなたは2つの問題を抱えているかもしれません:self.view
center
UIViewController
オブザーバーから自分を削除すると、のKVO登録も削除される可能性があります。UIViewController
のKVO登録と区別できるオブザーバーとして自分自身を登録する方法が必要です。そこで引数が出てきます。引数として使用していないことが絶対に確実なcontext
値を渡す必要があります。登録を解除するときは、同じものを再度使用して、登録を削除するだけで、の登録は削除しないようにします。そして、あなたのメソッドでは、メッセージがあなたのためのものか、あなたのスーパークラスのためのものかを確認するためにをチェックする必要があります。context
UIViewController
context
context
UIViewController
observeValueForKeyPath:ofObject:change:context:
context
context
他に何も使用しないを確実に使用する1つの方法は、で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];
}
}