本文介绍了缓存过期使用NSCache实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用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?

推荐答案

这将是一个坏的解决方案,因为你可能在定时器触发。有效期应根据具体项目的年龄而定。 (当然,有可能使用计时器有条件地使项无效);

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

  • 假设您使用ARC。

  • 我没有实现 setObject:forKey: cost:,因为NSCache文档。

  • catch块,因为在技术上,你可以添加一个对象到缓冲区,不响应 expiringCacheItemDate 。我想到使用 responsesToSelector:为此,但你可以添加一个对象也没有响应,因为NSCache需要 id 而不是 NSObject

  • 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实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 12:27