我使用NSCache在我的应用程序中实现缓存。我想添加到期,以便它会在一段时间后获取新的数据。有哪些选项和什么是最好的方法?
I am using NSCache to implement caching in my app. I want to add expiration to it so it will obtain new data after some time. What are the options and what's the best approach?
我应该查看缓存访问时的时间戳,然后使其无效吗?是否缓存通过使用固定间隔定时器自动失效?
Should I look at the timestamp when the cache is accessed and invalidate it then? Should the cache automatically invalidate itself by using a fixed interval timer?
推荐答案
Should the cache automatically invalidate itself by using a fixed interval timer?
这将是一个坏的解决方案,因为你可能在定时器触发。有效期应根据具体项目的年龄而定。 (当然,有可能使用计时器有条件地使项无效);
This would be a bad solution, because you might add something seconds before the timer fires. The expiry should be based on the specific item's age. (It would, of course, be possible to conditionally invalidate items using a timer; see the comments on this answer.)
这里有一个例子。我想到子类化 NSCache ,但决定使用组合更简单。
Here's an example. I thought about subclassing NSCache, but decided it was simpler to use composition.
// // ExpiringCache.h // // Created by Aaron Brager on 10/23/13. #import <Foundation/Foundation.h> @protocol ExpiringCacheItem <NSObject> @property (nonatomic, strong) NSDate *expiringCacheItemDate; @end @interface ExpiringCache : NSObject @property (nonatomic, strong) NSCache *cache; @property (nonatomic, assign) NSTimeInterval expiryTimeInterval; - (id)objectForKey:(id)key; - (void)setObject:(NSObject <ExpiringCacheItem> *)obj forKey:(id)key; @end实施
Implementation
// // ExpiringCache.m // // Created by Aaron Brager on 10/23/13. #import "ExpiringCache.h" @implementation ExpiringCache - (instancetype) init { self = [super init]; if (self) { self.cache = [[NSCache alloc] init]; self.expiryTimeInterval = 3600; // default 1 hour } return self; } - (id)objectForKey:(id)key { @try { NSObject <ExpiringCacheItem> *object = [self.cache objectForKey:key]; if (object) { NSTimeInterval timeSinceCache = fabs([object.expiringCacheItemDate timeIntervalSinceNow]); if (timeSinceCache > self.expiryTimeInterval) { [self.cache removeObjectForKey:key]; return nil; } } return object; } @catch (NSException *exception) { return nil; } } - (void)setObject:(NSObject <ExpiringCacheItem> *)obj forKey:(id)key { obj.expiringCacheItemDate = [NSDate date]; [self.cache setObject:obj forKey:key]; } @end 注意 $ $ b
Notes
- Assumes you're using ARC.
- I didn't implement setObject:forKey:cost: since the NSCache documentation all but tells you not to use it.
- I use a @try/@catch block, since technically you could add an object to the cache that doesn't respond to expiringCacheItemDate. I thought about using respondsToSelector: for this, but you could add an object that doesn't respond to that too, since NSCache takes id and not NSObject. #import "ExpiringCache.h" @property (nonatomic, strong) ExpiringCache *accountsCache; - (void) doSomething { if (!self.accountsCache) { self.accountsCache = [[ExpiringCache alloc] init]; self.accountsCache.expiryTimeInterval = 7200; // 2 hours } // add an object to the cache [self.accountsCache setObject:newObj forKey:@"some key"]; // get an object NSObject *cachedObj = [self.accountsCache objectForKey:@"some key"]; if (!cachedObj) { // create a new one, this one is expired or we've never gotten it } }
更多推荐
缓存过期使用NSCache实现
发布评论