Alamofire源碼分析:網(wǎng)絡(luò)請(qǐng)求的封裝

Alamofire是Swift開發(fā)者最熟悉也是最常使用的網(wǎng)絡(luò)框架,源碼中應(yīng)用了Swift這門年輕語言的很多新特性,包括了很多泛型、枚舉、協(xié)議及擴(kuò)展的高級(jí)使用。

DataRequest

先來看一個(gè)簡單的Alamofire網(wǎng)絡(luò)請(qǐng)求:

request(requestUrl, method: .get , parameters: params).responseString{ (responseStr) in
      switch responseStr.result{
          case .success(let value):
                //拿到請(qǐng)求成功的數(shù)據(jù)做處理
          case .failure(let error):
               //失敗處理
        }
}

request(requestUrl, method: .get , parameters: params)方法返回的是一個(gè)DataRequest類型的對(duì)象,繼承自Request類,也就是Alamofire封裝的請(qǐng)求類,Request封裝了NSURLSessionTask以及Task的基本的代理方法。接著利用DataRequest的responseString方法將請(qǐng)求回來的二進(jìn)制數(shù)據(jù)序列化成字符串類型,而回調(diào)回來的responseStr字符串是通過responseStr.result中的枚舉值.success來獲得的,我們接下來就來簡單分析一下這么一個(gè)簡單的網(wǎng)絡(luò)封裝的工具方法在源碼中是怎么實(shí)現(xiàn)的。
注意:此處因?yàn)槭瞧胀ǖ膅et、post請(qǐng)求,所以返回的是DataRequest類,如果是下載或者上傳,則需要調(diào)用download或upload方法,返回的則是DownloadRequest或UploadRequest類)。

先看request方法的封裝實(shí)現(xiàn):

// MARK: - Data Request
    open func request(
        _ url: URLConvertible,
        method: HTTPMethod = .get,
        parameters: Parameters? = nil,
        encoding: ParameterEncoding = URLEncoding.default,
        headers: HTTPHeaders? = nil)
        -> DataRequest    //返回類型
    {
        var originalRequest: URLRequest?
        do {
            originalRequest = try URLRequest(url: url, method: method, headers: headers)
            let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
            return request(encodedURLRequest) //調(diào)用下方的方法
        } catch {
            return request(originalRequest, failedWith: error)
        }
    }
    
    open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
        var originalRequest: URLRequest?
        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)
        }
    }

下面來看看關(guān)鍵的網(wǎng)絡(luò)請(qǐng)求完成并且序列化數(shù)據(jù)的封裝方法,也就是上面代碼中的responseString是如何實(shí)現(xiàn)的,DataRequest的擴(kuò)展中提供了五類方法,用來將response序列化成不同類型的數(shù)據(jù),以滿足實(shí)際的需要,包括Default、Data、String、JSON對(duì)象以及Plist類型,而所有這些擴(kuò)展都被Alamofire放在了ResponseSerialization.swift這個(gè)文件里。

ResponseSerialization

我們以其中的responseString為例,先看源碼:

    /// - returns: The request.
    @discardableResult
    public func responseString(
        queue: DispatchQueue? = nil,
        encoding: String.Encoding? = nil,
        completionHandler: @escaping (DataResponse<String>) -> Void)
        -> Self
    {
        return response(
            queue: queue,
            responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding),
            completionHandler: completionHandler
        )
    }

 //response方法,第二個(gè)參數(shù)要遵循DataResponseSerializerProtocol
  public func response<T: DataResponseSerializerProtocol>(
        queue: DispatchQueue? = nil,
        responseSerializer: T,
        completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
        -> Self

返回一個(gè)response方法的實(shí)現(xiàn),completionHandler是最終網(wǎng)絡(luò)返回的閉包回調(diào),繼續(xù)傳進(jìn)去給response方法。先看第二個(gè)參數(shù) responseSerializer,要遵循DataResponseSerializerProtocol這個(gè)協(xié)議,此處傳入 DataRequest.stringResponseSerializer(encoding: encoding),進(jìn)入這個(gè)方法:

extension DataRequest {
    /// Creates a response serializer that returns a result string type initialized from the response data with
    /// - returns: A string response serializer.
    public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DataResponseSerializer<String> {
        return DataResponseSerializer { _, response, data, error in
            return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
        }
    }

就是 通過調(diào)用這個(gè)方法 返回一個(gè) DataResponseSerializer結(jié)構(gòu)體。

DataResponse

再來看看DataResponseSerializer,他遵循 DataResponseSerializerProtocol,在初始化init方法中:

public struct DataResponseSerializer<Value>: DataResponseSerializerProtocol {
    public typealias SerializedObject = Value

    /// A closure used by response handlers that takes a request, response, data and error and returns a result.
    public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>

    public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>) {
        self.serializeResponse = serializeResponse 
    }
}

給自己的serializeResponse閉包賦值(此處閉包的返回值 在不同的response序列化數(shù)據(jù)類型中 根據(jù)情況 使用,并返回不同的Result),而上面的這個(gè)方法:

  //返回值正是Result<String>
 return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
//實(shí)現(xiàn)方法
 public static func serializeResponseString(
        encoding: String.Encoding?,
        response: HTTPURLResponse?,
        data: Data?,
        error: Error?)
        -> Result<String>

該返回值Result<String>就是網(wǎng)絡(luò)請(qǐng)求成功后處理完的返回值,也是我們最終需要得到的結(jié)果,那上面這個(gè)DataResponseSerializer的閉包又是在哪返回的Result呢,再回到這個(gè)函數(shù):

  return response(
            queue: queue,
            responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding),
            completionHandler: completionHandler
        )

就是在response方法中處理的,來看具體實(shí)現(xiàn):

 public func response<T: DataResponseSerializerProtocol>(
        queue: DispatchQueue? = nil,
        responseSerializer: T,
        completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
        -> Self
    {
        //確保在網(wǎng)絡(luò)請(qǐng)求成功后再處理后續(xù)操作
        delegate.queue.addOperation {
            //調(diào)用responseSerializer的閉包,進(jìn)行處理獲得result結(jié)果
            let result = responseSerializer.serializeResponse(
                self.request,
                self.response,
                self.delegate.data,
                self.delegate.error
            )

          //初始化一個(gè)dataResponse,并回調(diào)出去
            var dataResponse = DataResponse<T.SerializedObject>(
                request: self.request,
                response: self.response,
                data: self.delegate.data,
                result: result,
                timeline: self.timeline
            )
            dataResponse.add(self.delegate.metrics)
            //回調(diào)出去
            (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
        }
        return self
    }

上面的delegate.queue.addOperation {} 保證了這個(gè)operation會(huì)在網(wǎng)絡(luò)請(qǐng)求成功后再執(zhí)行,然后通過調(diào)用let result = responseSerializer.serializeResponse(...),閉包屬性responseSerializer的返回值為Result,最后將dataResponse通過dcompletionHandler(dataResponse) 回調(diào)出去,而dataResponse

public struct DataResponse<Value> {
    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     //最終我們需要的序列化好的數(shù)據(jù)Result<Value>
        self.timeline = timeline
    }
}

而這個(gè)Result<Value>就是個(gè)枚舉,利用了泛型,例如網(wǎng)絡(luò)請(qǐng)求返回的不同類型的結(jié)果(Data、String),結(jié)構(gòu)如下:

public enum Result<Value> {
    case success(Value)
    case failure(Error)  
}

以上就是Alamofire中一個(gè)簡單網(wǎng)絡(luò)請(qǐng)求封裝的過程,通過源碼解析也一定程度上將Swift的網(wǎng)絡(luò)請(qǐng)求知識(shí)點(diǎn)再鞏固了一遍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容