URLSession 详解
问题
URLSession 的架构和核心 API 是什么?如何发起网络请求?
答案
URLSession 架构
Configuration 类型
| 类型 | 说明 |
|---|---|
.default | 使用磁盘缓存、Cookie |
.ephemeral | 无持久化(类似无痕模式) |
.background | 后台下载/上传(App 被挂起仍继续) |
基本请求(async/await)
// GET 请求
func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, response) = try await URLSession.shared.data(from: url)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw NetworkError.invalidResponse
}
return try JSONDecoder().decode(User.self, from: data)
}
// POST 请求
func createUser(_ user: User) async throws -> User {
var request = URLRequest(url: URL(string: "https://api.example.com/users")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(user)
let (data, _) = try await URLSession.shared.data(for: request)
return try JSONDecoder().decode(User.self, from: data)
}
后台下载
let config = URLSessionConfiguration.background(withIdentifier: "com.app.download")
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: url)
task.resume()
// 通过 delegate 接收进度和完成回调
extension DownloadManager: URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL) {
// 文件下载到临时路径,需要移动到目标路径
try? FileManager.default.moveItem(at: location, to: destinationURL)
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64, totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64) {
let progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
print("Progress: \(progress)")
}
}
请求超时与重试
var request = URLRequest(url: url)
request.timeoutInterval = 15 // 请求超时 15 秒
let config = URLSessionConfiguration.default
config.timeoutIntervalForResource = 300 // 整体资源超时 5 分钟
config.waitsForConnectivity = true // 等待网络恢复
常见面试问题
Q1: URLSession.shared 和自定义 URLSession 的区别?
答案:
URLSession.shared:单例,不可设置 delegate,不可自定义 configuration,适合简单请求- 自定义 URLSession:可设置缓存策略、Cookie 策略、后台任务、证书校验等
Q2: 如何实现断点续传?
答案:
- 下载失败时保存
resumeData(包含已下载的范围信息) - 恢复时调用
session.downloadTask(withResumeData: resumeData) - 服务器需要支持 HTTP Range 请求