Apple开发_NSCache

前言

  • NSCache 是苹果提供的一个专门用来做缓存的类,当内存 "不足" 或超过限制的时候,会自动清理缓存,使用时可以指定缓存的数量和成本。
  • 用法与 NSMutableDictionary 的用法很相似,在 AFNetworking 和 SDWebImage 中,都使用它来管理缓存。
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g;
  • 设置对象并指定 "成本",成本可以自行指定
  • 例子:缓存图片

    • 1、缓存 100 张图片
    • 2、将图片的"宽 * 高"当作成本,图像"像素",10M 当作缓存成本,无论缓存的多少张照片,只要像素值超过 10M,就自动清理缓存图像的时候,使用成本,比单纯设置数量要科学!
    • NSCache 是线程安全的,在多线程操作中,不需要对 Cache 加锁。
    • NSCache 的 Key 只是做强引用,与可变字典不同,缓存对象不会对键名做 copy 操作,不需要实现 NSCopying 协议。
    • 使用 NSCache 做缓存一定要保证能够有恢复的办法,这是能否使用 NSCache 做缓存的一个重要原则。
    • 例如:imageCache 可以使用 NSCache ,而 downloadQueueCache 不能使用!
    • 当超出限制之后,缓存会自动清理!缓存中的任何对象,都有可能被干掉。
    • 如果是图像缓存,内存中没有,会自动从沙盒加载。
    • 如果操作被释放,就没有回复的渠道!
    • 这个是是否使用 NSCache 做缓存的一个重要原则,一定要保证能够有恢复的办法!
  • 千万不要清理 NSCache

    • 一旦调用了 removeAllObjects,就无法给 cache 添加对象。
    • 关于 NSCache 的内存管理,交给他自己就行!
    • SDWebImage 中存在同样的问题,一旦内存警告,清理了内存之后,之后所有的图片都是从沙盒加载的。

1、NSCache 的使用

// 创建对象
NSCache *cache = [[NSCache alloc] init];

// 设置缓存数量限制,默认值是 0,表示没有限制
cache.countLimit = 10;

// 设置缓存总成本限制,默认值是 0,表示没有限制
cache.totalCostLimit = 1024 * 1024;

// 设置是否自动清理缓存,默认为 YES,表示自动清理
cache.evictsObjectsWithDiscardedContent = YES;

// 设置代理
cache.delegate = self;

// 设置缓存
/*
0 成本,与可变字典不同,缓存对象不会对键名做 copy 操作,只是做强引用
*/
[cache setObject:str forKey:@(i)];

// 设置缓存
/*
指定成本
*/
[cache setObject:str forKey:@(i) cost:1024];

// 查看缓存内容
/*
NSCache 没有提供遍历的方法,只支持用 key 来取值,NSCache 的 Key 只是做强引用,不需要实现 NSCopying 协议
*/
NSString *string = [cache objectForKey:@(i)];

// 删除指定缓存
[cache removeObjectForKey:@8];

// 删除所有缓存
/*
一旦调用了 removeAllObjects,就无法给 cache 添加对象,关于 NSCache 的内存管理,交给他自己就行
*/
[cache removeAllObjects];

// 缓存协议方法
/*
须遵守 <NSCacheDelegate> 协议,obj 就是要被清理的对象
当缓存中的对象被清除的时候,会自动调用,不建议平时开发时重写!仅供调试使用
*/
- (void)cache:(NSCache *)cache willEvictObject:(id)obj {

}

0、前言

1、创建示例

2、API说明

API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0))
@interface NSCache <KeyType, ObjectType> : NSObject

/**
 * @brief 获取指定key对应的缓存对象
 *
 * @param key    缓存对象的key
 *
 * @return 返回指定key对应的缓存对象,如果缓存中不存在key对应的缓存对象,则返回nil
 *
 * @code
 * NSCache *cache = [[NSCache alloc] init];
 * [cache setObject:@"value" forKey:@"key"];
 * id obj = [cache objectForKey:@"key"];
 * NSLog(@"%@", obj); // 输出 value
 * @endcode
 */
- (nullable ObjectType)objectForKey:(KeyType)key;

/**
 * @brief 设置缓存对象
 *
 * @param obj    缓存对象
 * @param key    缓存对象对应的key
 *
 * @code
 * NSCache *cache = [[NSCache alloc] init];
 * [cache setObject:@"value" forKey:@"key"];
 * @endcode
 */
- (void)setObject:(ObjectType)obj forKey:(KeyType)key;

/**
 * @brief 设置缓存对象及其对应的开销
 *
 * @param obj    缓存对象
 * @param key    缓存对象对应的key
 * @param g      缓存对象的开销
 *
 * @code
 * NSCache *cache = [[NSCache alloc] init];
 * [cache setObject:@"value" forKey:@"key" cost:2];
 * @endcode
 */
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;

/**
 * @brief 移除指定key对应的缓存对象
 *
 * @param key    要移除的缓存对象的key
 *
 * @code
 * NSCache *cache = [[NSCache alloc] init];
 * [cache setObject:@"value" forKey:@"key"];
 * [cache removeObjectForKey:@"key"];
 * id obj = [cache objectForKey:@"key"];
 * NSLog(@"%@", obj); // 输出 nil
 * @endcode
 */
- (void)removeObjectForKey:(KeyType)key;

/**
 * @brief 移除所有缓存对象
 *
 * @code
 * NSCache *cache = [[NSCache alloc] init];
 * [cache setObject:@"value" forKey:@"key"];
 * [cache removeAllObjects];
 * id obj = [cache objectForKey:@"key"];
 * NSLog(@"%@", obj); // 输出 nil
 * @endcode
 */
- (void)removeAllObjects;

/** 缓存的名称 */
@property(copy) NSString *name;
/** 缓存的委托,用于回调 */
@property(nullable, assign) id<NSCacheDelegate> delegate;
/** 缓存对象总成本上限,当缓存成本超过此限制时,缓存将自动删除对象 */
@property NSUInteger totalCostLimit;
/** 缓存对象数量上限,当缓存中的对象数量超过此限制时,缓存将自动删除对象 */
@property NSUInteger countLimit;
/** 缓存是否应该自动删除具有已丢弃内容的对象 */
@property BOOL evictsObjectsWithDiscardedContent;

@end

@protocol NSCacheDelegate <NSObject>
@optional
/**
 * @brief 缓存即将移除对象时触发的方法
 *
 * @param cache         相关的缓存对象
 * @param obj           被移除的对象
 *
 * @discussion         当缓存对象将要移除一个对象的时候,会触发该方法,可以在该方法中对该被移除的对象进行相应的处理。
 *                      例如,可以将该对象进行持久化操作,或者进行释放操作,以免占用过多的内存空间。
 *
 * @code               可以在该方法中调用自定义的方法对被移除的对象进行处理,例如:
 *                      MyObject *myObj = (MyObject *)obj;
 *                      [myObj releaseMemory];
 *                      或者将该对象进行持久化操作,例如:
 *                      NSData *data = [NSKeyedArchiver archivedDataWithRootObject:obj];
 *                      [MyFileManager writeData:data toFile:@"myData"];
 */
- (void)cache:(NSCache *)cache willEvictObject:(id)obj;

@end
posted @ 2019-02-16 22:30  CH520  阅读(245)  评论(0编辑  收藏  举报