iOS——NSCache

什么是NSCache

NSCache是Foundation框架中的一个类,用于在iOS和macOS应用程序中进行临时性的内存缓存。它提供了一种轻量级的缓存机制,可以用于存储临时性的数据,例如图片、对象等。NSCache的主要特点和用法包括:

  1. 临时性缓存:NSCache用于存储需要临时性缓存的数据,这些数据在应用的生命周期内需要频繁访问,但并不需要永久保存。

  2. 自动管理内存:NSCache会自动管理缓存中的对象,当系统内存不足时,NSCache会自动释放部分缓存对象以腾出内存空间。

  3. 键值对存储:NSCache使用键值对的方式来存储和访问缓存数据。通过键(Key)可以快速查找对应的值(Value)。

  4. 线程安全:NSCache是线程安全的,多个线程可以同时读取和写入缓存,不需要额外的同步措施。

数据持久化的目的

  1. 快速展示,提升体验
    • 已经加载过的数据,用户下次查看时,不需要再次从网络(磁盘)加载,直接展示给用户
  2. 节省用户流量(节省服务器资源)
    • 对于较大的资源数据进行缓存,下次展示无需下载消耗流量
    • 同时降低了服务器的访问次数,节约服务器资源。
  3. 离线使用。
    • 用户浏览过的数据无需联网,可以再次查看。
    • 部分功能使用解除对网络的依赖。(百度离线地图、图书阅读器)
    • 无网络时,允许用户进行操作,等到下次联网时同步到服务端。
  4. 记录用户操作
    • 草稿:对于用户需要花费较大成本进行的操作,对用户的每个步骤进行缓存,用户中断操作后,下次用户操作时直接继续上次的操作。
    • 已读内容标记缓存,帮助用户识别哪些已读。
    • 搜索记录缓存
      ...

数据持久化方式分类

在移动端的数据持久化方式总体可以分为以下两类:

  1. 内存缓存
    对于使用频率比较高的数据,从网络或者磁盘加载数据到内存以后,使用后并不马上销毁,下次使用时直接从内存加载。

案例:

  • iOS系统图片加载------[UIImage imageNamed:@"imageName"]
  • 网络图片加载三方库:SDWebImage
  1. 磁盘缓存
    将从网络加载的、用户操作产生的数据写入到磁盘,用户下次查看、继续操作时,直接从磁盘加载使用。

案例:

  • 用户输入内容草稿缓存(如:评论、文本编辑)
  • 网络图片加载三方库:SDWebImage
  • 搜索历史缓存

NSCache缓存类的详解

NSCache在系统内存很低时,会自动释放一些对象。为了确保接收到内存警告时能够真正释放内存,最好调用一下removeAllObjects方法。

NScache的key只是做强引用,不需要实现NScopying协议。

NSCache的属性:

delegate代理属性

  • totalCostLimit :缓存空间的最大成本,超出上限会自动回收对象。默认值是0没有限制。
  • countLimit:能够缓存对象的最大数量,默认值也是0(默认没有限制)。
    (当超出缓存最大成本或数量时,NSCache会把前面的数据即最开始存的给清除掉)
  • evictsObjectsWithDiscardedContent:标示是否回收废弃的内容,默认值是YES(自动回收)。

"成本" 指的是每个对象的缓存大小,通常以字节为单位。如果缓存中的对象总成本超过了这个限制,NSCache 会自动回收一些对象,直到总成本符合限制。默认值为 0,表示没有限制。

NSCache的方法:

-objectForKey:返回与键值关联的对象。通过指定键名调用该方法,可以获取到缓存中对应的对象。如果该键名没有对应的对象,则返回 nil。

-setObject: forKey: 在缓存中设置指定键名对应的值。通过指定键名和对象调用该方法,可以将对象存储到缓存中。与可变字典不同的是,缓存对象不会对键名进行复制操作,因此设置键值对的成本是 0 成本,不会消耗额外的内存。

在可变字典中,通常当你向字典中添加一个新的键值对时,字典会对键名进行复制操作,以确保字典中的键是唯一的。这种复制操作虽然可以保证字典中键名的唯一性,但也会在一定程度上消耗额外的内存。而在 NSCache 中,当你使用 -setObject:forKey: 方法设置键值对时,并不会对键名进行复制操作。这种设计使得在设置键值对时不会消耗额外的内存,这就是"0成本"的意思。

-setObject: forKey: cost: 在缓存中设置指定键名对应的值,并且指定该键值对的成本。成本cost用于计算记录在缓冲中所有对象的总成本。当出现内存警告,或者超出缓存的成本上限时,缓存会开启一个回收过程,删除部分元素。

-removeObjectForKey:删除缓存中指定键名的对象。通过指定键名调用该方法,可以从缓存中移除对应的对象。

-removeAllObjects:删除缓存中的所有对象。调用该方法会清空缓存中的所有对象,使缓存变为空缓存。

委托方法:

-cache: willEvictObject: 缓存将要删除对象时调用,不能在此方法中修改缓存。仅仅用于后台的打印,以便于程序员的测试。

示例:

objectivec 复制代码
#import "ViewController.h"

@interface ViewController ()<NSCacheDelegate>

@property (nonatomic, strong) NSCache *myCaChe;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //设置缓存容器 
    self.myCaChe = [[NSCache alloc] init];
    self.myCaChe.countLimit = 10;
    self.myCaChe.totalCostLimit = 0;
    self.myCaChe.delegate = self;
    
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
    btn.frame = CGRectMake(100, 300, 200, 80);
    [btn setTitle:@"按钮" forState:UIControlStateNormal];
    [self.view addSubview:btn];
    [btn addTarget:self action:@selector(touchPress) forControlEvents:UIControlEventTouchUpInside];
}

static int a = 0;
- (void) touchPress{
    //将数据加入缓存 
    [self.myCaChe setObject:[NSString stringWithFormat:@"value - %d", a] forKey:@(a) cost:1000];
    NSLog(@"%@", [self.myCaChe objectForKey:@(a)]);
    a++;
}

- (void)cache:(NSCache *)cache willEvictObject:(id)obj {
    //打印出被从缓存中删除的数据 
    NSLog(@"delete - %@", obj);
}

@end
相关推荐
半桶水专家6 小时前
go语言中package详解
开发语言·golang·xcode
DisonTangor7 小时前
苹果发布iOS 18.2首个公测版:Siri接入ChatGPT、iPhone 16拍照按钮有用了
ios·chatgpt·iphone
- 羊羊不超越 -7 小时前
App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)
android·ios·harmonyos
青花瓷21 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
2401_865854881 天前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone
HackerTom1 天前
iOS用rime且导入自制输入方案
ios·iphone·rime
良技漫谈1 天前
Rust移动开发:Rust在iOS端集成使用介绍
后端·程序人生·ios·rust·objective-c·swift
2401_852403551 天前
高效管理iPhone存储:苹果手机怎么删除相似照片
ios·智能手机·iphone
星际码仔2 天前
【动画图解】是怎样的方法,能被称作是 Flutter Widget 系统的核心?
android·flutter·ios
emperinter2 天前
WordCloudStudio:AI生成模版为您的文字云创意赋能 !
图像处理·人工智能·macos·ios·信息可视化·iphone