iOS网络——NSURLCache设置网络请求缓存

2023-05-16

今天在看HTTP协议,看到了response头中的cache-control,于是就深入的研究了一下。发现了iOS中一个一直被我忽略的类——NSURLCache类。

 

NSURLCache

NSURLCache用于缓存网络请求,也就是NSURLRequest,然后根据我们设置的NSURLCache策略进行相应的缓存。

首先介绍一下各种策略

策略意义

UseProtocolCachePolicy

 默认行为
 ReloadIgnoringLocalCacheData 不使用缓存
 ReloadIgnoringLocalAndRemoteCacheData* 我是认真地,不使用任何缓存
 ReturnCacheDataElseLoad 使用缓存(不管它是否过期),如果缓存中没有,那从网络加载吧
 ReturnCacheDataDontLoad 离线模式:使用缓存(不管它是否过期),但是从网络加载
 ReloadRevalidatingCacheData*在使用前去服务器验证 

其中ReloadIgnoringLocalAndRemoteCacheData和ReloadRevalidatingCacheData两种是没有实现的,可以不看。

在创建对request使用cache的时候会让我们选择以上的某种策略进行,也就是


+ (instancetype)requestWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval;  

该方法让我们设置策略和时间,然后request会根据策略和时间来进行相应的调度。

 

感受NSURLCache

这里使用默认的缓存策略ReturnCacheDataElseLoad缓存策略,

首先需要创建NSURLCache类


NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];  

1.这里可以看到,创建参数我们制定了 4 * 1024 * 1024的内存(4MB) ,没有使用磁盘空间。

2.NSURLCache使用[NSURLCache sharedURLCache]创建默认的的缓存行为,默认为 4(MB) 内存和 20(MB)磁盘空间,这里我们使用自定义的,所以要setSharedCache。

然后创建request和connection进行请求


NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:3];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];  

实现NSURLConnectionDelegate协议


-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"finish");
}  

然后运行开一下请求,这里用的工具是Charles

可以看到只有一次请求,再看控制台输出


2015-08-04 09:29:55.297 requestCache[19405:6375355] finish
2015-08-04 09:29:55.301 requestCache[19405:6375355] finish
2015-08-04 09:29:55.310 requestCache[19405:6375355] finish
2015-08-04 09:29:55.451 requestCache[19405:6375355] finish
2015-08-04 09:29:55.618 requestCache[19405:6375355] finish
2015-08-04 09:29:55.784 requestCache[19405:6375355] finish
2015-08-04 09:29:55.984 requestCache[19405:6375355] finish
2015-08-04 09:29:56.120 requestCache[19405:6375355] finish  

所以说多次的请求只会进行一次请求,因为在内存中NSURLCache为我们缓存了一份response,一旦有同样请求就会使用缓存。

 

缓存持久化

缓存如果设定本地磁盘就会为我们自动进行持久化,修改NSURLCache创建代码


    NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
    [NSURLCache setSharedURLCache:URLCache];  

设置了20MB的本地磁盘,然后运行程序,进行请求发现还是请求一次没有变化。但是在次运行程序进行请求就会发现,一次远程请求也不会进行了!

打开沙盒,发现在 Library/Caches/bundleId+项目名/下面有三个文件

这不就是sqlite么!原来NSURLCache帮我们用sqlite将请求存入了数据库,然后当有相同请求时就会调用缓存!

可以想到webView如果加载一个静态页面不用只用请求一次,并且在效果要更新的时候远程请求会有多爽!

 

默认策略

默认策略是 UseProtocolCachePolicy 从字面上来看是说,使用协议缓存策略,但是什么是协议缓存策略呢?

在HTTP协议的response头中,有一个字段是cache-control,由服务器来告诉客户端如何使用缓存。

下面是一个response头

 

可以看到cache-control指定的行为是public,max-age=5

这里先介绍一下各种指令

对应上表,可以看出了刚才响应头是要求缓存所有内容,缓存5秒失效,5秒后还要请求远程服务器。

对应PHP就是header("Cache-Control:public,max-age=5");

 

伪造响应

如果我们想让一些请求,有特定的响应,我们可以自己来制作响应


    NSLog(@"%@",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]);
    
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:3];
    NSURLCache * cache = [NSURLCache sharedURLCache];
    
    NSData *contentData = [@"123" dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] MIMEType:@"text/html" expectedContentLength:1000 textEncodingName:@"UTF-8"];
    NSCachedURLResponse *cacheRespone = [[NSCachedURLResponse alloc] initWithResponse:response data:contentData];
    
    [cache storeCachedResponse:cacheRespone forRequest:request];
    
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [connection start];  

如上代码,创建了一个针对@"http://172.16.25.44/test1.php"请求的响应,并且让 cache 对该响应进行了存储。

实现


-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",dataString);
}  

输出结果如下


2015-08-04 09:48:58.825 requestCache[19503:6441561] 123
2015-08-04 09:48:58.826 requestCache[19503:6441561] finish
2015-08-04 09:48:58.983 requestCache[19503:6441561] 123
2015-08-04 09:48:58.984 requestCache[19503:6441561] finish
2015-08-04 09:48:59.167 requestCache[19503:6441561] 123
2015-08-04 09:48:59.167 requestCache[19503:6441561] finish
2015-08-04 09:48:59.334 requestCache[19503:6441561] 123
2015-08-04 09:48:59.335 requestCache[19503:6441561] finish  

可以看到输出的是我们自定义的123,而不是服务器返回的1。

 

修改响应内容

修改响应内容需要我们实现NSURLConnectionDataDelegate 协议并实现


-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
    NSMutableData *mutableData = [[cachedResponse data] mutableCopy];
    
    //添加数据
    
    NSCachedURLResponse *response = [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:mutableData];
    return response;
}  

应为 NSCachedURLResponse 的属性都是readonly的,所以我们想要添加内容就要创建一个可变副本增减内容。

 

转载于:https://www.cnblogs.com/madpanda/p/4700741.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS网络——NSURLCache设置网络请求缓存 的相关文章

  • 当前图像选择模式会擦除 UI

    我下面有一个非常简单的视图控制器 UI 实际上只是一个带有底部标签栏的按钮 import UIKit class ImageAdderViewController UIViewController override func viewDid
  • 将 UIPanGestureRecognizer 添加到 UIScrollView 时禁用滚动

    我有一个滚动视图 我想让它在平移完成时消失 它工作正常 平移时滚动视图消失 但问题是现在我无法滚动内容 UIView animateWithDuration 0 2 delay 0 2 options UIViewAnimationCurv
  • 使用自动布局时 UIScrollview 的中心内容

    我在项目中使用自动布局 并且有一个滚动视图 其中有一个居中的按钮 我已经让滚动视图滚动 但不占据整个屏幕 我尝试按照此处的教程进行操作 https developer apple com library ios technotes tn21
  • iOS-将图像转为视频时,CVPixelBufferCreate内存无法正确释放

    我正在将图像制作成视频 但总是因为内存警告而崩溃 分配太多CVPixelBufferCreate 我不知道如何正确处理 我看过很多类似的主题 但没有一个能解决我的问题 这是我的代码 void writeImagesArray NSArray
  • SwiftUI 检测用户何时截取屏幕截图或屏幕录制

    On UIViewController我们可以轻松地将观察者添加到控制器 喜欢 class ViewController UIViewController override func viewDidLoad super viewDidLoa
  • 在 UITableViewCell 内动态更改标签宽度

    我正在尝试建立一个自定义表格视图 正如您在图片中看到的 我在故事板一侧将标签的宽度默认设置为 160 磅 并在加载表格时动态更改宽度 我通过修改 cellForRowAtIndexPath 委托方法来实现此目的 因此 根据日期的长度 我设置
  • Swift 1.2 可选外部变量?

    由于 Swift 无法访问编译变量 因此我创建了一个指向编译变量的 Objective C extern 变量 编译变量转换器 h extern NSString const NetworkApiBasicAuthUsername 编译变量
  • “EXC_BAD_ACCESS”与“分段错误”。两者实际上相同吗?

    在我的前几个虚拟应用程序 用于学习时练习 中 我遇到了很多EXC BAD ACCESS 这以某种方式告诉我错误访问是 您正在触摸 访问一个不应该的对象 因为它尚未分配或释放 或者只是您无权访问它 查看此示例代码 该代码存在访问错误问题 因为
  • WKWebView在后台,几个奇怪的断言

    我想找出iOS中当前浏览器的userAgent 所以在 Xcode 创建的默认项目中我添加了 import ViewController h import
  • 为什么我无法更改 UIBarButtonItem 的标题?

    我想改变UIBarButtonItem s title 但这段代码不起作用 void viewDidLoad self smay void smay AppDelegate apd AppDelegate UIApplication sha
  • iOS5 和 Facebook API

    我想将我的应用程序与 Facebook 集成并从 github 下载 Facebook ios sdk 但是 该 sdk 适用于 Xcode 4 0 代码库 我正在使用 Xcode 4 2 for iOS 5 beta 5 应用程序 是否有
  • 视频中的图像/文本叠加 swift

    我正在使用 swift 在视频中使用图像叠加来实现水印效果 我正在使用AVFoundation为此 但不知何故我没有成功 以下是我的覆盖图像 文本的代码 let path NSBundle mainBundle pathForResourc
  • 带有图像的 UITableView 滚动非常慢[重复]

    这个问题在这里已经有答案了 可能的重复 带图像的表格视图 加载和滚动缓慢 https stackoverflow com questions 4071497 table view with images slow load and scro
  • UIImageWriteToSavedPhotosAlbum 选择器语法问题

    努力让 UIImageWriteToSavedPhotosAlbum 快速工作https developer apple com library ios documentation UIKit Reference UIKitFunction
  • 使用 UIWebView 显示 PDF 不起作用

    因此 我意识到有关使用 UIWebView 在应用程序 在 iPad 上 中显示 PDF 存在很多问题 我已经审查了我能找到的所有内容 但似乎找不到任何满意的东西 我想做的事情非常基本 所以我真的不知道为什么它不起作用 我需要做的就是在 U
  • 在 Swift 中,如何为具有自动布局的 UIView 制作动画,就像页面滑入一样?

    我尝试创建一个 UIView 来表示一个大小与设备屏幕相同的页面 由于该应用程序支持方向 因此我使用 AutoLayout 来构建它 它工作正常 直到我尝试将页面动画化以从右侧滑入 经过一番研究后 我能想到的最好的办法是 myView UI
  • 游戏中心玩家显示名称在沙盒中始终为“我”

    我使用用户的游戏中心显示名称和玩家 ID 来维护他们在我的服务器上的个人资料 当我进行测试时 一切似乎都正确执行 但我的沙箱帐户的用户显示名称显示为 Me 而不是附加到我的帐户的显示名称 Billybobbo 这应该在沙盒模式下发生吗 Co
  • 使用自定义格式将字符串转换为 NSDate [重复]

    这个问题在这里已经有答案了 可能的重复 NSString 到 NSDate https stackoverflow com questions 1353081 nsstring to nsdate iPhone 如何将 yyyyMMddTh
  • iOS 开发:如何强制 UIWebView 加载 Facebook 的非移动版本?

    我正在深入研究 iOS 开发 当我尝试在 UIWebView 中加载特定的 Facebook 粉丝页面时 它会加载该网站的移动版本 该版本仅加载粉丝页面的墙 而不是我需要加载的特定选项卡 在我的应用程序的 iPad 版本中 UIWebVie
  • 如何删除以前的 ViewController

    我是一名学生 对编程还很陌生 我正在尝试在业余时间学习 Objective C Swift 我使用 spriteKit 和 swift 制作了一个游戏 有多个菜单 场景 我正在尝试从一个视图控制器转换到另一个视图控制器 为此 我使用了以下代

随机推荐

  • iOS开发中UITableView和UITableViewCell的几种样式

    说了很久要写自己的技术博客 xff0c 由于执行力差 xff0c 一直拖到现在才开始写文章 我是一个刚进入软件行业还不到一年的小菜鸟 xff0c 没有什么技术可言 xff0c 然后就在这里斗胆妄自尊大的在博客园上写些东西 xff0c 还希望
  • ubuntu 16.04 + VMware Workstation 16player VCS +Verdi 安装备忘录

    经过了一周左右的煎熬 xff0c 终于将VCS 43 Verdi的验证环境搭建好了 xff0c 只能说很不容易 xff0c 在此作一叙述 xff0c 也是以备自己将来再在相同的地方摔跤 参考 下载软件 xff08 tb买一天会员就行 xff
  • 素数伴侣HJ28

    题目链接 xff1a 素数伴侣 牛客题霸 牛客网 解法 xff1a 最大匹配 因为素数不可能是偶数 xff0c 所以 素数伴侣 只能是一个奇数和一个偶数 由此我们可以创建二分图 xff1a 一个子集全是奇数 xff0c 另一个子集全是偶数
  • A Radiologist's Notes

    肺 lung 肺野 lung fields 后前位胸像上自纵膈肺门向外的透光区域 为了便于定位 xff0c 演第2 4前肋下缘水平画线将肺野分为上中下肺野 xff0c 从肺门到一侧肺野的最外部纵行均分三带 内 xff0c 中 xff0c 外
  • html中内联元素和块级元素的区别

    1 下表列出了内联元素和块级元素的主要区别 html中内联元素和块级元素的区别 块级元素 行内元素 独占一行 默认情况下 xff0c 其宽度自动填满其父元素宽度 相邻的行内元素会排列在同一行里 xff0c 直到一行排不下 xff0c 才会换
  • 基于STM32F429,Cubemx的SDHC卡的基本Fatfs文件移植

    本博文要求各位初步了解Fatfs文件系统 友情提示Fatfs官网 xff1a http elm chan org fsw ff 00index e html 1 开发软件 keil5 Cube5 21 2 实验目的 往SDHC卡上移植Fat
  • 详解equals()方法和hashCode()方法

    前言 Java的基类Object提供了一些方法 xff0c 其中equals 方法用于判断两个对象是否相等 xff0c hashCode 方法用于计算对象的哈希码 equals 和hashCode 都不是final方法 xff0c 都可以被
  • 对本课程的期望以及教学建议

    本学期我们学的c程序更加难了上学期c语言我是压线过的 xff0c 我希望这个学期我能把以前学的知识好好再看看然后总结下来 xff0c 我终于明白了多编程是有多么重要 xff0c 这学期我的电脑一定要派上用场 老师讲课跟以往的不同 xff0c
  • centos 6.3 使用 vnc xrdp 远程登陆 不断弹出对话框“ Authentication is required to set the network proxy used for...

    参考国外解决方案 xff1a 1 cd 进入 etc xdg autostart 2 在该目录下的所有文件的末尾添加 X GNOME Autostart enabled 61 false 3 注意 如果文件中已经的值设置为true xff0
  • 【深度学习】在Caffe中配置神经网络的每一层结构

    前言 层结构 xff0c 是神经网络 Neural Networks 建模和计算的最基本单元 由于神经网络有不同的层结构 xff0c 不同类型的层又有不同的参数 所以 xff0c 对Caffe的每一层配置都不一样 xff0c 而层结构和参数
  • nyoj239 月老的难题 二分图 匈牙利算法

    月老的难题 时间限制 xff1a 1000 ms 内存限制 xff1a 65535 KB 难度 xff1a 4 描述 月老准备给n个女孩与n个男孩牵红线 xff0c 成就一对对美好的姻缘 现在 xff0c 由于一些原因 xff0c 部分男孩
  • iOS开发之键盘类型UIKeyboardType

    UIKeyboardTypeDefault xff1a UIKeyboardTypeASCIICapable xff1a UIKeyboardTypeNumbersAndPunctuation xff1a UIKeyboardTypeURL
  • 转:Maven常用命令

    Maven库 xff1a http repo2 maven org maven2 Maven依赖查询 xff1a http mvnrepository com Maven常用命令 xff1a 1 创建Maven的普通java项目 xff1a
  • 外派公司或者外包公司,真的适合选择吗?

    外派公司是什么 任何公司如果需要用人 xff0c 不论需要什么样的人 xff0c 都可以从外派公司要人 xff0c 用几个月 xff0c 给外派公司几个月的钱 xff0c 管理非常方便灵活 xff0c 不需要考虑长期的员工福利和培养问题 x
  • 对新课程的期望

    我希望在这节课上学到更多技术相关的东西 xff0c 我自己希望通过这学期的学习能过自己写出一个像样点的网站 我计划每周花19小时的时间在这门课上其中包括每周的上课时间两次一共4个小时 xff0c 回到宿舍在每天的6 9点的三个小时进行学习
  • 函数模板和类模板成员函数的定义通常放在头文件中

    今天写程序时 xff0c 将函数模板的声明和定义分开放在头文件和 cpp文件中 xff0c 发生了连接错误 上网查看资料和查看 C 43 43 PRIMER 5 P582发现 xff0c xff1a 函数模板和类模板成员函数的定义通常放在头
  • 虚拟机防火墙关了怎么端口还是不能访问

    今天虚拟机启动时候发现网站不能访问了 xff0c 先在本地ping了下地址 xff0c 发现是可以ping通的 xff1b 然后telnet下 80 端口 xff0c 发现进不去 然后在虚拟机上面启动apache xff0c 发现不能访问
  • T84341 Jelly的难题1

    T84341 Jelly的难题1 题解 当窝发现窝的锅在读入这个矩阵的时候 xff0c 窝 窝 窝 果然 xff0c 一遇到和字符串有关的题就开始吹空调 好啦我们说说思路吧 BFS队列实现 拿出一个没有走过的点 xff0c 扩展它可以达到的
  • strtok(), strtok_s() 字符串分割函数

    strtok 函数原型 Check return CRT INSECURE DEPRECATE strtok s CRTIMP char cdecl strtok Inout opt z char Str In z const char D
  • iOS网络——NSURLCache设置网络请求缓存

    今天在看HTTP协议 xff0c 看到了response头中的cache control xff0c 于是就深入的研究了一下 发现了iOS中一个一直被我忽略的类 NSURLCache类 NSURLCache NSURLCache用于缓存网络