这个observeValueForKeyPath有什么问题:ofObject:change:context:implementation?

在我的UIScrollView子类中,我正在观察帧的变化:

[self addObserver:self forKeyPath:@"frame" options:0 context:NULL]; 

我的observeValueForKeyPath:ofObject:change:context:实现如下:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == self && [keyPath isEqualToString:@"frame"]) { [self adjustSizeAndScale]; } if ([UIScrollView instancesRespondToSelector:@selector(observeValueForKeyPath:ofObject:change:context:)]) { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; // Exception } } 

但是我得到这个代码的例外:

 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<WLImageScrollView: 0x733a440; baseClass = UIScrollView; frame = (0 0; 320 416); clipsToBounds = YES; layer = <CALayer: 0x7346500>; contentOffset: {0, 0}>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled. Key path: frame Observed object: <WLImageScrollView: 0x733a440; baseClass = UIScrollView; frame = (0 0; 320 416); clipsToBounds = YES; layer = <CALayer: 0x7346500>; contentOffset: {0, 0}> Change: { kind = 1; } Context: 0x0' 

这是否意味着UIScrollView实现了observeValueForKeyPath:ofObject:change:context:但引发上述exception?

如果是的话,我怎样才能正确地实现observeValueForKeyPath:ofObject:change:context:这样我就可以处理我感兴趣的变化,并给超类有机会处理它感兴趣的变化?

编辑:BJ荷马的答案可能是一个更好的方法来采取这里; 我忘了所有关于上下文参数!

即使调用超级实现是通过书,它似乎就像调用observeValueForKeyPath:ofObject:change:context: on UIKit类实际上并没有观察有问题的字段抛出一个NSInternalInconsistencyexception(而不是NSInvalidArgumentException你会得到一个无法识别的select器)。 这个例外中的关键字串就是“接收但没有处理”。

据我所知,没有很好的文档logging的方式来查明一个对象是否观察到给定关键path上的另一个对象。 可能有一些部分logging的方法,例如-observationInfo属性,据说-observationInfo属性将信息传递给对象的观察者,但是你自己在那里 – 这是一个void *

所以我看到它,你有两个select:要么不要调用super实现,要么使用@try / @catch / @finally块来忽略特定types的NSInternalInconsistencyException 。 第二个select可能更有前途,但我有一个预感,一些侦探工作可以通过第一个选项让你更满意的结果。

添加观察者时应该添加一个context值。 在你的-observeValueForKeyPath方法中,检查上下文参数。 如果不是你在添加观察者时传递的上下文,那么你知道这个消息不是为你的子类devise的,你可以放心地把它传递给超类。 如果它相同的价值,那么你知道这是为你打算,你不应该把它传递给超级。

喜欢这个:

 static void *myContextPointer; - (void)addSomeObserver { [self addObserver:self forKeyPath:@"frame" options:0 context:&myContextPointer]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context != &myContextPointer) { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } else { // This message is for me, do whatever I want with it. } }