URLSession至關於管理一個請求的類,它涉及到URL/URLRequest/URLSessionConfiguration/URLSessionTask。經過這幾個類的綜合使用,咱們就能夠很方便的建立請求javascript
let userTel = "13231852031"
let userPassword = "123456"
let defaultConfiguration = URLSessionConfiguration.default
let sessionWithoutADelegate = URLSession(configuration: defaultConfiguration)
if let url = URL(string: "http://127.0.0.1:8080/v1/login?usertel=\(userTel)&userpassword=\(userPassword)") {
(sessionWithoutADelegate.dataTask(with: url) { (data, response, error) in
if let error = error {
print("Error: \(error)")
} else if let response = response,
let data = data,
let string = String(data: data, encoding: .utf8) {
print("Response: \(response)")
print("DATA:\n\(string)\nEND DATA\n")
}
}).resume()
}複製代碼
let defaultConfiguration = URLSessionConfiguration.default
let sessionWithoutADelegate = URLSession(configuration: defaultConfiguration)
let paramer: [String: String] = ["userTel":"13231852031","userPassword":"123456"]
if let url = URL(string: "http://127.0.0.1:8080/v1/register") {
var request = URLRequest.init(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: paramer, options: JSONSerialization.WritingOptions.prettyPrinted)
sessionWithoutADelegate.dataTask(with: request, completionHandler: { (data, response, error) in
if let error = error {
print("Error:\(error)")
}else if let response = response,
let data = data,
let string = String(data: data,encoding: .utf8){
print("Response: \(response)\n")
print("DATA:\(string)\n")
}
}).resume()
}複製代碼
Alamofire.request("https://httpbin.org/get")複製代碼
首先,文檔中給出上面的一個例子,咱們能夠看到很簡單就發送了一個請求。接下來咱們能夠看一下Alamofire是如何實現的request,經過跳轉咱們能夠看到該方法是實如今Alamofire.swift文件中:html
@discardableResult
public func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
{
return SessionManager.default.request(
url,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers
)
}複製代碼
首先該方法經過URLConvertible
協議來判斷URL的有效性(如未無效URL會拋出Error),而後方法默認爲GET,parameters參數默認爲空,參數編碼默認爲URLEncoding.default,header默認爲空。在該方法中又調用了SessionManager
,接下來咱們再跳轉到SessionManager,在SessionManager中的request方法實現以下(因爲方法較長下面代碼只貼關鍵部分):java
do {
originalRequest = try URLRequest(url: url, method: method, headers: headers)
let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
return request(encodedURLRequest)
} catch {
return request(originalRequest, failedWith: error)
}複製代碼
在上述實現中咱們能夠看到,若是各項參數都沒問題的話,它會進入do
代碼塊中request方法.
do中的request方法實現以下:ios
do {
originalRequest = try urlRequest.asURLRequest()
let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
delegate[task] = request
if startRequestsImmediately { request.resume() }
return request
} catch {
return request(originalRequest, failedWith: error)
}複製代碼
仍是在判斷各項參數都正確後調用resume方法,在該方法中它會調用URLSessionTask的resume()
來啓動該次請求。由此咱們能夠看出雖然咱們只是調用這麼簡單的一句話,可是裏面仍是由不少條件和邏輯的,只不過這一切Alamofire替咱們作了。git
上述的代碼邏輯若是把全部的錯誤檢查和判斷邏輯簡化掉,相似於下方的代碼:github
let url = URL.init(string: "http://example.com")
let session = URLSession.shared
session.dataTask(with: url!).resume()複製代碼
Alamofire默認有五種response handler:編程
Tip:上述五種response handler都沒對返回數據的HTTPURLResponse作驗證,Alamofire是經過Response Validation作驗證的。json
Alamofire.request("https://httpbin.org/get").response { response in
}複製代碼
ResponseSerialization.swift中的方法實現:swift
delegate.queue.addOperation {
(queue ?? DispatchQueue.main).async {
var dataResponse = DefaultDataResponse(
request: self.request,
response: self.response,
data: self.delegate.data,
error: self.delegate.error,
timeline: self.timeline
)
dataResponse.add(self.delegate.metrics)
completionHandler(dataResponse)
}複製代碼
DefaultDataResponse
爲結構體,包含request、response、data等數據。api
Alamofire不建議使用這種response serializers。
Alamofire.request("https://httpbin.org/get").responseData { response in
}複製代碼
若是請求數據和解析數據的過程當中沒有發生錯誤,它將返回一個Data類型的數據,Response的Result將會是.success。在該方法的實現源碼中調用了responseSerializer: DataRequest.dataResponseSerializer()
序列化數據的方法
Alamofire.request("https://httpbin.org/get").responseString { response in
}複製代碼
該Handler經過responseStringSerializer
將返回的Data數據轉爲String類型,若是沒有錯誤發生,而且服務器數據成功轉爲String,response的Result將爲.success而且值爲String。
Alamofire.request("https://httpbin.org/get").responseJSON { response in
}複製代碼
該handler經過調用jsonResponseSerializer
方法來轉換數據類型,若沒發生錯誤request同上
Tip:使用鏈式response包含幾個handler,就會請求幾回數據數據
Response handlers默認在主線程隊列中執行,可是咱們能夠提供一個自定義線程隊列
默認狀況下,Alamofire認爲任何已完成的請求都是成功的,不管相應內容是什麼。你能夠在handler以前調用validate
來判斷status code
Alamofire支持HTTP的GET、POST、DELETE等方法,並將這些方法聲明爲HTTPMethod
的enum
Alamofire提供三種參數編碼方式URL,JSON和PropertyList
SessionManager.swift是Alamofire中比較重要的一個文件,它是URLSession的管理類,文件中是對request方法的具體實現。正是有該類才使得Alamofire發起一個請求很是簡單。
經過源碼咱們能夠看見若是不設置URLSessionConfiguration,默認爲URLSessionConfiguration.default
你也能夠將URLSessionConfiguration修改成Background Configuration和Ephemeral Configuration
Requests能夠被暫停(suspended)復位(resumed)和取消(cancelled)
隨着APP的不斷更新和迭代,構建網絡層的通用模式很重要。如何路由你的request也是很是重要的一個部分。URLConvertible
和URLRequestConvertible
協議能夠幫助你構建路由的通用部分
String, URL, 和URLComponents是默認遵照URLConvertible
協議的,因此你能夠在request中寫String, URL, 和URLComponents,它會自動檢測request中的參數,根據參數類型找到相應的方法轉爲URL。你也能夠根據文檔中的例子來構造本身的路由
URLRequest默認遵照該協議,該協議用來構造URLRequest
@discardableResult
:此關鍵字表示修飾的方法沒必要接受返回值Swift 3.0 中方法的返回值必須有接收不然會報警告,固然其實主要目的是爲了不開發人員忘記接收返回值的狀況,可是有些狀況下確實不須要使用返回值可使用"_"接收來忽略返回值。固然你也能夠增長@discardableResult聲明,告訴編譯器此方法能夠不用接收返回值open
:open 一個元素在其餘module中仍是能夠被overridestatic
:在方法的func關鍵字以前加上關鍵字static或者class均可以用於指定類方法.不一樣的是用class關鍵字指定的類方法能夠被子類重寫@escaping
至此,Alamofire的源碼已經瞭解完,我在這裏只是簡單的瞭解一下Alamofire是如何實現最基本的GET和POST請求如何實現。能夠看到,它經過幾層包裝實現了參數的校驗、request支持String、URL和URLComponents三種方式。因爲水平有限,對於它下載上傳等功能的源碼並無十分理解,因此在這並無寫,你們有能力的能夠自行查看源碼。在Alamofire中比較重要的幾個文件Alamofire.swift/Response.swift/SessionManager.swift/Request.swift。