Reputation: 22290
I've done some simple KVO setups. Now I have a bit more complex one. I have a singleton object that is settable. That is reachable with code like
[Site singleton].value
I can (and have) watch that singleton
for changes in it's value
property. But I would also like to watch a property of the current value (IF it's not nil). It has a valves
property that I would like to notice changes in.
Without knowing any better, I guess I can do something like
value
property like I'm used tovalves
property as well IF it is non nilvalves
watching it was doing on the previous value
.This seems... burdensome.
I see that you can do more complex keyPath
s but I've not found documentation that explains how to use them. Are they something that could make this problem easier? If not, is this a pattern that others have found a good solution for?
Upvotes: 1
Views: 720
Reputation: 42598
I can provide a better answer if I know a little more about the code involved, but this should be easy. I will assume that the observer is a view controller, but this is the most straightforward way of setting this up.
- (void)viewWillAppear:(BOOL)animated
{
// …
[[Site singleton] addObserver:self forKeyPath:@"value" options:0 context:NULL];
[[Site singleton] addObserver:self forKeyPath:@"value.valves" options:0 context:NULL];
}
- (void)viewWillDisappear:(BOOL)animated
{
// …
[[Site singleton] removeObserver:self forKeyPath:@"value"];
[[Site singleton] removeObserver:self forKeyPath:@"value.valves"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqualToString:@"value"]) {
// …
} else if ([keyPath isEqualToString:@"value.valves"]) {
// …
}
}
See Key-Value Coding Fundamentals.
Observe something that you know the full lifecycle of. A singleton is a good choice as long as it truly lives the whole life of the application. Generally, I stick to objects observing themselves.
Add an observer right when you need to do observing, remove an observer as soon as you no longer need observing. Always adding an observer in -init*
and removing it in -dealloc
is asking for trouble.
Upvotes: 3
Reputation: 9553
Yes, you can observe the keyPath @“value.valves” on self.singleton in:
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
You’ll be notified whenever value
changes OR valves
changes on it.
NOTE, however, that if value ever changes without correctly posting a willChange.../didChange..., you’ll get a run-time error. Mostly ‘value’s notifications will be posted for you by setter machinery, but if you have a weak
reference to it, it can delete itself without posting, which is super-annoying and a really stupid thing the clang team did.
Also note that if valves is a mutableArray you’re playing with fire, because it’ll mutate without you being notified.
Upvotes: 2