URLSession — 是 iOS 和 macOS 中用于网络请求的 API,属于 Foundation 框架的一部分,提供统一的接口来处理 HTTP、HTTPS、后台下载和 WebSocket。它取代了已过时的 NSURLConnection,并成为 Apple 开发者的主要网络工具。根据 Apple Developer Documentation (2025),URLSession 处理超过 90% 的 iPhone 和 iPad 应用中的网络流量。
要点
URLSession — 是 Apple 在 iOS 7 和 macOS 10.9 中引入的网络操作 API。它取代了 NSURLConnection,提供了更灵活、更强大的网络工作模型。该库支持 HTTP/1.1、HTTP/2、HTTP/3 和 WebSocket,以及用于数据下载的后台会话。
URLSession 相对于旧的 NSURLConnection 的主要优势——通过单一会话支持多个同时连接、可自定义配置以及暂停和恢复下载的能力。会话将一组网络任务与通用设置组合在一起:缓存、Cookie 策略、超时、TLS 证书。
在 iOS 中,URLSession 与系统 DNS 缓存、电源管理和后台进程协同工作。当应用最小化时,系统可以通过后台会话继续下载数据,并在完成后通过完成处理程序通知应用。后台会话对于下载大文件、更新内容以及同步处理文档和媒体文件的应用中的数据特别有用。要使用后台会话,需要实现 URLSessionDelegate 并在创建会话时传递配置标识符——系统在应用重启后使用此标识符来恢复会话。
URLSession 的一个重要优势是支持 HTTP/2 和 HTTP/3。HTTP/2 的多路复用允许通过单个 TCP 连接发送多个请求,从而减少延迟和服务器负载。基于 UDP 之上的 QUIC 协议的 HTTP/3,通过消除 TCP 握手实现更快速的连接建立。
URLSession 的架构由三个关键组件组成:会话配置、会话本身和任务(tasks)。每个组件负责网络交互的一个方面,它们的组合决定了应用在网络工作时的行为。
配置设置会话参数——从超时到缓存策略。有三种类型:.default(带磁盘缓存的标准配置)、.ephemeral(不保存缓存和 Cookie)和 .background(用于后台下载)。在配置中可以设置每个主机的最大连接数、请求和资源超时、TLS 策略和代理。
URLSessionTask — 是所有网络操作的基类。主要子类:URLSessionDataTask 用于 GET 和 POST 请求,在内存中返回数据;URLSessionDownloadTask 用于下载文件到磁盘;URLSessionUploadTask 用于上传文件到服务器;URLSessionWebSocketTask 用于从 iOS 13 开始使用 WebSocket。
会话委托接收关于任务进度的事件:数据接收、下载完成、身份验证错误、重定向。URLSessionDelegate 及其子协议允许在身份验证时拦截 TLS 证书、通过 URLCache 管理响应缓存以及监控大文件下载进度。作为替代方案,在不需要处理中间事件的简单情况下,可以使用闭包(完成处理程序)。
使用 URLSession 的基本场景如下:创建配置,基于配置创建会话,然后通过会话创建带有 URL 请求的任务,并启动任务。让我们分析一个带有闭包的 GET 请求示例。此模式在大多数 iOS 应用中用于从 REST API 获取数据、加载图像以及与云服务交互。
let url = URL(string: "https://api.example.com/users")!
let session = URLSession.shared
let task = session.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
print("错误: \(error!.localizedDescription)")
return
}
if let json = try? JSONSerialization.jsonObject(with: data) {
print("JSON: \(json)")
}
}
task.resume()
在示例中使用 URLSession.shared — 一个带有 .default 配置的单例,用于简单请求。dataTask 创建一个异步操作,但不会启动它——必须调用 resume()。闭包在请求完成后执行,并返回 data、response 或 error。对于具有自定义配置的会话,使用 URLSession(configuration:) 初始化器,它允许为所有会话任务设置缓存策略、超时、最大连接数、默认 HTTP 标头和代理设置。这种方法可以完全控制应用中的网络行为。
URLSession 支持具有暂停和恢复功能的文件下载,以及后台下载。DownloadTask 将文件保存到临时目录,在完成闭包中需要将其移动到永久位置。
let url = URL(string: "https://example.com/file.zip")!
let session = URLSession(configuration: .default)
let task = session.downloadTask(with: url) { location, _, _ in
guard let location = location else { return }
let destination = FileManager.default.temporaryDirectory
.appendingPathComponent("file.zip")
try? FileManager.default.moveItem(at: location, to: destination)
}
task.resume()
闭包中的 location 参数指向需要移动的临时文件,否则系统将在退出闭包后将其删除。为了跟踪进度,使用 URLSessionDownloadDelegate 委托及其 didWriteData 方法,该方法传递已写入的字节数和文件总大小——这些数据可用于在用户界面中显示进度条。带有 downloadTask 的后台会话允许在应用最小化后继续下载,完成后系统调用 AppDelegate 中的处理程序。
Alamofire — 是一个构建在 URLSession 之上的 Swift 库,提供更声明式的接口。原生 API 和 Alamofire 之间的选择取决于项目的复杂性和团队的偏好。
| 标准 | URLSession | Alamofire |
|---|---|---|
| 依赖 | 无,内置于 Foundation | 需要 SPM 或 CocoaPods |
| 语法 | 带闭包的命令式 | 带链式调用的声明式 |
| JSON 处理 | 手动 JSONSerialization | responseDecodable 配合 Codable |
| 拦截器 | 通过委托 | RequestInterceptor, EventMonitor |
| 进度 | 通过委托 | downloadProgress, uploadProgress |
对于简单项目,URLSession 已经足够且不增加依赖。Alamofire 适用于具有大量网络请求、复杂错误处理和需要简洁语法的项目。这两种技术都使用共同的 URLSessionConfiguration 基础,并且相互兼容。在选择时需要考虑,URLSession 完全由 Apple 控制并随 iOS 更新,而 Alamofire 需要库开发者支持与新 OS 版本的兼容性。
现代 Swift 支持 async/await,这使得网络请求比闭包更易读。让我们看看使用异步语法的同一个 GET 请求。
func fetchUsers() async throws -> [User] {
let url = URL(string: "https://api.example.com/users")!
let (data, _) = try await URLSession.shared.data(from: url)
let users = try JSONDecoder().decode([User].self, from: data)
return users
}
data(from:) 方法从 iOS 15 和 macOS 12 开始可用。它返回一个元组 (Data, URLResponse),并在网络问题时抛出错误。使用 Codable 模型的 JSONDecoder 自动反序列化响应——这取代了前面示例中繁琐的 JSONSerialization。
对于带 JSON 正文的 POST 请求,使用 URLRequest,在其中配置方法、Content-Type 标头和 Data 格式的请求正文。Async/await 使这个过程简洁明了,而错误处理通过 do-catch 块也很简单。
func createUser(name: String) async throws -> User {
var request = URLRequest(url: URL(string: "https://api.example.com/users")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = try JSONEncoder().encode(["name": name])
request.httpBody = body
let (data, _) = try await URLSession.shared.data(for: request)
return try JSONDecoder().decode(User.self, from: data)
}
常见问题
URLSession 是 NSURLConnection 的现代替代品,在 iOS 7 中引入。主要区别:通过会话支持多个连接、暂停和恢复任务、后台下载和 WebSocket。NSURLConnection 已过时,不建议在新项目中使用。
要跟踪进度,使用 URLSessionDownloadDelegate 委托及其 urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite) 方法。对于 dataTask,可以订阅 URLSessionTaskDelegate 并通过 didSendBodyData 接收更新。
后台下载通过 .background(withIdentifier:) 配置进行设置。应用在 AppDelegate 中注册完成处理程序,并在最小化或关闭后仍能接收结果。系统管理下载并通过 sessionDidFinishEvents 委托通知应用。
是的,从 iOS 13 开始,URLSession 通过 URLSessionWebSocketTask 类支持 WebSocket。它通过 webSocketTask(with:) 方法创建,并提供 send、receive 方法,支持文本和二进制消息,以及用于保持连接的 ping/pong。
超时通过 URLSessionConfiguration 设置:timeoutIntervalForRequest(等待请求响应)和 timeoutIntervalForResource(整个下载的最长时间)。默认值:请求 60 秒,资源 7 天。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。