iOS开发-NSCache

开发时,经常会遇到一个问题,从网络下载的图片应该如何来缓存?难道每次请求都要去下载一次?流量不要钱哇?所以比较好的方法就是把图片资源下载下来,保存到本地,然后下次直接从本地取出图片就可以了,但是用什么来保存这个图片呢?有些人可能说用NSDictionary(应该是NSMutableDictionary),因为这个类在开发中非常非常常用。但是其实可能有一个更好的选择,是专门为缓存来设计的,没错,就是NSCache。非常牛逼的AFN、SDWebImage都是用它来进行图片缓存的。

就像上边说到的,NSCache和NSDictionary很类似,用key-value键值对来存储,但是相对于NSDictionary,他有几点优势:

  • 1.NSCache结合了各种自动删除的策略,用来确保不会占用过多的系统内存。
  • 2.NSCache是线程安全的,在多线程情况下,不需要考虑加锁来保证数据的安全。
  • 3.不像NSMutableDictionary,NSCache不会copy对象,而是保留它。

NSCache 框架

NSCache的类中内容很少,从Xcode进去看也就只有43行,接下来我们来看一下他都提供了哪些方法和属性。

NSCache 的属性

1
@property NSUInteger countLimit;	

countLimit用来限制缓存最多维护的对象个数,默认为0,0表示不限制数量。
但是需要注意的是,这个限制并不是严格的限制,如果缓存的数量超过这个数量,缓存中的一个对象可能会被立即丢弃,也可能稍候丢弃,还可能永远都不会丢弃,具体还要看实现的方式。

1
@property NSUInteger totalCostLimit;	

totalCostLimit用来限制缓存最大能够维持的内存,默认也为0,表示没有限制。
一般我们会使用字节来作为cost进行限制,在添加缓存时可以指定写入的缓存的cost,当总消耗的cost值超过限制时,就会释放一些缓存对象,这个释放对象的选择使用LRU(Least Recently Used)算法来选择最近没有使用的对象进行淘汰。

NSCache 方法

NSCache的存取方法主要是用key-value的形式,存取方法分为set、get、remove三种类型。

1

2

3

4

5

6
- (nullable ObjectType)objectForKey:(KeyType)key;

- (void)setObject:(ObjectType)obj forKey:(KeyType)key; // 0 cost

- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;

- (void)removeObjectForKey:(KeyType)key;

- (void)removeAllObjects;

其中

1
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;

可以指定消耗的cost,配合之前的totalCostLimit来管理缓存大小。

NSCacheDelegate

NSCacheDelegate只有一个方法:

1
- (void)cache:(NSCache *)cache willEvictObject:(id)obj;

当代理对象即将从缓存中移除时激活。

NSCache 使用

NSCache的使用很简单。

实例化一个cache对象,然后设定缓存内容就可以了,但是我们

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18
self.myCache = [[NSCache alloc] init];

self.myCache.delegate = self;

//设置最大缓存数量:10

self.myCache.countLimit = 10;

//设置最大缓存cost:5M

self.myCache.totalCostLimit = 5 * 1024 * 1024;

for(NSInteger i = 0 ; i < 100 ; i ++)

{

UIImage *image = [UIImage imageNamed:@"111.jpg"];

NSData *data = UIImageJPEGRepresentation(image, 1.0);

NSString *keyStr = [NSString stringWithFormat:@"image%ld",i];

[self.myCache setObject:data forKey:keyStr];

}

然后添加一个按钮,在点击时获取缓存

1

2

3

4

5

6

7

8

9

10

11

12

13
- (IBAction)getBtnClicked:(id)sender

{

for(NSInteger i = 0 ; i < 100 ; i ++)

{

NSString *keyStr = [NSString stringWithFormat:@"image%ld",i];

NSData *data = [self.myCache objectForKey:keyStr];

NSLog(@"%ld",[data length]);

}

}

可以看到打印出来的内容:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28
...

2018-04-08 17:41:16.916639+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.916978+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.917196+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.917504+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.917818+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.918076+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.918456+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.918640+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.918945+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.919214+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.919521+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.919740+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.920067+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.920571+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.920829+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.921340+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.921631+0800 CacheDemo[56627:2584885] 0

2018-04-08 17:41:16.921903+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.922146+ 大专栏  iOS开发-NSCache0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.922386+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.922575+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.922783+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.923082+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.923476+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.923756+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.923991+0800 CacheDemo[56627:2584885] 9132462

2018-04-08 17:41:16.924333+0800 CacheDemo[56627:2584885] 9132462

发现还是有10个图片被保存了下来,这时候我们把限制的cost大小和存入cost的方法修改一下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20
    self.myCache = [[NSCache alloc] init];

self.myCache.delegate = self;

//设置最大缓存数量:10

self.myCache.countLimit = 10;

//设置最大缓存cost:10M

self.myCache.totalCostLimit = 10 * 1024 * 1024;

for(NSInteger i = 0 ; i < 100 ; i ++)

{

UIImage *image = [UIImage imageNamed:@"111.jpg"];

NSData *data = UIImageJPEGRepresentation(image, 1.0);

NSString *keyStr = [NSString stringWithFormat:@"image%ld",i];

//        [self.myCache setObject:data forKey:keyStr];

//存入时添加cost

[self.myCache setObject:data forKey:keyStr cost:[data length]];

}

打印结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30
2018-04-08 17:43:36.566623+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.566814+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.567049+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.567326+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.567738+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.568164+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.568451+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.568780+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.569227+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.569489+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.569771+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.569993+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.570265+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.570518+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.570832+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.571092+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.571305+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.571526+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.571921+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.572595+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.572763+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.572979+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.573266+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.573541+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.573775+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.573969+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.574232+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.574565+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.575234+0800 CacheDemo[56686:2587750] 0

2018-04-08 17:43:36.575364+0800 CacheDemo[56686:2587750] 9132462

发现只有最后一次的图片被缓存下来了。

最后

以上就是NSCache的全部内容了,这个类中的内容不多,但是可能会在开发时帮助我们解决很多麻烦的问题。

原文地址:https://www.cnblogs.com/sanxiandoupi/p/11692185.html

时间: 2024-08-27 18:38:02

iOS开发-NSCache的相关文章

iOS开发tips-神奇的UITableView

概述 UITableView是iOS开发中使用频率最高的UI控件,在前面的文章中对于UITableView的具体用法有详细的描述,今天主要看一些UITableView开发中的常见一些坑,这些坑或许不深,但是如果开发中注意不到的话往往比较浪费时间. 神奇的section header 事情的起因是一个网友说要实现一个类似下图界面,但是不管是设置sectionHeaderHeight还是代理方法中实现func tableView(_ tableView: UITableView, heightFor

iOS开发网络篇—文件的上传

iOS开发网络篇—文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: YYViewController.m 1 #import "YYViewController.h" 2 3 #define YYEncode(str) [str dataUsingEncoding:NSUTF8StringEncoding] 4 5 @inter

iOS开发UI篇—推荐两个好用的Xcode插件(提供下载链接)

iOS开发UI篇—推荐两个好用的Xcode插件(提供下载链接) 这里推荐两款好用的Xcode插件,并提供下载链接. 一.插件和使用如下: 1.两款插件 对项目中图片提供自动提示功能的插件:KSImageNamed-Xcode-master 提供快速创建自动注释:VVDocumenter-Xcode-master 2.使用介绍: (1)KSImageNamed-Xcode-master的使用 安装该插件后,会对文件中图片进行智能提示. (2)VVDocumenter-Xcode-master能提供

IOS 开发环境,证书和授权文件等详解

一.成员介绍 1.    Certification(证书) 证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种: 1)    Developer Certification(开发证书) 安装在电脑上提供权限:开发人员通过设备进行真机测试. 可以生成副本供多台电脑安装: 2)      Distribution Certification(发布证书) 安装在电脑上提供发布iOS程序的权限:开发人员可以制做测试版和发布版的程序. 不可生成副本,仅有配置该证书的电脑才可使用:(副本制做介绍在

iOS开发之保存照片到系统相册(Photo Album)

iOS开发之保存照片到系统相册(Photo Album) 保存照片到系统相册这个功能很多社交类的APP都有的,今天我们简单讲解一下,如何将图片保存到系统相册(Photo Album). 创建UIImageView 创建UIImageView是为了将照片展示出来,我们是要把UIImage保存到系统相册(Photo Album): #define SCREEN [UIScreen mainScreen].bounds.size self.image = [UIImage imageNamed:@"i

iOS开发网络篇—发送GET和POST请求(使用NSURLSession)

iOS开发网络篇—发送GET和POST请求(使用NSURLSession) 说明: 1)该文主要介绍如何使用NSURLSession来发送GET请求和POST请求 2)本文将不再讲解NSURLConnection的使用,如有需要了解NSURLConnection如何发送请求. 详细信息,请参考:http://www.cnblogs.com/wendingding/p/3813706.html 3)本文示例代码发送的请求均为http请求,已经对info.plist文件进行配置. 如何配置,请参考:

iOS开发中UIPopoverController的使用详解

这篇文章主要介绍了iOS开发中UIPopoverController的使用,代码基于传统的Objective-C,需要的朋友可以参考下 一.简单介绍 1.什么是UIPopoverController 是iPad开发中常见的一种控制器(在iPhone上不允许使用) 跟其他控制器不一样的是,它直接继承自NSObject,并非继承自UIViewController 它只占用部分屏幕空间来呈现信息,而且显示在屏幕的最前面 2.使用步骤 要想显示一个UIPopoverController,需要经过下列步骤

iOS开发——多线程OC篇&amp;GCD实用总结

GCD实用总结 图片下载 注:iOS开发中常见GCD的实用也就这些了, 先来看看之前我们经常使用的方式: 1 static NSOperationQueue * queue; 2 3 - (IBAction)someClick:(id)sender { 4 self.indicator.hidden = NO; 5 [self.indicator startAnimating]; 6 queue = [[NSOperationQueue alloc] init]; 7 NSInvocationO

iOS开发——面试篇&amp;OC基本语法总结(面试)

OC基本语法总结(面试) C和OC对比 OC中主要开发在什么平台上的应用程序? 答:可以使用OC开发Mac OS X平台和iOS平台的应用程序 OC中新增关键字大部分是以什么开头? 答:OC中新增关键字大部分是以@开头 OC中新增加了那些数据类型? 答: Block类型 指针类型(Class, id类型) 空类型 特殊类型(SEL, nil) 面向对象特性是什么? 答:继承性,封装性,多态性 import和#include有什么区别? 答:import 的功能和 include一样, 是将右边的