Key-Value Observing
"objcでKey-Value Observingしたいのだけど、observeValueForKeyPath:ofObject:change:contextメソッドでsuperを呼び出すのはどんなとき?" という話。
Key-Value Observingの方法とかは、他の方の分かりやすい記事を参照ください。
observeValueForKeyPath:ofObject:change:contextの書き方
Key-Value Observingするとき、監視する側はこのメソッドが呼ばれて通知される様子。
// NSKeyValueObserving Protocol - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
でgoogleさんで探すと良く見つかるのはこんなコード
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"tintColor"]) { // tintColorに変更があったときのコード } }
他には、superを呼び出してるコードも見つけた。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // なにかのコード [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; }
どんなときにsuperを呼ぶ必要があるのか気になったので探してみた。
NSInternalInconsistencyException when using KVO
自分が監視しているkeyPathの場合はsuperを呼び出すべきじゃないね (NSInternalInconsistencyExceptionが起きるから)という話の様子。
で、自分で監視したkeyPathかどうかを判別する一つの方法として、 「observerを登録する際にcontextも一緒に登録しておくと、observeValueForKeyPath:ofObject:change:contextメソッドのcontextで判断できる」という内容ぽい。
// enabled ARC // observerを追加するとき [observedObject addObserver:self forKeyPath:@"tintColor" options:0 context:(__bridge void *)self]; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == (__bridge void *)self) { // 監視してるkeyPath毎のコード } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } //
一つ疑問が解消した。