引言:为什么掌握 Swift 中的 HTTP 操作很重要
\n现代移动和桌面应用程序很少孤立存在。几乎任何应用——从天气小部件到银行客户端——都会与服务器交换数据。为此使用 HTTP 协议,而在 Swift(iOS/macOS)端,主要工具是 Foundation 框架及其 URLSession 类。
在本文中,我们将探讨如何正确创建 Swift HTTP 客户端:从简单的 GET 请求到复杂的错误处理和 JSON 操作。本材料既适合刚接触 iOS 开发的新手,也适合希望系统化知识的有经验的开发者。
\n我们将介绍使用 async/await(Swift 5.5+)的现代方法,这使代码简洁易读,同时也会涉及使用闭包(completion handlers)的传统方法以实现向后兼容。
URLSession 基础:创建与配置
\nURLSession 类是 Swift 中网络请求的主要“指挥者”。它管理连接、缓存和认证。在发起请求之前,需要创建一个会话实例。
会话类型
\n- \n
- 共享(单例):
URLSession.shared— 无自定义配置的简单会话。适用于基本请求。 \n - 默认:
URLSession(configuration: .default)— 允许配置超时、缓存和标头。 \n - 临时:
URLSession(configuration: .ephemeral)— 不将缓存和 cookies 保存到磁盘。非常适合私有数据。 \n - 后台:
URLSession(configuration: .background(withIdentifier:))— 用于后台下载/上传数据,即使应用被最小化也能进行。 \n
import Foundation\n\n// 简单会话\nlet sharedSession = URLSession.shared\n\n// 自定义会话,超时时间为 30 秒\nlet config = URLSessionConfiguration.default\nconfig.timeoutIntervalForRequest = 30\nconfig.timeoutIntervalForResource = 60\nlet customSession = URLSession(configuration: config)\n\n\n创建和发送 HTTP 请求
\n请求通过 URLRequest 类构建。它包含 URL、HTTP 方法、标头和请求体。我们来看一下主要方法:GET 和 POST。
使用 async/await 的 GET 请求(现代方法)
\n从 Swift 5.5 开始,Apple 添加了对异步函数(async/await)的支持。这是最简洁、最安全的网络操作方式。
func fetchData(from urlString: String) async throws -> Data {\n guard let url = URL(string: urlString) else {\n throw URLError(.badURL)\n }\n \n var request = URLRequest(url: url)\n request.httpMethod = "GET"\n request.setValue("application/json", forHTTPHeaderField: "Accept")\n \n let (data, response) = try await URLSession.shared.data(for: request)\n \n // 检查 HTTP 状态码\n guard let httpResponse = response as? HTTPURLResponse,\n (200...299).contains(httpResponse.statusCode) else {\n throw URLError(.badServerResponse)\n }\n \n return data\n}\n\n// 使用方式:\nTask {\n do {\n let data = try await fetchData(from: "https://api.example.com/users")\n print("获取到 \\(data.count) 字节")\n } catch {\n print("错误:\\(error.localizedDescription)")\n }\n}\n\n\n带 JSON 体的 POST 请求
\n要向服务器发送数据,使用 POST 方法。请求体通常编码为 JSON。
\n\nstruct User: Codable {\n let name: String\n let email: String\n}\n\nfunc createUser(_ user: User) async throws -> Data {\n let url = URL(string: "https://api.example.com/users")!\n var request = URLRequest(url: url)\n request.httpMethod = "POST"\n request.setValue("application