原文链接:github.com/Alamofire/A…说明:本文是 Alamofire 的高级文档,讲解自定义会话、拦截器、证书校验、路由封装、Combine / Swift Concurrency 等进阶能力。
Alamofire 构建于 URLSession 和 Foundation 的 URL 加载系统之上。为充分发挥框架能力,建议你熟悉底层网络栈的概念与能力。
推荐阅读官方资料
- URL Loading System 编程指南
URLSession类参考文档URLCache类参考文档URLAuthenticationChallenge类参考文档
Session
Alamofire 的 Session 职责大体等价于它内部持有的 URLSession 实例:它提供 API 生成各类 Request 子类,封装不同的 URLSessionTask,同时封装一套配置,作用于该实例产生的所有请求。
Session 提供单例 default,AF 命名空间顶层 API 就是由它驱动。下面两行代码完全等价:
swift
AF.request("https://httpbin.org/get")
let session = Session.default
session.request("https://httpbin.org/get")
创建自定义 Session 实例
多数应用需要以各种方式自定义 Session 行为,最简单的方式是使用便捷构造器,将实例保存为全局单例供 App 各处使用。
swift
public convenience init(
configuration: URLSessionConfiguration = URLSessionConfiguration.af.default,
delegate: SessionDelegate = SessionDelegate(),
rootQueue: DispatchQueue = DispatchQueue(label: "org.alamofire.session.rootQueue"),
startRequestsImmediately: Bool = true,
requestQueue: DispatchQueue? = nil,
serializationQueue: DispatchQueue? = nil,
interceptor: RequestInterceptor? = nil,
serverTrustManager: ServerTrustManager? = nil,
redirectHandler: RedirectHandler? = nil,
cachedResponseHandler: CachedResponseHandler? = nil,
eventMonitors: [EventMonitor] = []
)
该构造器可以自定义 Session 的全部基础行为。
使用 URLSessionConfiguration 创建 Session
想要定制底层 URLSession 的行为,可以传入自定义的 URLSessionConfiguration。推荐基于 URLSessionConfiguration.af.default 来修改,该默认配置已经预置了 Alamofire 的 Accept‑Encoding、Accept‑Language、User‑Agent 请求头;当然也可以传入任意配置。
swift
let configuration = URLSessionConfiguration.af.default
configuration.allowsCellularAccess = false
let session = Session(configuration: configuration)
不建议在
URLSessionConfiguration里设置Authorization、Content‑Type这类请求头。应该通过请求的 headers 参数、ParameterEncoder或者RequestAdapter来添加。根据 Apple 文档:配置对象一旦被交给URLSession(Alamofire 中即初始化 Session)之后,再修改配置属性不会生效。
SessionDelegate
SessionDelegate 封装全部 URLSessionDelegate 及相关协议回调。同时它也是每个 Request 的状态提供者,让请求可以间接拿到所属 Session 的状态。SessionDelegate 可以传入自定义 FileManager,用于磁盘读写,例如上传、下载文件操作。
swift
let delegate = SessionDelegate(fileManager: .default)
startRequestsImmediately
默认情况下,Session 只要给请求添加至少一个响应回调,就会自动调用 resume() 启动请求。设置为 false,就必须手动调用每个 Request 的 resume()。
swift
let session = Session(startRequestsImmediately: false)
Session 的调度队列 DispatchQueue
默认 Session 使用同一个调度队列处理全部异步工作:包括 URLSession delegate 的底层队列、创建请求、响应序列化、Session/Request 内部状态变更。如果性能分析发现创建请求或者序列化响应成为瓶颈,可以为不同工作分配独立队列。
swift
let rootQueue = DispatchQueue(label: "com.app.session.rootQueue")
let requestQueue = DispatchQueue(label: "com.app.session.requestQueue")
let serializationQueue = DispatchQueue(label: "com.app.session.serializationQueue")
let session = Session(
rootQueue: rootQueue,
requestQueue: requestQueue,
serializationQueue: serializationQueue
)
自定义
rootQueue必须是串行队列;requestQueue、serializationQueue可以串行或并行。没有性能问题优先使用串行。
添加 RequestInterceptor
RequestInterceptor 协议同时继承 RequestAdapter & RequestRetrier,提供强大的请求修改与重试能力。既可以作用于整个 Session,也可以单独作用于某一个请求。后面会详细介绍,内置实现如 RetryPolicy。
swift
let policy = RetryPolicy()
let session = Session(interceptor: policy)
添加 ServerTrustManager(服务端证书信任管理器)
iOS14 /tvOS14 /watchOS7 /macOS11+,Apple 已经在 Info.plist 原生支持证书锁定,优先使用系统能力,再考虑 Alamofire 的实现。
ServerTrustManager 维护域名与信任评估器的映射,用来定制 TLS 校验逻辑,支持证书锁定、公钥锁定、证书吊销校验。
swift
let manager = ServerTrustManager(evaluators: ["httpbin.org": PinnedCertificatesTrustEvaluator()])
let session = Session(serverTrustManager: manager)
添加 RedirectHandler(重定向处理器)
RedirectHandler 自定义 HTTP 重定向逻辑,支持 Session 全局设置,也可以单请求覆盖。Alamofire 提供实现类 Redirector。
swift
let redirector = Redirector(behavior: .follow)
let session = Session(redirectHandler: redirector)
添加 CachedResponseHandler(缓存处理器)
CachedResponseHandler 自定义响应缓存逻辑,全局或单请求均可配置,内置实现 ResponseCacher。
swift
let cacher = ResponseCacher(behavior: .cache)
let session = Session(cachedResponseHandler: cacher)
添加 EventMonitor(事件监视器)
EventMonitor 监听 Alamofire 内部各类事件,常用于日志打印、埋点。Session 初始化时传入数组。
swift
let monitor = ClosureEventMonitor()
monitor.requestDidCompleteTaskWithError = { (request, task, error) in
debugPrint(request)
}
let session = Session(eventMonitors: [monitor])
操作全部活跃请求
该接口不常用,withAllRequests 可以批量操作当前所有正在运行的请求,执行在 rootQueue,逻辑要尽量简短。
swift
let session: Session = ...
session.withAllRequests { requests in
requests.forEach { $0.suspend() }
}
一键取消全部请求,完成后回调:
swift
session.cancelAllRequests(completingOn: .main) {
print("已取消全部请求")
}
注意:操作是异步执行,执行时部分请求可能已经完成或新建,不能保证操作集合完全符合预期。
基于已有 URLSession 创建 Session
除便捷构造器,也可以直接传入现成的 URLSession,但有诸多限制,优先使用便捷初始化:
- 不支持后台模式的 URLSession,会触发运行时错误。
- 必须手动创建
SessionDelegate,作为 URLSession 的 delegate,同时传给 Session。 - 必须自定义 OperationQueue 作为 delegateQueue,底层绑定串行 DispatchQueue,作为 Session 的 rootQueue。
swift
let rootQueue = DispatchQueue(label: "org.alamofire.customQueue")
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
queue.underlyingQueue = rootQueue
let delegate = SessionDelegate()
let configuration = URLSessionConfiguration.af.default
let urlSession = URLSession(
configuration: configuration,
delegate: delegate,
delegateQueue: queue
)
let session = Session(session: urlSession, delegate: delegate, rootQueue: rootQueue)
请求 Requests
Alamofire 的请求分为 DataRequest、UploadRequest、DownloadRequest。DataRequest、DownloadRequest 继承自父类 Request;UploadRequest 继承 DataRequest。不要直接实例化 Request,全部由 Session 的 request 系列方法产出。
请求流水线 Request Pipeline
当创建一个 Request 子类之后,会经过一套流水线处理,成功请求完整流程:
- 将 method /headers/parameters 封装为内部
URLRequestConvertible;如果直接传入该类型,则直接复用。 - 调用
asURLRequest()生成第一个URLRequest,存入请求数组;如果创建时传入RequestModifier,此时执行修改。 - 执行 Session / Request 上的
RequestAdapter/RequestInterceptor,修改 URLRequest,修改后的对象同样保存。 - Session 根据 URLRequest 创建
URLSessionTask,发起网络。 - Task 完成,收集
URLSessionTaskMetrics,执行校验器 Validator。 - 执行追加的响应回调,例如
responseDecodable。
流水线任意步骤都可能抛出错误,错误交给 Request。一旦发生错误,会尝试执行 RequestRetrier,如果选择重试,整个流水线重新跑一遍。
流水线各环节是否会报错:
- 参数封装:不会失败
asURLRequest():可以抛出(参数编码、URL 校验失败)RequestAdapter:适配过程可以报错(如 token 缺失)- 创建 URLSessionTask:不会失败
- URLSessionTask 执行:网络异常、取消等会产生错误
- 响应回调:解析数据可以抛出错误
Request 基类
Request 不区分请求类型,保存所有请求通用状态与能力。
State 状态枚举
swift
public enum State {
case initialized // 初始化完成
case resumed // 已启动
case suspended // 挂起暂停
case cancelled // 已取消
case finished // 请求全部完成
}
resume():启动 / 恢复网络请求。startRequestsImmediately=true时添加回调会自动调用。suspend():暂停请求。只有 DownloadRequest 有机会断点续传;其他请求恢复会重新发起。cancel():取消请求,状态不可回退。error 属性被置为AFError.explicitlyCancelled。
请求已经 finished 之后,如果再追加新的响应回调,会回到 resumed 状态重新执行网络请求。
Progress 进度
提供 uploadProgress、downloadProgress 闭包接口,建议在添加响应回调之前设置。
swift
AF.request(...)
.uploadProgress { progress in
print(progress)
}
.downloadProgress { progress in
print(progress)
}
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
上传进度依赖:上传 Data 长度 / 文件大小 / 手动设置的 Content‑Length。下载进度依赖:服务端返回
Content‑Length响应头,否则进度一直是 0 直到完成。
处理重定向 Redirect
除 Session 全局 RedirectHandler,每个请求可以单独设置,会覆盖全局配置。
swift
let redirector = Redirector(behavior: .follow)
AF.request(...)
.redirect(using: redirector)
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
一个请求只能设置一个 RedirectHandler,多次设置会运行时崩溃。
自定义缓存 Caching
单请求可以设置 CachedResponseHandler,覆盖 Session 全局配置。
swift
let cacher = ResponseCacher(behavior: .cache)
AF.request(...)
.cacheResponse(using: cacher)
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
一个请求只能设置一个 CachedResponseHandler。
Credentials 凭证
用于处理服务器弹出的 HTTP 认证质询(401)。
swift
AF.request(...)
.authenticate(username: "user@example.domain", password: "password")
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
⚠️ 仅针对服务器弹出认证框场景。如果接口每次请求都需要 Authorization 请求头,不要用这个,直接设置 header 或者 RequestAdapter。
也可以直接传入 URLCredential 对象:
swift
let credential = URLCredential(...)
AF.request(...)
.authenticate(using: credential)
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
Request 的生命周期对象
URLRequest
requests 数组保存该请求产生过的全部 URLRequest(原始的 + 经过适配器修改后的)。
注意:不包含 URLSessionTask 内部实际执行的请求。访问实际 task 看
.tasks属性。
onURLRequestCreation 在每次生成 URLRequest 时回调,重试会多次触发;不能在闭包里修改 request 对象,修改请使用 RequestAdapter。
swift
AF.request(...)
.onURLRequestCreation { request in
print(request)
}
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
URLSessionTask
.tasks 数组保存该请求所有的 task,重试会新增 task。onURLSessionTaskCreation 在每次创建 task 回调;禁止在回调里操作 task 生命周期,只用来向外传递 task 对象。
swift
AF.request(...)
.onURLSessionTaskCreation { task in
print(task)
}
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
HTTPURLResponse 响应回调
onHTTPResponse 在收到服务端响应头时触发,可以决定继续执行还是取消请求。
swift
AF.request(...)
.onHTTPResponse { response, completionHandler in
print(response)
completionHandler(.allow) // .cancel 取消请求
}
必须调用 completionHandler,否则请求会挂起直到超时。
Swift5.7 + 支持 async 闭包版本,也可以用异步序列迭代所有响应:
swift
let responses = AF.request(...).httpResponses()
for await response in responses {
print(response)
}
URLSessionTaskMetrics 网络指标
每个 task 都会收集网络指标,response 对象上可以直接拿到。
watchOS <7 系统不支持收集 metrics。
swift
AF.request(...)
.responseDecodable(of: DecodableType.self) { response in
print(response.metrics)
}
DataRequest
封装 URLSessionDataTask,下载数据读到内存。**超大文件不要使用,改用 DownloadRequest。**额外属性:data(收到的二进制数据)、convertible(创建请求的原始对象)。
Validation 校验
默认不会校验响应,必须手动调用 .validate()。
swift
public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> Result<Void, Error>
默认校验:状态码 200‑299,Content‑Type 匹配 Accept。也可以自定义校验闭包。
swift
AF.request(...)
.validate { request, response, data in
// 自定义校验逻辑
return .success(())
}
DataStreamRequest
流式请求,URLSessionDataTask,持续接收数据流,不把全部数据存入内存。同样支持 validate,校验签名:
swift
public typealias Validation = (_ request: URLRequest?, _ response: HTTPURLResponse) -> Result<Void, Error>
UploadRequest
继承自 DataRequest,封装 URLSessionUploadTask,上传内存 Data、本地文件、InputStream。额外属性:fileManager、upload(封装上传源信息)。
DownloadRequest
封装 URLSessionDownloadTask,文件下载到磁盘。额外属性:
resumeData:取消时产出的数据,用于断点续传fileURL:下载完成后本地文件地址
Cancellation 取消
支持普通 cancel,也可以取消同时获取断点续传数据:
swift
AF.download(...)
.cancel { resumeData in
// resumeData 用于恢复下载
}
Validation
下载校验的闭包拿到的是文件 URL,而不是内存 Data。
swift
public typealias Validation = (_ request: URLRequest?, _ response: HTTPURLResponse, _ fileURL: URL?) -> Result<Void, Error>
RequestInterceptor 请求拦截器(适配 + 重试)
RequestInterceptor = RequestAdapter + RequestRetrier,可以全局 Session 设置,也可以单请求设置。典型场景:统一添加 token、token 过期自动刷新并重试请求。Alamofire 内置 RetryPolicy。
RequestAdapter 请求适配器
在网络真正发出之前修改 URLRequest,异步回调模式。
swift
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
示例:统一添加 Bearer Token
swift
let accessToken: String
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
var urlRequest = urlRequest
urlRequest.headers.add(.authorization(bearerToken: accessToken))
completion(.success(urlRequest))
}
新版本会使用带
RequestAdapterState的重载,可以拿到requestID,用于绑定自定义业务数据。
RequestRetrier 请求重试器
请求发生错误时决定是否重试。
swift
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
RetryResult 枚举:
swift
public enum RetryResult {
case retry // 立刻重试
case retryWithDelay(TimeInterval) // 延迟后重试
case doNotRetry // 不重试
case doNotRetryWithError(Error) // 不重试,返回指定错误
}
内置 RetryPolicy 实现指数退避重试逻辑,只对幂等请求重试。
组合多个 RequestInterceptor
使用 Interceptor 类型可以拼接多个适配器、重试器。适配器顺序执行,任意一个失败就终止;重试器按顺序执行。
swift
let adapter: RequestAdapter
let retrier: RequestRetrier
let interceptor: RequestInterceptor
let adapterAndRetrier = Interceptor(adapter: adapter, retrier: retrier)
let composite = Interceptor(interceptors: [adapterAndRetrier, interceptor])
AuthenticationInterceptor 认证拦截器
专门处理 OAuth 刷新 token 场景,处理并发请求排队等待刷新凭证的复杂逻辑。需要实现 Authenticator 协议,定义凭证模型 AuthenticationCredential。
示例 OAuth 凭证:
swift
struct OAuthCredential: AuthenticationCredential {
let accessToken: String
let refreshToken: String
let userID: String
let expiration: Date
// 距离过期5分钟就需要刷新
var requiresRefresh: Bool { Date(timeIntervalSinceNow: 60 * 5) > expiration }
}
实现 Authenticator:
swift
class OAuthAuthenticator: Authenticator {
func apply(_ credential: OAuthCredential, to urlRequest: inout URLRequest) {
urlRequest.headers.add(.authorization(bearerToken: credential.accessToken))
}
func refresh(_ credential: OAuthCredential,
for session: Session,
completion: @escaping (Result<OAuthCredential, Error>) -> Void) {
// 在这里调用刷新token接口,回调返回新凭证
}
func didRequest(_ urlRequest: URLRequest,
with response: HTTPURLResponse,
failDueToAuthenticationError error: Error) -> Bool {
// 判断本次失败是否属于鉴权失败,如 return response.statusCode == 401
return false
}
func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: OAuthCredential) -> Bool {
// 判断请求是否已经使用该凭证
return true
}
}
使用:
swift
let credential = OAuthCredential(
accessToken: "a0",
refreshToken: "r0",
userID: "u0",
expiration: Date(timeIntervalSinceNow: 60 * 60)
)
let authenticator = OAuthAuthenticator()
let interceptor = AuthenticationInterceptor(authenticator: authenticator, credential: credential)
let session = Session()
let url = URL(string: "https://api.example.com/example/user")!
var urlRequest = URLRequest(url: url)
session.request(urlRequest, interceptor: interceptor)
DeflateRequestCompressor 请求体压缩
请求体很大时(大 JSON,图片不要压缩),使用 deflate 压缩请求体。
swift
session.request(..., interceptor: .deflateCompressor)
遇到已经存在 Content‑Encoding 头,可以配置冲突策略:
swift
public enum DuplicateHeaderBehavior {
case error // 默认,抛出错误
case replace // 覆盖原有头
case skip // 跳过压缩
}
也可以全局配置给 Session,通过闭包判断多大的数据才开启压缩:
swift
let compressor = DeflateRequestCompressor { bodyData in
bodyData.count > 100 * 1024 // 大于100KB才压缩
}
let session = Session(..., interceptor: compressor)
Security 安全 TLS 证书校验
HTTPS 默认继承系统 URLSession 的证书校验,可以防止证书链非法,但无法防御中间人攻击。处理敏感数据建议开启证书锁定。
ServerTrustEvaluating 协议
自定义 TLS 评估逻辑,唯一方法:
swift
func evaluate(_ trust: SecTrust, forHost host: String) throws
内置评估器:
DefaultTrustEvaluator:系统默认校验,可控制是否校验主机名RevocationTrustEvaluator:校验证书吊销状态(会产生网络开销)PinnedCertificatesTrustEvaluator:证书锁定,支持自签名证书PublicKeysTrustEvaluator:公钥锁定CompositeTrustEvaluator:组合多个校验器,全部通过才算成功DisabledTrustEvaluator:调试用!生产绝对禁止,关闭全部校验
ServerTrustManager
维护域名与评估器映射。
swift
let evaluators: [String: ServerTrustEvaluating] = [
"cert.example.com": PinnedCertificatesTrustEvaluator(),
"keys.example.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
不在映射表里的域名请求直接报错。如需通配域名,继承
ServerTrustManager,重写serverTrustEvaluator(forHost:)。
App Transport Security ATS
使用自签名证书时,ATS 会覆盖 Alamofire 的校验逻辑,报 SSLHandshake (-9806)。需要修改 Info.plist。
本地开发使用自签名证书,添加:
xml
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
</dict>
自定义缓存与重定向
CachedResponseHandler 缓存处理器
控制 URLCache 缓存行为,仅对 DataTask(DataRequest / UploadRequest)生效。
swift
func dataTask(_ task: URLSessionDataTask,
willCacheResponse response: CachedURLResponse,
completion: @escaping (CachedURLResponse?) -> Void)
返回 nil = 不缓存;可以修改存储策略、Data、URLResponse。
内置实现 ResponseCacher:
swift
public enum Behavior {
case cache
case doNotCache
case modify((URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)
}
RedirectHandler 重定向处理器
swift
func task(_ task: URLSessionTask,
willBeRedirectedTo request: URLRequest,
for response: HTTPURLResponse,
completion: @escaping (URLRequest?) -> Void)