女兒惹她媽媽生氣了,我讓她去道歉催首。
“知錯(cuò)就改扶踊,快去找你媽,認(rèn)錯(cuò)郎任⊙砗模”我催促她。
小家伙猶豫了半天舶治,終于走進(jìn)了廚房分井,對(duì)她媽說(shuō)道:
“媽媽车猬,請(qǐng)問(wèn)你是周二珂嗎?”
妻子很疑惑:“不是啊尺锚≈槿颍”
“哦,對(duì)不起瘫辩,我認(rèn)錯(cuò)了伏嗜。”
哈哈哈伐厌,意淫下承绸。
最近看Alamifire
的源碼,不得不說(shuō)挣轨,好的源碼的確讓人獲益良多军熏。
但是看之前會(huì)很懵,如果不熟悉請(qǐng)求流程的話卷扮,很有可能堅(jiān)持不下去荡澎,所以我這里簡(jiǎn)要的把他的一個(gè)請(qǐng)求流程簡(jiǎn)單分析一下,希望能夠幫助到你画饥。
Alamofire.request(posturl, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headerFile).responseJSON { (response) in
switch response.result{
case .success(_):
///成功
if let value = response.result.value {
}
case .failure(_):
///失敗
print(response.result.error)
}
}
上面是一個(gè)請(qǐng)求json數(shù)據(jù)的一個(gè)標(biāo)準(zhǔn)用法衔瓮,看源碼可以發(fā)現(xiàn)Alamofire
提供了多個(gè)靜態(tài)的請(qǐng)求方法,而這些請(qǐng)求方法全部是通過(guò)SessionManager
管理的抖甘。
由于Alamofire
本質(zhì)上是對(duì)URLSession
的的一個(gè)封裝,所以我們需要了解下URLSession
的結(jié)構(gòu),如上圖一個(gè)session
管理者多個(gè)請(qǐng)求的task
和回調(diào)的delegate
衔彻。所以在SessionManager
中我們可以看到一個(gè)靜態(tài)的default
常量薇宠,以及類型為SessionDelegate
的一個(gè)delegate
變量。
接下來(lái)我們分析上面的請(qǐng)求過(guò)程
首先Alamofire
將請(qǐng)求分成了幾個(gè)大類
這里我就不一個(gè)個(gè)分析了艰额,今天主要分析請(qǐng)求的流程澄港。后面我會(huì)針對(duì)Alamofire
中幾個(gè)比較怪的寫法,我們不經(jīng)常用的寫法分析一下柄沮。
Alamofire.request
這個(gè)方法調(diào)用的是SessionManager
中的DataRequest的方法
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)
}
}
返回值還是DataRequest
回梧,這是為了后面可以鏈?zhǔn)秸{(diào)用.responseJSON
。
這里的請(qǐng)求步驟簡(jiǎn)單來(lái)說(shuō)是(這里還需要再研究下祖搓,回頭會(huì)專門寫個(gè)文章仔細(xì)分析下)
獲取
urlRequest
獲取
URLSessionTask
將
session
和URLSessionTask
封裝至Request
相應(yīng)的子類對(duì)象
這句delegate[task] = request
可能一開始看很難看懂狱意,但其實(shí)這是給SessionDelegate
定義了下標(biāo)方法,其實(shí)是通過(guò)SessionDelegate
的requests
屬性來(lái)存儲(chǔ)task
對(duì)應(yīng)的request
的
///通過(guò)自身的requests屬性來(lái)存儲(chǔ)[task: request],用lock來(lái)確保線程安全拯欧。
/// Access the task delegate for the specified task in a thread-safe manner.
open subscript(task: URLSessionTask) -> Request? {
get {
lock.lock() ; defer { lock.unlock() }
return requests[task.taskIdentifier]
}
set {
lock.lock() ; defer { lock.unlock() }
requests[task.taskIdentifier] = newValue
}
}
后面的.responseJSON
這里是指定對(duì)返回的數(shù)據(jù)進(jìn)行json
解析
public func responseJSON(
queue: DispatchQueue? = nil,
options: JSONSerialization.ReadingOptions = .allowFragments,
completionHandler: @escaping (DataResponse<Any>) -> Void)
-> Self
{
return response(
queue: queue,
responseSerializer: DataRequest.jsonResponseSerializer(options: options),
completionHandler: completionHandler
)
}
相信大家看到這里頭肯定大了一圈详囤,講真的,我看到這里頭大的一度想放棄镐作。
[圖片上傳失敗...(image-5840f4-1535621411864)]
但是頭大了之后發(fā)現(xiàn)能思考更多東西了藏姐,這里我來(lái)一個(gè)一個(gè)分解開來(lái)
public func response<T: DataResponseSerializerProtocol>(
queue: DispatchQueue? = nil,
responseSerializer: T,
completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
-> Self
{
delegate.queue.addOperation {
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
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)
(queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
}
return self
}
首先return
調(diào)用了DataRequest
的一個(gè)序列化結(jié)果的一個(gè)根方法隆箩,為什么說(shuō)根方法呢,大家可以看下responseString
這個(gè)方法中也是return
這個(gè)方法,通過(guò)<T: DataResponseSerializerProtocol>
這個(gè)泛型參數(shù)就可以實(shí)現(xiàn)請(qǐng)求結(jié)果序列化成任意類型羔杨,只要遵守了DataResponseSerializerProtocol
這個(gè)協(xié)議捌臊,并實(shí)現(xiàn)即可。
而這個(gè)協(xié)議中的
serializeResponse
這個(gè)閉包則是起到傳輸數(shù)據(jù)然后返回序列化的結(jié)果的一個(gè)作用问畅。
下面我闡述下代碼調(diào)用的順序娃属。
調(diào)用
.responseJSON
————> 傳入responseSerializer
這個(gè)參數(shù)(系列化的過(guò)程)來(lái)調(diào)用DataRequest的序列化根方法
-
DataRequest.jsonResponseSerializer(options: options)
這里就是序列化的方法,我盡量在注釋中描述清楚public static func jsonResponseSerializer( options: JSONSerialization.ReadingOptions = .allowFragments) -> DataResponseSerializer<Any> { ///返回的是遵守DataResponseSerializerProtocol協(xié)議的一個(gè)結(jié)構(gòu)體對(duì)象 ///這是一個(gè)初始化方法护姆,初始化的對(duì)象存儲(chǔ)了一個(gè)閉包矾端。 return DataResponseSerializer { _, response, data, error in return Request.serializeResponseJSON(options: options, response: response, data: data, error: error) } ///所以上面可以等價(jià)為 let jsonResponseSerializer = DataResponseSerializer.init { (request, response, data, error) -> Result<Any> in ///這里就是根據(jù)閉包傳過(guò)來(lái)的response, data, error來(lái)對(duì)結(jié)果進(jìn)行序列化。 return Request.serializeResponseJSON(options: options, response: response, data: data, error: error) } return jsonResponseSerializer }
-
接下來(lái)看
DataRequest的序列化根方法
的實(shí)現(xiàn)卵皂,我們可以看到let result = responseSerializer.serializeResponse( self.request, self.response, self.delegate.data, self.delegate.error )
這里的responseSerializer.serializeResponse
傳遞參數(shù)然后調(diào)用第二步中序列化操作秩铆,最后得到return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
返回值
-
最后將得到的序列化結(jié)果
result
以及其他數(shù)據(jù)封裝在dataResponse
中通過(guò)completionHandler
在指定線程中回調(diào)。var dataResponse = DataResponse<T.SerializedObject>( request: self.request, response: self.response, data: self.delegate.data, result: result, timeline: self.timeline )
這里對(duì)協(xié)議的關(guān)聯(lián)類型以及屬性的應(yīng)用值得我們認(rèn)真拜讀一下
最終
最近很迷茫灯变,來(lái)個(gè)人私信我陪我聊聊騷啊殴玛。
聯(lián)系方式
- GitHub: 大貓傳說(shuō)中的gitHud地址
- 郵箱: 1030472953@qq.com