URLSession 的三件套

iOS 原生网络就是 URLSession。它由三层构成:session(会话,管理连接与配置)、configuration(会话配置,决定缓存、超时、蜂窝开关)、task(具体的一次请求任务)。大多数情况用共享会话就够,需要精细控制时再自定义 configuration。

网络层的目标:让上层只管"要什么数据",缓存、超时、重试这些细节都藏在下面。

这篇从发请求讲到缓存策略,把 iOS 网络层搭得既快又省。

异步发起一个请求

配合 Swift 并发,发请求就是一行 await。URLSession.shared.data(from:) 同时拿到数据与响应。

func fetch() async throws -> [Item] {
  let url = URL(string: "https://api.example.com/items")!
  let (data, resp) = try await URLSession.shared.data(from: url)
  guard let http = resp as? HTTPURLResponse,
        http.statusCode == 200 else { throw URLError(.badServerResponse) }
  return try JSONDecoder().decode([Item].self, from: data)
}

先检查状态码再解码,是网络层最基本的健壮性。

配置请求:方法与头

GET 之外要用 URLRequest 自定义:设 httpMethod、加请求头、放 body。POST 上传 JSON 时记得设 Content-Type。

请求配置要点
  • httpMethodGET / POST / PUT / DELETE。
  • setValue加 Authorization、Content-Type 头。
  • httpBody放序列化后的 JSON。
  • timeoutInterval设合理超时,别等太久。

系统的 URL 缓存

URLSession 自带一个内存加磁盘的 URLCache,默认会遵守服务端返回的缓存头(Cache-Control)。也就是说,服务端说这个资源能缓存一分钟,系统就会在这分钟里直接给你缓存结果,不再请求网络。

let config = URLSessionConfiguration.default
config.urlCache = URLCache(
  memoryCapacity: 8 * 1024 * 1024,
  diskCapacity: 50 * 1024 * 1024)
config.requestCachePolicy = .useProtocolCachePolicy

用对缓存头,很多"第二次打开快"的需求系统就帮你做了。

自定义缓存策略

服务端不给缓存头时,就得自己决定。常用策略:有网就刷新、同时把旧数据先展示;无网就读本地缓存。把"网络结果"和"本地缓存"分成两层,界面永远先有内容。

iOS 网络缓存示意:左侧一朵云经管道连接分层存储块,右侧一部手机与一个本地缓存立方体形成双向箭头
分层缓存:云端数据先入本地缓存层,再供界面读取。

缓存键通常用请求 URL 加参数,注意区分可缓存与不可缓存的请求(POST 一般不缓存)。