URLSession、Alamofire 和 Moya
1. URLSession
1.1 核心概念
URLSession 是 Apple 官方提供的網絡請求 API,封裝在 Foundation 框架中。它支持 HTTP、HTTPS、FTP 等協議,可用于:
? ? 普通網絡請求(GET/POST)
? ? 后臺下載、斷點續傳
? ? WebSocket 連接
? ? 數據上傳(multipart/form-data)
? ? 流式傳輸
1.2 組成部分
URLSession 主要由以下三部分組成:
? 1. URLSession:管理網絡任務的會話對象。
? 2. URLSessionTask:
? ? URLSessionDataTask:處理普通的 HTTP 請求,獲取 Data 數據
? ? URLSessionDownloadTask:支持后臺下載、斷點續傳
? ? URLSessionUploadTask:上傳文件
? ? URLSessionStreamTask:處理 TCP 連接和 WebSocket 連接
? 3. URLSessionDelegate:
? ? 處理身份認證、數據接收、下載進度、錯誤處理等。
1.3 使用方式
URLSessionDataTask是平時使用頻率最高的,平時使用的POST還有GET請求都是通過它來實現的。
1.3.1 發送 GET 請求
import Foundationlet url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")!
let task = URLSession.shared.dataTask(with: url) { data, response, error inif let error = error {print("請求失敗: \(error)")return}guard let data = data else {print("無數據返回")return}// 解析 JSONdo {let json = try JSONSerialization.jsonObject(with: data, options: [])print("請求成功: \(json)")} catch {print("JSON 解析失敗: \(error)")}
}task.resume()
1.3.2 發送 POST 請求
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")let parameters = ["title": "foo", "body": "bar", "userId": 1]
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)let task = URLSession.shared.dataTask(with: request) { data, response, error inguard let data = data, error == nil else {print("請求失敗: \(error!)")return}let json = try? JSONSerialization.jsonObject(with: data, options: [])print("請求成功: \(json!)")
}task.resume()
URLSessionDownloadTask用于下載,有兩種方式:Block 和 代理,URLSession 在下載文件的時候,是將數據一點點地寫入本地的一個臨時文件,這個臨時文件系統會很很快刪除,所以我們需要把文件從這個臨時地址移動到一個永久的地址保存起來,這樣才算完整的下載完一個文件,另外,使用 NSURLSessionConfiguration 的 background 模式可以做到后臺下載,并且即使應用被 Kill 之后也還可以恢復之前的下載任務。
1.3.3 下載文件
let url = URL(string: "https://example.com/file.zip")!
let task = URLSession.shared.downloadTask(with: url) { localURL, response, error inguard let localURL = localURL else { return }print("文件下載成功,存儲在: \(localURL.path)")
}
task.resume()
1.4 優缺點
? 優點:
? ? 官方提供,穩定可靠
? ? 支持后臺下載、斷點續傳
? ? 無額外依賴,輕量級
? ? 高度可定制,適用于各種網絡任務
? 缺點:
? ? 代碼較冗長,每次請求都需要手動解析 Data
? ? 不支持鏈式調用
? ? 不支持內置 JSON 解析和參數編碼
? ? 不適合復雜的 REST API 結構
2. Alamofire
2.1 核心概念
Alamofire 是基于 URLSession 的封裝,簡化了常見的網絡請求,提供鏈式調用、JSON 解析、文件上傳等功能。
我們查看代碼發現,AF直接就是Session.default。所以Alamofire就是基于NSURLSession進行封裝的。
返回類型
//Data示例let url = "https://httpny.org/get"AF.request(url).responseData { response inswitch response.result {case let .success(data):print("data:\(String(describing: data))")case let .failure(error):print(error)}}//String示例AF.request(url).responseString { response inswitch response.result {case let .success(data):print("data:\(String(describing: data))")case let .failure(error):print(error)}}//JSON示例AF.request(url).responseJSON { response inswitch response.result {case let .success(data):print("data:\(String(describing: data))")case let .failure(error):print(error)}}//自定義格式示例AF.request(url).responseDecodable(of: PersonResponse.self) { response inswitch response.result {case let .success(data):print("data:\(String(describing: data))")case let .failure(error):print(error)}}
2.2 使用方式
2.2.1 發送 GET 請求
import AlamofireAF.request("https://jsonplaceholder.typicode.com/todos/1").responseJSON { response inswitch response.result {case .success(let data):print("請求成功: \(data)")case .failure(let error):print("請求失敗: \(error)")}
}
2.2.2 發送 POST 請求
let parameters: [String: Any] = ["title": "foo", "body": "bar", "userId": 1]AF.request("https://jsonplaceholder.typicode.com/posts",method: .post,parameters: parameters,encoding: JSONEncoding.default)
.responseJSON { response inprint("請求結果: \(response)")
}
2.2.3 文件上傳
AF.upload(multipartFormData: { multipartFormData inlet fileURL = URL(fileURLWithPath: "/path/to/file")multipartFormData.append(fileURL, withName: "file")
}, to: "https://example.com/upload")
.response { response inprint("上傳結果: \(response)")
}
2.3 優缺點
? 優點:
? ? 代碼簡潔,封裝良好
? ? 支持 JSON 解析
? ? 支持文件上傳、下載
? ? 支持請求隊列和隊列優先級
? 缺點:
? ? 比 URLSession 體積大
? ? 自定義控制較少
? ? 不適用于 API 統一管理
3. Moya
3.1 核心概念
Moya 是基于 Alamofire 的進一步封裝,旨在統一 API 管理,適合大型項目。
Moya和Alamofire之間的緊密聯系只是因為Moya本身并沒有真正進行任何聯網。它使用Alamofire經過實戰檢驗的網絡功能,并且僅提供其他功能,類型和概念來進一步抽象Alamofire。
3.2 使用方式
3.2.1 定義 API
import Moyaenum API {case getPostscase getPost(id: Int)case createPost(title: String, body: String, userId: Int)
}extension API: TargetType {var baseURL: URL { return URL(string: "https://jsonplaceholder.typicode.com")! }var path: String {switch self {case .getPosts: return "/posts"case .getPost(let id): return "/posts/\(id)"case .createPost: return "/posts"}}var method: Moya.Method {switch self {case .getPosts, .getPost: return .getcase .createPost: return .post}}var task: Task {switch self {case .getPosts, .getPost: return .requestPlaincase .createPost(let title, let body, let userId):return .requestParameters(parameters: ["title": title, "body": body, "userId": userId],encoding: JSONEncoding.default)}}
}
3.2.2 發送請求
let provider = MoyaProvider<API>()provider.request(.getPosts) { result inswitch result {case .success(let response):let json = try? response.mapJSON()print("請求成功: \(json!)")case .failure(let error):print("請求失敗: \(error)")}
}
3.3 優缺點
? 優點:
? ? 適合 API 統一管理
? ? 結構清晰,代碼更模塊化
? ? 支持 RxSwift 和 Combine
? 缺點:
? ? 比 Alamofire 更重
? ? 學習成本較高
總結
框架 | 適用場景 | 主要優勢 | 主要劣勢 |
---|---|---|---|
URLSession | 基礎網絡請求 | 輕量級、無依賴 | 代碼繁瑣,需要手動解析 JSON |
Alamofire | 現代 REST API | 代碼簡潔、支持 JSON | 依賴庫較大,不適合 API 統一管理 |
Moya | 大型項目 | 適合 MVVM 架構,API 統一管理 | 復雜度高,學習成本高 |