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)再鞏固了一遍。