跳过正文
  1. Posts/

NSURLCache 缓存机制浅谈

·3 分钟

APP 中有很多从服务器获取数据、资源的需求,为了节省流量、加快访问速度、离线使用等需求,就会使用到网络缓存。HTTP协议对于缓存设计了很多机制,感兴趣的同学可以看看《RFC2616-section13-Caching in HTTP》

iOS 中常见缓存机制
#

在iOS中,如果没有特殊需求,使用系统的缓存机制就可以满足。如:max-age、Last-Modified、ETag、Expires等机制系统都实现了的,不需要自己再去搞一套。只需要将 NSURLRequestcachePolicy 设置为 NSURLRequestUseProtocolCachePolicy

NSURLRequest *request = [[NSURLRequest alloc] init];
request.cachePolicy = NSURLRequestUseProtocolCachePolicy;

这里简单说下常见的几种机制,首先来看一个GET请求的响应报文,里面包含了几种常见的缓存标识。

HTTP/1.1 200 
Cache-Control	max-age=86400, private
Last-Modified	Tue, 16 Apr 2019 06:07:39 GMT
ETag	W/"28111-1554979928000"
Expires	Wed, 17 Apr 2019 06:07:39 GMT
Date	Tue, 16 Apr 2019 06:07:39 GMT
Transfer-Encoding	chunked
Connection	keep-alive

max-age
#

max-agecache-control 下的一个指令,表示 Response 的最大 Age。例如:

Cache-Control max-age=86400, private

含义为:该 Response 的有效期为1天,在一天以内,同样的 URL 将不会再次请求,直接使用缓存。

Expires
#

Expires 告诉客户端 Response 的过期时间。例如:

Expires Wed, 17 Apr 2019 06:07:39 GMT

含义为:该 ResponseWed, 17 Apr 2019 06:07:39 GMT 时过期,在这之前,同样的 URL 将不会再次请求,直接使用缓存。 需要注意的是,max-age 的优先级大于 expires

Last-Modified
#

Last-Modified 指明资源的最终修改时间,客户端在请求的时候,将这个值带在 If-Modified-Since 中。例如:

If-Modified-Since Thu, 11 Apr 2019 10:52:08 GMT

服务器会根据客户端传递的时间判断资源是否有更新,如果没有更新,服务器返回304,客户端直接使用缓存,如果有更新,服务器返回200和最新的资源。

Etag
#

Etag 类似于资源的唯一hash值,资源发生变化,这个值就发生变更,客户端在请求资源时,会将 Etag 放在 If-None-Match 中,例如:

If-None-Match W/“28111-1554979928000”

服务端根据客户端传递的 Etag 判断资源是否有更新,如果没有更新,服务器返回304,客户端直接使用缓存,如果有更新,服务器返回200和最新的资源。

启发式缓存(heuristic expiration)
#

在测试缓存机制时,发现了一种特殊情况,返回报文里没有 max-ageExpires,再次请求相同URL时却直接使用的缓存,没有重新发请求,请求报文如下:

HTTP/1.1 200 
Accept-Ranges	bytes
ETag	W/"28111-1554979928000"
Last-Modified	Thu, 11 Apr 2019 10:52:08 GMT
Date	Tue, 16 Apr 2019 07:23:21 GMT
Content-Type	image/jpeg
Content-Length	28111
Connection	keep-alive

让人摸不着头脑,在查询资料后发现一篇文章,提到了这个现象,Caching and NSURLConnection

在文章的指引下,仔细研究了下RFC2616-section13-Caching in HTTP,发现了答案。

RFC的原文如下:

If none of Expires, Cache-Control: max-age, or Cache-Control: s- maxage (see section 14.9.3) appears in the response, and the response does not include other restrictions on caching, the cache MAY compute a freshness lifetime using a heuristic. The cache MUST attach Warning 113 to any response whose age is more than 24 hours if such warning has not already been added. Also, if the response does have a Last-Modified time, the heuristic expiration value SHOULD be no more than some fraction of the interval since that time. A typical setting of this fraction might be 10%.

这是一种叫启发式缓存(heuristic expiration)的策略,在 response 中如果没有 Expires、max-age、s-maxage,来明确指定资源的过期时间,NSURLCache 会根据 Last-Modified 来计算一个过期时间。

根据实验结果,在iOS中计算公式是这样的:lifetime = (Last-Modified - Now) * 10%

参考文章
#

1、Caching and NSURLConnection 2、RFC2616-section13-Caching in HTTP 3、NSURLCache-NSHipster 4、iOS网络缓存扫盲篇 - 使用两行代码就能完成80%的缓存需求

相关文章

从FMDB线程安全问题说起

··6 分钟
本文讨论的 FMDB 版本为2.7.5,测试环境是 Xcode 10.1 & iOS 12.1。 一、问题记录 # 最近在分析崩溃日志的时候发现一个 FMDB 的 crash 频繁出现,crash 堆栈如下:

Core Animation学习笔记(三)- 视觉效果

··4 分钟
我们在之前的文章中讨论了CALayer的backing images与几何布局,这篇文章我们来看看如何通过它的特性来实现一些炫酷的效果。 圆角与边框 # conrnerRadius 属性控制图层角的曲率。它是一个浮点数,默认为0(为0的时候就是直角)。conrnerRadius 只影响背景色而不影响 backing image 和 sublayers。如果把 masksToBounds 设置成YES,图层里面的所有东西都会被截取。 CALayer另外两个非常有用属性就是borderWidth和borderColor。二者共同定义了图层边的绘制样式。这条线(也被称作stroke)沿着图层的bounds绘制,同时也包含图层的角。 borderWidth是以点为单位的定义边框粗细的浮点数,默认为0。borderColor定义了边框的颜色,默认为黑色。

Core Animation学习笔记(一)- CALayer

··7 分钟
本文是我阅读书籍《iOS CORE ANIMATION ADVANCED TECHNIQUES》的读书笔记,感谢原书作者及译者的分享! 推荐大家有时间可以读读原书,写的很精彩。中文版 一、Core Animation定义 # 什么是Core Animation,相信很多同学对于它既熟悉又陌生,从名字上来看它应该是一个做动画的框架,其实动画只是它的一部分,它曾经叫做Layer Kit。

Core Animation学习笔记(二)- 图层几何布局

··4 分钟
一、Layout # UIView有三个比较重要的布局属性:frame,bounds和center,CALayer对应地叫做frame,bounds和position。 frame是图层在父图层上的坐标,bounds是内部坐标({0, 0}通常是左上角)。 center和position要难理解一些,简单来说他们定义了anchorPoint在父图层中的位置(后面会详细说明)。

App Store上架漫谈

··4 分钟
前言 # 最近忙着写Bug😂,好久没有写文章了。今天和大家分享下我最近上架第二个独立开发的APP“识之”的上架经验(其实就是为了做一波广告)。