15-16.【HTTP】HTTP 缓存机制有哪些?iOS 如何控制?

2 阅读2分钟

TTP 缓存是优化 iOS App 性能最有效的手段之一。它能减少流量消耗、节省电池电量,并显著提升用户感知的加载速度。

HTTP 缓存主要分为两大类:强缓存协商缓存


1. HTTP 缓存分类

A. 强缓存 (Strong Caching)

浏览器(或 iOS 系统)直接从本地获取数据,不向服务器发送请求

  • Expires: 绝对时间(如:Expires: Wed, 21 Oct 2026 07:28:00 GMT)。受限于客户端时钟。
  • Cache-Control: 相对时间(如:max-age=3600,表示 1 小时内有效)。它是现代标准的优先选择。

B. 协商缓存 (Conditional Caching)

本地缓存已过期,App 向服务器询问:“我这份数据还能用吗?”

  • Last-Modified / If-Modified-Since: 基于文件的最后修改时间。
  • ETag / If-None-Match: 基于内容的唯一哈希值(指纹)。优先级高于 Last-Modified
  • 结果:如果没变,服务器返回 304 Not Modified(不含 Body),App 继续用旧数据;如果变了,返回 200 OK 和新数据。

2. iOS 中的缓存控制 (NSURLCache)

在 iOS 中,URLSession 默认使用 URLCache.shared 来管理缓存。它会自动处理上述的 HTTP 头部逻辑。

A. 设置缓存容量

通常在 AppDelegate 或网络层初始化阶段设置,建议将磁盘缓存设置大一些。

Swift

let memoryCapacity = 4 * 1024 * 1024 // 4MB
let diskCapacity = 50 * 1024 * 1024   // 50MB
let cache = URLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "my_cache_path")
URLCache.shared = cache

B. 请求层面的缓存策略

在创建 URLRequest 时,你可以通过 cachePolicy 显式控制:

Swift

var request = URLRequest(url: url)

// 常用策略:
request.cachePolicy = .useProtocolCachePolicy      // 1. 默认:遵从 HTTP 协议头
request.cachePolicy = .reloadIgnoringLocalCacheData // 2. 忽略缓存,强制刷服务器
request.cachePolicy = .returnCacheDataElseLoad      // 3. 有缓存就用,没缓存再请求(适合离线模式)
request.cachePolicy = .returnCacheDataDontLoad      // 4. 只读缓存,不发请求(强制离线)

3. 如何手动清理缓存

当用户点击 App 内的“清理缓存”按钮时,你可以调用:

Swift

// 清理所有缓存
URLCache.shared.removeAllCachedResponses()

// 清理特定请求的缓存
URLCache.shared.removeCachedResponse(for: request)

4. 关键点:为什么我的缓存没生效?

  1. 服务器响应头不支持:如果服务器返回的 Cache-Controlno-storeprivate(且未配置正确),iOS 不会缓存。
  2. HTTPS 限制:默认情况下,某些安全等级高的磁盘缓存可能不持久化 HTTPS 响应,除非显式允许。
  3. URL 变动:URL 字符串中哪怕多一个空格或一个随机参数(如 ?timestamp=...),缓存就会失效。
  4. Header 冲突:如果你在 URLRequest 中手动设置了 Cache-Control: no-cache,会覆盖服务器的缓存指令。

总结

  • 强缓存max-age)最快,因为根本不发请求。
  • 协商缓存ETag)最稳,保证数据永远是最新的,且流量消耗极小。
  • 在 iOS 中,尽量复用 URLCache.shared 并根据业务需求选择合适的 cachePolicy