I want to get notified when the object corresponding to a certain key in an NSCache instance changes. I’ve tried using Key-Value Observing without luck (the console doesn’t log anything).
- (void)viewDidLoad
{
[super viewDidLoad];
[self.cache addObserver:self forKeyPath:@"myKey" options:NSKeyValueObservingOptionNew context:NULL];
[self.cache setObject:@"myObject" forKey:@"myKey"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"KEYPATH CHANGED: %@", keyPath);
}
How can I observe the contents of an NSCache?
I would expect
NSCachenot to be key-value observing (KVO) compliant for that sort of key. KVO is implemented internally at theNSObjectlevel by replacing the normal setter with one that alerts relevant observers and calls the original setter. In the case of things you set withsetObject:forKey:there is no specific setter so nothing for the runtime to hang off.Since
NSCachedoesn’t post any relevant notifications I think your best hope is the delegate protocol. It’s not explicit exactly what counts as an eviction but ifcache:willEvictObject:is called when the object associated with a key is changed on purpose then you could hook directly off that.Otherwise I’d recommend you create a wrapper class for
NSCache, sayDWCachefor argument’s sake, that contains anNSCache, is the delegate of the cache, and provides its ownsetObject:forKey:. It will posts an appropriate message (i) upon the first call to setObject:forKey:; (ii) upon every subsequent call that supplies an object different from that already in the cache; and (iii) whenever it receives acache:willEvictObject:.The only potential complexity is that
NSCachedoesn’t copy the original keys and, partly as a result, has no means to get key from object. You may want to store those connections separately, e.g. through anNSDictionary. Provided you clear the dictionary when the cache evicts the object you’ll still be providing caching behaviour.