简体   繁体   中英

Key-Value Observing NSCache

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 NSCache not to be key-value observing (KVO) compliant for that sort of key. KVO is implemented internally at the NSObject level by replacing the normal setter with one that alerts relevant observers and calls the original setter. In the case of things you set with setObject:forKey: there is no specific setter so nothing for the runtime to hang off.

Since NSCache doesn'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 if cache: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 , say DWCache for argument's sake, that contains an NSCache , is the delegate of the cache, and provides its own setObject: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 a cache:willEvictObject: .

The only potential complexity is that NSCache doesn'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, eg through an NSDictionary . Provided you clear the dictionary when the cache evicts the object you'll still be providing caching behaviour.

You have to implement this method:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

keyPath is the key that changed, object is the new value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM