引言
當我們完成Request
的時候,肯定要處理服務器返回的響應數據,在之前的文章中,我們講過Alamofire
中,把Request
分為了4類Request
:
DataRequest
DownloadRequest
UploadRequest
StreamRequest
所以,有4種不同的Request
類型,那么就有與之對應的不同的Response
。
StreamRequest
因為之前沒有提過,在這里,我們也不先提,然后UploadRequest
,服務器的數據響應其實很簡單,只需響應一個結果,因此,是不需要對它的Response
再次進行獨立的封裝了。
所以,我們這里講到2種與之相對應的Response
類型,它們是:
DefaultDataResponse/DataResponse
DefaultDownloadResponse/DownloadResponse
看下代碼:
/// Adds a handler to be called once the request has finished.
///
/// - parameter queue: The queue on which the completion handler is dispatched.
/// - parameter completionHandler: The code to be executed once the request has finished.
///
/// - returns: The request.
@discardableResult
public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
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)
}
}
return self
}
當我使用這個函數方法獲取響應數據,這里獲取到的數據是沒有經過序列化處理的數據,所以,我們這樣區分,如果是返回的帶有Default
開頭的響應者,如DefaultDataResponse
、DefaultDownloadResponse
,這些都是沒有進過序列化處理的response
方法。相反的,如果使用了序列化處理過的response
方法,返回的,應該就是DataResponse
或者是DownloadResponse
。
其實,這樣的設計,更好的理解一些,我們在實際項目種,也不會把所有的參數都放在一個模型中。
接下來,我們來慢慢講講這些響應方法。
DefaultDataResponse
屬性
DefaultDataResponse
用于響應data
或者upload
請求的未經過序列化處理的的數據。看看代碼:
/// The URL request sent to the server.
public let request: URLRequest?
/// The server's response to the URL request.
public let response: HTTPURLResponse?
/// The data returned by the server.
public let data: Data?
/// The error encountered while executing or validating the request.
public let error: Error?
/// The timeline of the complete lifecycle of the request.
public let timeline: Timeline
var _metrics: AnyObject?
request: URLRequest?
:表示該響應來源于那個請求response: HTTPURLResponse?
:服務器返回的響應data: Data?
:響應數據error: Error?
:在請求中可能發生的錯誤timeline: Timeline
:請求的時間線封裝_metrics: AnyObject?
:包含了請求和響應的統計信息
為了保存數據,Alamofire
把這個類設計成了struct
,對數據操作更安全。
構造函數
當然,Alamofire
還提供了一個構造函數:
/// Creates a `DefaultDataResponse` instance from the specified parameters.
///
/// - Parameters:
/// - request: The URL request sent to the server.
/// - response: The server's response to the URL request.
/// - data: The data returned by the server.
/// - error: The error encountered while executing or validating the request.
/// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default.
/// - metrics: The task metrics containing the request / response statistics. `nil` by default.
public init(
request: URLRequest?,
response: HTTPURLResponse?,
data: Data?,
error: Error?,
timeline: Timeline = Timeline(),
metrics: AnyObject? = nil)
{
self.request = request
self.response = response
self.data = data
self.error = error
self.timeline = timeline
}
DataResponse
屬性
一樣的,我們先來看看它有些什么屬性:
/// Used to store all data associated with a serialized response of a data or upload request.
public struct DataResponse<Value> {
/// The URL request sent to the server.
public let request: URLRequest?
/// The server's response to the URL request.
public let response: HTTPURLResponse?
/// The data returned by the server.
public let data: Data?
/// The result of response serialization.
public let result: Result<Value>
/// The timeline of the complete lifecycle of the request.
public let timeline: Timeline
/// Returns the associated value of the result if it is a success, `nil` otherwise.
public var value: Value? { return result.value }
/// Returns the associated error value if the result if it is a failure, `nil` otherwise.
public var error: Error? { return result.error }
var _metrics: AnyObject?
對比我們上面的DefaultDataResponse
,可以看到,DataResponse
多了一個result
屬性,該屬性的存在,即是存儲了序列化后的數據。result
屬性的類型是Result
,關于Result
的內容,我們后面會單獨講到,這里不在詳述。
構造函數
同樣的,Alamofire
也提供了一個構造函數:
/// Creates a `DataResponse` instance with the specified parameters derived from response serialization.
///
/// - parameter request: The URL request sent to the server.
/// - parameter response: The server's response to the URL request.
/// - parameter data: The data returned by the server.
/// - parameter result: The result of response serialization.
/// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
///
/// - returns: The new `DataResponse` instance.
public init(
request: URLRequest?,
response: HTTPURLResponse?,
data: Data?,
result: Result<Value>,
timeline: Timeline = Timeline())
{
self.request = request
self.response = response
self.data = data
self.result = result
self.timeline = timeline
}
擴展
不僅如此,我們往下可以看到,DataResponse
還有擴展屬性:
extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
/// The textual representation used when written to an output stream, which includes whether the result was a
/// success or failure.
public var description: String {
return result.debugDescription
}
/// The debug textual representation used when written to an output stream, which includes the URL request, the URL
/// response, the server data, the response serialization result and the timeline.
public var debugDescription: String {
var output: [String] = []
output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil")
output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
output.append("[Data]: \(data?.count ?? 0) bytes")
output.append("[Result]: \(result.debugDescription)")
output.append("[Timeline]: \(timeline.debugDescription)")
return output.joined(separator: "\n")
}
}
DataResponse
實現了CustomStringConvertible
和CustomDebugStringConvertible
協議,因此可以自定義DataResponse
的打印信息。
我們也可以給我們模型實現這兩個協議,在代碼調試的時候,打印出詳細的信息,比打斷點來查看效率更高。
DefaultDownloadResponse
屬性
我們來看下它的屬性定義:
/// The URL request sent to the server.
public let request: URLRequest?
/// The server's response to the URL request.
public let response: HTTPURLResponse?
/// The temporary destination URL of the data returned from the server.
public let temporaryURL: URL?
/// The final destination URL of the data returned from the server if it was moved.
public let destinationURL: URL?
/// The resume data generated if the request was cancelled.
public let resumeData: Data?
/// The error encountered while executing or validating the request.
public let error: Error?
/// The timeline of the complete lifecycle of the request.
public let timeline: Timeline
var _metrics: AnyObject?
有很多屬性和前面的都有重復,我們就不說了,來看看不同的。
temporaryURL: URL?
:下載成功后,數據會被保存在這個臨時URL中destinationURL: URL?
:目標URL,如果設置了該屬性,那么文件會復制到該URL中resumeData: Data?
:表示可恢復的數據,對于下載任務,如果因為某種原因下載中斷了,或失敗了,可以使用該數據恢復之前的下載
構造函數
同樣,也有相應的構造方法:
/// Creates a `DefaultDownloadResponse` instance from the specified parameters.
///
/// - Parameters:
/// - request: The URL request sent to the server.
/// - response: The server's response to the URL request.
/// - temporaryURL: The temporary destination URL of the data returned from the server.
/// - destinationURL: The final destination URL of the data returned from the server if it was moved.
/// - resumeData: The resume data generated if the request was cancelled.
/// - error: The error encountered while executing or validating the request.
/// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default.
/// - metrics: The task metrics containing the request / response statistics. `nil` by default.
public init(
request: URLRequest?,
response: HTTPURLResponse?,
temporaryURL: URL?,
destinationURL: URL?,
resumeData: Data?,
error: Error?,
timeline: Timeline = Timeline(),
metrics: AnyObject? = nil)
{
self.request = request
self.response = response
self.temporaryURL = temporaryURL
self.destinationURL = destinationURL
self.resumeData = resumeData
self.error = error
self.timeline = timeline
}
DownloadResponse
其實,也沒有什么可以說了,類比上面的內容,比較學習一下,都差不多的意思,這里就不在詳細說了。
常規打廣告系列:
簡書:Alamofire(六)-- 響應封裝Response
掘金:Alamofire(六)-- 響應封裝Response
小專欄:Alamofire(六)-- 響應封裝Response