这个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
类实际上并没有观察有问题的字段抛出一个NSInternalInconsistency
exception(而不是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. } }