Alamofire基于URLSession和Foundation URL的加载机制,为了更充分的了解和使用本框架,建议大家深刻的学习底层的网络实现.
建议阅读
- URL Loading System Programming Guide
- URLSession Class Reference
- URLCache Class Reference
- URLAuthenticationChallenge Class Reference
Session Manager
Alamofire.request就是我们最外层的方法方法,内部通过Alamofire.SessionManager和默认的URLSessionConfiguration实现
下面两者是等价的
1Alamofire.request("https://httpbin.org/get") 2 3 4let sessionManager = Alamofire.SessionManager.default 5sessionManager.request("https://httpbin.org/get")
通过URLSessionConfiguration我们可以自由的修改http请求头,超时时间等.应用程序可以未后台和临时会话创建管理器
Creating a Session Manager with Default Configuration
1let configuration = URLSessionConfiguration.default 2let sessionManager = Alamofire.SessionManager(configuration: configuration)
Creating a Session Manager with Background Configuration
1let configuration = URLSessionConfiguration.background(withIdentifier: "com.example.app.background") 2let sessionManager = Alamofire.SessionManager(configuration: configuration)
Creating a Session Manager with Ephemeral Configuration
1let configuration = URLSessionConfiguration.ephemeral 2let sessionManager = Alamofire.SessionManager(configuration: configuration)
自定义Session Configuration
1var defaultHeaders = Alamofire.SessionManager.defaultHTTPHeaders 2defaultHeaders["DNT"] = "1 (Do Not Track Enabled)" 3 4let configuration = URLSessionConfiguration.default 5configuration.httpAdditionalHeaders = defaultHeaders 6 7let sessionManager = Alamofire.SessionManager(configuration: configuration)
对于Authorization和Content-Type,不建议通过configuration来修改,Alamofire.request API提供的header来配置.
Session Delegate
默认情况下,Alamofire SessionManager会创建一个SessionDelegate对象来处理URLSession生成的所有各种回调,从中抽出最简单的实现方法. 对于特定需求的开发者,需要覆盖这些方法. ####重写闭包 第一种自定义SessionDelegate方法是重写闭包,每个闭包都对应着SessionDelegate的实现. 举例
1/// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`. 2open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? 3 4/// Overrides default behavior for URLSessionDelegate method `urlSessionDidFinishEvents(forBackgroundURLSession:)`. 5open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)? 6 7/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`. 8open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)? 9 10/// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)`. 11open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)? 12
以下是如何使用taskWillPerformHTTPRedirection避免重定向到任何apple.com的问题
1let sessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.default) 2let delegate: Alamofire.SessionDelegate = sessionManager.delegate 3 4delegate.taskWillPerformHTTPRedirection = { session, task, response, request in 5 var finalRequest = request 6 7 if 8 let originalRequest = task.originalRequest, 9 let urlString = originalRequest.url?.urlString, 10 urlString.contains("apple.com") 11 { 12 finalRequest = originalRequest 13 } 14 15 return finalRequest 16}
###子类覆盖父类方法 另一种方法就是通过子类来重写父类方法
1class LoggingSessionDelegate: SessionDelegate { 2 override func urlSession( 3 _ session: URLSession, 4 task: URLSessionTask, 5 willPerformHTTPRedirection response: HTTPURLResponse, 6 newRequest request: URLRequest, 7 completionHandler: @escaping (URLRequest?) -> Void) 8 { 9 print("URLSession will perform HTTP redirection to request: \(request)") 10 11 super.urlSession( 12 session, 13 task: task, 14 willPerformHTTPRedirection: response, 15 newRequest: request, 16 completionHandler: completionHandler 17 ) 18 } 19}
####Request request,download, upload stream这四个方法的返回值分别为DataRequest, DownloadRequest, UploadRequest StreamRequest,并且他们都继承自Request.每个子类都有专用的方法,如authenticate,validate,responseJSON和uploadProgress,都会返回调用者的实例,方便使用. Request可以被暂停,恢复,取消:
- suspend() 暂停
- resume() 恢复, 在SessionManager中有一个属性:startRequestsImmediately。他控制这请求是不是立刻发起,默认的值为true。
- cancel() 取消 同时该请求的每一个监听对象都会受到一个错误回调
####Routing Requests 随着应用程序的扩展,在构建网络堆栈时,采用通用模式很重要. 该设计的重要部分是如何路由您的请求. Alamofire URLConvertible和URLRequestConvertible协议以及路由器设计模式就是为之设计的. 路由的概念就是中转站的意思,在Alamofire中,String, URL, URLComponents实现了URLConvertible协议.
1let urlString = "https://httpbin.org/post" 2Alamofire.request(urlString, method: .post) 3 4let url = URL(string: urlString)! 5Alamofire.request(url, method: .post) 6 7let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)! 8Alamofire.request(urlComponents, method: .post)
采用URLConvertible协议的类型可用于构造URL,然后用于内部构造URL请求。 默认情况下,string,URL和URLComponent准守URLConvertible协议,允许将任何一个作为URL参数传递发送请求,上传和下载等方法:
1let urlString = "https://httpbin.org/post" 2Alamofire.request(urlString, method: .post) 3 4let url = URL(string: urlString)! 5Alamofire.request(url, method: .post) 6 7let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)! 8Alamofire.request(urlComponents, method: .post)
遵守URLConvertible协议,可以方便我们便捷的使用model与服务器生成映射关系.
1extension User: URLConvertible { 2 static let baseURLString = "https://example.com" 3 4 func asURL() throws -> URL { 5 let urlString = User.baseURLString + "/users/\(username)/" 6 return try urlString.asURL() 7 } 8} 9let user = User(username: "mattt") 10Alamofire.request(user) // https://example.com/users/mattt