Alamofire(六)-- 響應封裝Response

引言

當我們完成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開頭的響應者,如DefaultDataResponseDefaultDownloadResponse,這些都是沒有進過序列化處理的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實現了CustomStringConvertibleCustomDebugStringConvertible協議,因此可以自定義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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容