I have a KVO-able class (call it Observee
), which affectedValue
dynamic property is affected by affectingValue
property. The dependency between the properties is defined by implementing +keyPathsForValuesAffectingAffectedValue
method.
Setting a value to affectingValue
notifies that affectedValue
has changed as I expected, unless Ovservee
is a subclass of NSObjectController
. Full example follows:
@interface Observee : NSObject // or NSObjectController
@property (readonly, strong, nonatomic) id affectedValue;
@property (strong, nonatomic) id affectingValue;
@property (strong, nonatomic) NSArrayController *arrayController;
@end
@implementation Observee
@dynamic affectedValue;
- (id)affectedValue { return nil; }
+ (NSSet *)keyPathsForValuesAffectingAffectedValue {
NSLog(@"keyPathsForValuesAffectingAffectedValue called");
return [NSSet setWithObject:@"affectingValue"];
}
@end
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (strong, nonatomic) Observee *observee;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
self.observee = [[Observee alloc] init];
[self.observee addObserver:self
forKeyPath:@"affectedValue"
options:NSKeyValueObservingOptionNew
context:NULL];
NSLog(@"setting value to affectingValue");
self.observee.affectingValue = @42;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSLog(@"affected key path = %@", keyPath);
}
@end
The example works fine and outputs as the following when Observee
derives NSObject
:
keyPathsForValuesAffectingAffectedValue called
setting value to affectingValue
affected key path = affectedValue
but when Observee
derives NSObjectController
:
keyPathsForValuesAffectingAffectedValue called
setting value to affectingValue
(note that "affected key path = affectedValue" is absent.)
It seems that keyPathsForValuesAffectingAffectedValue
is called in both cases but it is no-op in the latter.
Also, any key paths involving an instance of (subclass of) NSObjectController
won't affect other key paths, such as:
@implementation SomeObject
// `someValue` won't be affected by `key.path.(snip).arrangedObjects`
+ (NSSet *)keyPathsForValuesAffectingSomeValue {
return [NSSet setWithObject:@"key.path.involving.anNSArrayController.arrangedObjects"];
}
@end
How do I declare dependency between key paths in such cases? And, why is this whole thing happening?
(Yes, I know about will/didChangeValueForKey:
and friends, but wrapping up every affecting key path with a(nother) setter is terrible and I'd like to avoid it.)