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 Foundation
let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("请求失败: \(error)")
return
}
guard let data = data else {
print("无数据返回")
return
}
// 解析 JSON
do {
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 in
guard 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 in
guard 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 in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
//String示例
AF.request(url).responseString { response in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
//JSON示例
AF.request(url).responseJSON { response in
switch 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 in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
2.2 使用方式
2.2.1 发送 GET 请求
import Alamofire
AF.request("https://jsonplaceholder.typicode.com/todos/1").responseJSON { response in
switch 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 in
print("请求结果: \(response)")
}
2.2.3 文件上传
AF.upload(multipartFormData: { multipartFormData in
let fileURL = URL(fileURLWithPath: "/path/to/file")
multipartFormData.append(fileURL, withName: "file")
}, to: "https://example.com/upload")
.response { response in
print("上传结果: \(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 Moya
enum API {
case getPosts
case 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 .get
case .createPost: return .post
}
}
var task: Task {
switch self {
case .getPosts, .getPost: return .requestPlain
case .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 in
switch 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 统一管理 | 复杂度高,学习成本高 |