介绍
现代 iOS 和 macOS 应用程序几乎离不开与远程服务器的交互。无论是从新闻订阅中加载数据、提交注册表单,还是同步文件——所有这些操作都需要一个实现良好的 HTTP 客户端。在 Swift 生态系统中,开发者可以使用强大的内置框架 URLSession,随着 async/await 的引入,这一框架每年都变得更加便捷。
在本文中,我们将探讨如何在 Swift 中正确创建 HTTP 请求,从基本结构开始,一直到错误处理和数据序列化的高级技巧。您将学习如何为您的应用程序编写干净、安全且高性能的网络代码。
URLSession 基础:您的第一个 HTTP 请求
URLSession 类是 Swift 中所有网络工作的基础。它管理配置、缓存、会话以及请求的直接执行。让我们来看一个从服务器获取数据的简单 GET 请求。
创建一个简单的 GET 请求
import Foundation
// 1. 创建 URLguard let url = URL(string: "https://api.example.com/users") else { print("无效的 URL") return}
// 2. 创建请求(默认为 GET)var request = URLRequest(url: url)request.httpMethod = "GET"request.setValue("application/json", forHTTPHeaderField: "Accept")
// 3. 创建会话let session = URLSession.shared
// 4. 执行请求(旧式闭包方法)let task = session.dataTask(with: request) { data, response, error in if let error = error { print("请求错误:\(error.localizedDescription)") return } guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { print("服务器返回错误") return } if let data = data, let jsonString = String(data: data, encoding: .utf8) { print("收到数据:\(jsonString)") }}task.resume() // 重要!启动任务关键点:始终检查响应状态(200...299),不要忘记调用 resume(),并处理潜在错误。在实际项目中,这段代码通常会提取到一个独立的服务层中。
现代方法:async/await
从 Swift 5.5 开始,可以使用 async/await,这使得代码更具可读性,并消除了“闭包金字塔”。
func fetchUsers() async throws -> Data { guard let url = URL(string: "https://api.example.com/users") else { throw URLError(.badURL) } var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Accept") let (data, response) = try await URLSession.shared.data(for: request) guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { throw URLError(.badServerResponse) } return data}这段代码可以从任何异步函数或任务中调用,大大简化了逻辑。
使用 JSON:Codable 和数据模型
数据很少以“原始”形式出现。更多时候,我们处理的是 JSON。Swift 提供了一个优雅的解决方案——Codable 协议(结合了 Encodable 和 Decodable)。
创建模型并进行解码
// 1. 定义数据结构struct User: Codable { let id: Int let name: String let email: String}
// 2. 获取用户数组的异步函数func fetchUsers() async throws -> [User] { let data = try await fetchUsersData() // 来自前一个示例 let decoder = JSONDecoder() return try decoder.decode