) { finalRequest = originalRequest } return finalRequest }
子类化
另一个重写SessionDelegate
的实现的方法是把它子类化。通过子类化,我们可以完全自定义他的行为,或者为这个API创建一个代理并且仍然使用它的默认实现。通过创建代理,我们可以跟踪日志事件、发通知、提供前后实现。下面这个例子演示了如何子类化SessionDelegate
,并且有回调的时候打印信息:
class LoggingSessionDelegate: SessionDelegate { override func urlSession( _ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { print("URLSession will perform HTTP redirection to request: \(request)") super.urlSession( session, task: task, willPerformHTTPRedirection: response, newRequest: request, completionHandler: completionHandler ) } }
总的来说,无论是默认实现还是重写闭包,都应该提供必要的功能。子类化应该作为最后的选择。
请求
request
、download
、upload
和stream
方法的结果是DataRequest
、DownloadRequest
、UploadRequest
和StreamRequest
,并且所有请求都继承自Request
。所有的Request
并不是直接创建的,而是由session manager创建的。
每个子类都有特定的方法,例如authenticate
、validate
、responseJSON
和uploadProgress
,都返回一个实例,以便方法链接(也就是用点语法连续调用方法)。
请求可以被暂停、恢复和取消:
suspend()
:暂停底层的任务和调度队列
resume()
:恢复底层的任务和调度队列。如果manager的startRequestsImmediately
不是true
,那么必须调用resume()
来开始请求。
cancel()
:取消底层的任务,并产生一个error,error被传入任何已经注册的响应handlers。
传送请求
随着应用的不多增大,当我们建立网络栈的时候要使用通用的模式。在通用模式的设计中,一个很重要的部分就是如何传送请求。遵循Router
设计模式的URLConvertible
和URLRequestConvertible
协议可以帮助我们。
URLConvertible
遵循了URLConvertible
协议的类型可以被用来构建URL,然后用来创建URL请求。String
、URL
和URLComponent
默认是遵循URLConvertible
协议的。它们都可以作为url
参数传入request
、upload
和download
方法:
let urlString = "https://httpbin.org/post" Alamofire.request(urlString, method: .post) let url = URL(string: urlString)! Alamofire.request(url, method: .post) let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)! Alamofire.request(urlComponents, method: .post)
以一种有意义的方式和web应用程序交互的应用,都鼓励使用自定义的遵循URLConvertible
协议的类型将特定领域模型映射到服务器资源,因为这样比较方便。
类型安全传送
extension User: URLConvertible {
static let baseURLString = "https://example.com" func asURL() throws -> URL { let urlString = User.baseURLString + "/users/\(username)/" return try urlString.asURL() } }
let user = User(username: "mattt") Alamofire.request(user)
URLRequestConvertible
遵循URLRequestConvertible
协议的类型可以被用来构建URL请求。URLRequest
默认遵循了URLRequestConvertible
,允许被直接传入request
、upload
和download
(推荐用这种方法为单个请求自定义请求头)。
let url = URL(string: "https://httpbin.org/post")! var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" let parameters = ["foo": "bar"] do { urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: []) } catch {
以一种有意义的方式和web应用程序交互的应用,都鼓励使用自定义的遵循URLRequestConvertible
协议的类型来保证请求端点的一致性。这种方法可以用来抽象服务器端的不一致性,并提供类型安全传送,以及管理身份验证凭据和其他状态。
API参数抽象
enum Router: URLRequestConvertible {
case search(query: String, page: Int) static let baseURLString = "https://example.com" static let perPage = 50