在前面幾篇內容中已經大體介紹了Alamofire
的Request
請求,當一個Request
完成的時候,下一步 確定要處理服務器返回的響應數據。本篇內容就記錄一下學習處理響應數據Response
的內容。json
先來一個簡單的代碼例子🌰看一下下:swift
SessionManager.default.request("https://www.douban.com/j/app/radio/channels")
.response { (response) in
debugPrint(response)
}
複製代碼
咱們都知道Alamofire
可使用鏈式訪問,那就搞點事作😏,把request
和response
換一下,先進行response
,再進行request
,換了以後會發現根本不可能😞。這就說明了request
必需要在response
以前訪問,這也提現了request
的重要性安全
好了,在皮一下以後,回到代碼來看,看一下這個response
是怎麼實現的:bash
response
的任務是加入到了
delegate.queue.addOperation
,這個
delegate.queue
就是在發起
request
以後,建立的
TaskDelegate
會默認初始化一個掛起隊列。(具體請看上篇
時間軸部分)而後在
request
請求
Complete
以後再取消隊列的掛起,保證了隊列中的任務所有是在
request
請求完成以後進行的,
這一樣也更加說明了request
必需要在response
以前訪問。
而後任務被交給了主隊列(畢竟開發者有可能利用response
進行UI
的更新),能夠看到在這裏並無對response
進行序列化,而是初始化了一個DefaultDataResponse
類的對象,服務器
DefaultDataResponse
是用來保存self.request
、self.response
、self.delegate.data
、self.delegate.error
、self.timeline
、self.delegate.metrics
屬性,並把初始化的DefaultDataResponse
對象返回給completionHandler
閉包。(有點相似於Model
,通常來講,在swift
中,若是隻是爲了保存數據,那麼應該把這個類設計成struct
。struct
是值傳遞,所以對數據的操做更安全。除了定義須要保存的數據屬性後,必須設計一個符合要求的構造函數。), 閉包
小總結:app
request
(該響應來源於那個請求)response
(服務器返回的響應)data
(響應數據)error
(在請求中可能發生的錯誤)timeline
(請求的時間軸封裝)_metrics
(包含了請求和響應的統計信息)這些數據都不是由response
來建立的,它只有使用權。也就是說response
只是一個數據的保存信息者,把各類數據化零爲整返回給用戶。函數
在Alamofire
中把Request
分爲了4類:post
DataRequest
DownloadRequest
UploadRequest
StreamRequest
由於有四種不一樣的Request
類型,StreamRequest
咱們先a按下不表,對於UploadRequest
來講,服務器響應的數據比較簡單,就響應一個結果就行,所以不須要對它的Response
專門進行封裝。所以,Alamofire
設計了2種與之相對應的Response
類型學習
DefaultDataResponse
/ DataResponse
DefaultDownloadResponse
/ DataResponse
細心的你必定會發如今DataRequest
的擴展的中會有兩個response
方法,(第一個response
方法在上面👆已經給出,下面👇貼出第二個response
)
response
方法內部,能夠看到會先進行一個
serializeResponse
的操做獲得一個結果
result
,而後在初始化一個
DataResponse
對象用來保存
self.request
、
self.response
、
self.delegate.data
、
result
、
self.timeline
,
self.delegate.metrics
這些數據,並把
DataResponse
對象返回給
completionHandler
閉包。
若是你對比這兩個response
方法,聰明而優秀的你就會發現這兩個方法的不一樣之處:
在request
請求完成以後,獲取到的是沒有通過序列化後的數據,若是調用了沒有序列化的response
方法,DefaultDataResponse/DefaultDownloadResponse
。若是調用了序列化的response
方法,須要傳入一個泛型的responseSerializer
參數,返回的就是DataResponse
。
response
方法遵循了
DataResponseSerializerProtocol
協議,下面經過源碼看一下這個協議的具體實現:
在這個協議內部有一個序列化函數
serializeResponse
,並返回一個類型爲
SerializedObject的Result
,那麼也就是說序列者只須要遵循這個協議就能夠了:因此就有了這樣一個用序列化函數
serializeResponse
做爲參數來初始化,而且保存序列化函數的
DataResponseSerializer
類;
從這裏咱們知道調用序列化函數serializeResponse
會返回一個Result
,並且在前面也已經說過,在序列化的response
方法內部,看到會先進行一個serializeResponse
的操做獲得一個結果result
,
Result
的結果只有兩種:成功和失敗。成功就把序列化完成的數據返回,失敗就返回一個
error
信息。
若是我想把請求的結果序列化成json
類型或者String
類型的,怎麼辦,難道調用序列化的response
方法拿到返回的內容以後,用戶此時再去本身作序列化成json
類型或者String
類型的內容?怎麼可能,霸氣側漏的Alamofire
早就已經都作好了。
SessionManager.default.request("https://www.douban.com/j/app/radio/channels")
.response { (response) in
}
SessionManager.default.request("https://www.douban.com/j/app/radio/channels")
.responseData { (responsedata) in
}
SessionManager.default.request("https://www.douban.com/j/app/radio/channels")
.responseString { (responseString) in
}
SessionManager.default.request("https://www.douban.com/j/app/radio/channels")
.responseJSON { (responsejson) in
}
SessionManager.default.request("https://www.douban.com/j/app/radio/channels")
.responsePropertyList{ (responselist) in
}
複製代碼
responseData
在其方法內部是直接調用了
response
的序列化方法,那麼也就是和
response
同樣,把數據序列化爲
Data
類型也就是
Result
。
這裏傳入的序列化器responseSerializer
的參數是DataRequest.dataResponseSerializer()
,下面來看一下dataResponseSerializer()
:
DataResponseSerializer
類型的序列化器,
DataResponseSerializer
這個類前面已經介紹過,它是用來保存序列化函數的,關鍵在於
Request.serializeResponseData
,
這裏會根據序列化的成功和失敗來返回數據,返回
.success(validData)
或者
.failure(error信息)
。
註解:emptyDataStatusCodes
HTTP response code
是
204
或者
205
,就表示
Data
爲
nil
.
關於responseString
、responseJSON
、responsePropertyList
在內部是如何實現的,在這裏就不一一列出來了,基本和responseData
的套路同樣,有興趣的大佬能夠藉助源碼去看一下。
實際上這個response並非咱們常見的那種response,它只是一個保存內容的載體,它把request
、response
、data
、error
、timeline
、_metrics
這些數據所有收集整合起來,放到本身身上,而後一塊兒返回給用戶,這樣用戶在外面能夠拿到他想要的任何數據,這是多麼牛X的處理方式。