解讀Alamofire

在開(kāi)始介紹之前先明確一點(diǎn),本篇寫(xiě)的不是關(guān)于Alamofire是怎么使用的,而是我仔細(xì)看了Alamofire框架代碼后的一點(diǎn)感受與大家分享。寫(xiě)的不好也請(qǐng)大家見(jiàn)諒。如果是想要學(xué)習(xí)怎么使用的話還是建議直接閱讀github上面的文檔Alamofire documentation從基本到高級(jí)都講解的很詳細(xì)。

Alamofire

對(duì)于使用oc的同學(xué)來(lái)說(shuō)一定十分熟悉AFNetworking這個(gè)框架,因?yàn)楝F(xiàn)在我們的app只要是有關(guān)于網(wǎng)絡(luò)訪問(wèn)的部分大部分都會(huì)通過(guò)這個(gè)框架來(lái)進(jìn)行網(wǎng)絡(luò)的訪問(wèn)。而本篇要說(shuō)的Alamofire就是swift版本的AFNetworking拉。所以Alamofire也是進(jìn)行網(wǎng)絡(luò)訪問(wèn)的框架。

整體架構(gòu)

從github上下載Alamofire用Xcode打開(kāi)可以看到如下的結(jié)構(gòu)目錄:

Alamofire目錄

其中主要分為3部分:

  1. Alamofire.swift文件
  2. Core核心部分
  3. Features部分

我主要是分析Core部分的代碼,而Features部分的代碼我只會(huì)分析一部分,因?yàn)镕eatures部分的代碼是大同小異的只要理解了其中一部分的代碼是怎么寫(xiě)的其他的只要在稍稍閱讀下就可以了,當(dāng)然每個(gè)部分的代碼都有其精彩之處。希望大家有時(shí)間也可以自己再去閱讀下大家多交流交流??。

Alamofire.swift分析

在Alamofire.swift文件主要有兩個(gè)功能:1. 提供了整個(gè)框架的入口。2. 向整個(gè)框架提供了方便的工具方法。

整個(gè)Alamofire.swift文件在內(nèi)容上面也主要分成了兩部分:
第一部分:


接口和convenience

在這一部分中主要是定義了兩個(gè)Convertible協(xié)議和一個(gè)Convenience方法
兩個(gè)個(gè)Convertible協(xié)議代碼如下:

URLStringConvertible

這個(gè)協(xié)議是規(guī)定了其他類轉(zhuǎn)化為URLString的方法從而可以使用這個(gè)來(lái)構(gòu)造URLRequest。這么做得目的是將個(gè)各類的轉(zhuǎn)化方法和方式分散到個(gè)各類中各自實(shí)現(xiàn),就可以避免出現(xiàn)一大坨的轉(zhuǎn)化方法,實(shí)現(xiàn)代碼的美觀。同理在接下來(lái)的URLRequestConvertible也是這個(gè)道理

URLRequestConvertible

接下來(lái)就是工具方法了

URLRequest

這個(gè)方法是用來(lái)構(gòu)造NSURLRequest的簡(jiǎn)便方法,其中有一個(gè)參數(shù)就是URLStringConvitible類型的。所以如果我們自己的某個(gè)類也實(shí)現(xiàn)了URLStringConvertible協(xié)議也是可以通過(guò)這個(gè)方法構(gòu)造NSURLRequest的。在有一個(gè)Method類型這個(gè)類型是


Method

定義在ParameterEncoding.swift文件中。

接下來(lái)就是提供了整個(gè)框架的入口方法,這里就先不做介紹等下面的Core部分懂了那么這部分就很自然的懂了

Core部分

在正式介紹整個(gè)核心部分之前,必須要有NSURLSession的基礎(chǔ)知識(shí),因?yàn)檎麄€(gè)Alamofire框架其實(shí)是對(duì)NSURLSession進(jìn)行封裝的。如果對(duì)這一方面的只是缺乏還是建議先去補(bǔ)充一下,不然的話你會(huì)不知道接下來(lái)為什么要這么做。

在3個(gè)文件中總共是有Manager類、Request類和ParameterEncoding枚舉類型。

Manager類:封裝了NSURLSession以及相對(duì)應(yīng)的代理方法
Request類: 封裝了NSURLSessionTask以及Task的基本的代理方法
ParameterEncodeing:負(fù)責(zé)對(duì)HTTP請(qǐng)求的參數(shù)進(jìn)行編碼

框架總體流程是:


發(fā)送流程

這個(gè)是發(fā)送的流程,我們調(diào)用Alamofire.swift里的方法,而Alamofire里的方法其實(shí)是創(chuàng)建一個(gè)Manager調(diào)用Manager里的方法將得到的NSURLSessionTask封裝成Request實(shí)例,發(fā)送并且返回Request實(shí)例。

得到回復(fù)時(shí)候的回調(diào)

在消息發(fā)送成功了,服務(wù)器處理好以后,需要將處理好的回復(fù)發(fā)送回來(lái)那么在發(fā)送回來(lái)的時(shí)候首先是調(diào)用了Manager的代理方法,然后在Manager中調(diào)用Request類的方法,最后才是掉用response方法和progress方法等。

那么在我們進(jìn)行網(wǎng)絡(luò)訪問(wèn)的時(shí)候一定不是只是發(fā)一個(gè)Request這么簡(jiǎn)單,而是有很多個(gè)Request那么在有回調(diào)的時(shí)候Manager是怎么知道是哪個(gè)Request的回調(diào)呢?那么接下來(lái)這就要求我們知道Manager里面是如果工作的。

Manager

先上Manager的圖


Manager

屬性:

session: NSURLSession類型發(fā)送請(qǐng)求并且得到NSURLSessionTask
delegate: session的代理
queue:實(shí)現(xiàn)session線程安全的隊(duì)列
startRequestsImmediately:是否立刻發(fā)送請(qǐng)求
backgroundCompletionHandler:后臺(tái)運(yùn)行完成后的回調(diào)的closure

現(xiàn)在我們看以下Manager的request方法

request

在兩個(gè)request方法中其中一request方法是先將參數(shù)封裝成NSURLRequest在調(diào)用另一個(gè)重載的request方法,并且在封裝成URLRequest的時(shí)候還對(duì)參數(shù)進(jìn)行了編碼。
我們的重點(diǎn)是在request(URLRequest:)這個(gè)方法這里。這個(gè)方法里面先是得到一個(gè)NSURLSessionTask然后將Task封裝成Request,并將Request的delegate 存入自己的delegate的里面然后放回。
到這里為止Manager在將URLRequest封裝成Request的時(shí)候就已經(jīng)將Request的delegate存放到自己的delegate里面,好在后面的時(shí)候可以使用。

接下來(lái)就是Manage類里面的重頭戲,session的代理。

SessionDelegate

先看SessionDelegate類的屬性部分,但在此之前先跟大家提一下這個(gè)類是Manager的內(nèi)部類,而且它的修飾符是final,這就意味著這個(gè)類是不可被繼承的。那為什么是內(nèi)部類呢?這里就留給大家好好體會(huì)??
在SessionDelegate類里面有字典subdelegates這個(gè)就是在request里面用來(lái)存放request的delegate的。而下面的subdelegateQueue則是保證對(duì)字典的線程安全。在這里我們還注意到SessionDelegate還實(shí)現(xiàn)了subscript下標(biāo)主要是為了存取方便,也順便吧線程安全的操作一起寫(xiě)入。

同時(shí),我們也可以注意到SessionDelegate實(shí)現(xiàn)了所有NSURLSession應(yīng)該實(shí)現(xiàn)的所有協(xié)議NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionDataDelegate和NSURLSessionDownloadDelegate。那么接下來(lái)我們看他是怎么實(shí)現(xiàn)的

NSURLSessionDelegate

因?yàn)樘L(zhǎng)了所以我只截取了NSURLSessionDelegate部分。大家可以注意到在這里主要有兩大塊一塊是Override Closures部分,另一塊是DelegateMethod部分,而且這兩塊是相互對(duì)應(yīng)的。那么為什么這么做呢?因?yàn)榭梢宰屖褂谜邔?duì)其中一些方法進(jìn)行自定義同時(shí)也建議大家看看這篇文章更輕量的 View Controllers。每一部分Delegate都是以這種形式寫(xiě)的。所以Alamofire給使用者提供了很大的自定義的空間。

Request

同樣的Request類在處理上面也是有內(nèi)部來(lái)處理代理的主要結(jié)構(gòu)入下圖所示:


Request

在Request里面有兩個(gè)代理,分別是TaskDelegate和DataTaskDelegate。同樣都是內(nèi)部類,那么為什么要這么分呢?那是因?yàn)镹SURLSessionTask是有不同的類型的:

NSURLSessionUploadTask:上傳任務(wù)類型
NSURLSessionDataTask:請(qǐng)求數(shù)據(jù)類型
NSURLSessionDownloadTask:下載類任務(wù)

而我們平常的GET、POST請(qǐng)求就是屬于DataTask類型的。而每種類型的Task都有需要實(shí)現(xiàn)的協(xié)議UploadTask和DataTake所需要實(shí)現(xiàn)的協(xié)議是
NSURLSessionDataDelegate而DownloadTask所需要實(shí)現(xiàn)的協(xié)議是NSURLSessionDownloadDelegate。而不管是哪一種類型的Task都需要實(shí)現(xiàn)NSURLSessionTaskDelegate。所以在Request的內(nèi)部類中TaskDelegate是實(shí)現(xiàn)了NSURLSessionTaskDelegate,DataTaskDelegate在繼承了TaskDelegate的基礎(chǔ)上實(shí)現(xiàn)了NSURLSessionDataDelegate。那么Download類型的呢?因?yàn)镈ownload在一般的app中比Data出現(xiàn)的概率小,所以不應(yīng)該出現(xiàn)在核心部分,所以Download是以擴(kuò)展的形式在Features中Download.swift文件中實(shí)現(xiàn)的。
所以Request類的核心部分最主要的就是基礎(chǔ)的TaskDelegate類是怎么實(shí)現(xiàn)的:

TaskDelegate

在TaskDelegate中我們最主要的是關(guān)注兩個(gè)屬性一個(gè)是task屬性和queue屬性。task 屬性就是NSURLSessionTask類型,所以在這里我們知道Request吧基礎(chǔ)Task封裝到Delegate里面而外層的Request只是一個(gè)提供方便方法的外套而已。另外一個(gè)需要關(guān)注的屬性queue是一個(gè)隊(duì)列。而且大家注意到在隊(duì)列初始化的時(shí)候吧隊(duì)列的suspended屬性設(shè)置為true,說(shuō)明不希望隊(duì)列里面的任務(wù)立刻執(zhí)行。那么什么時(shí)候執(zhí)行呢?我們直接跳到Delegate的代理方法

complete

在代理方法didCompleteWithError的時(shí)候?qū)ueue的suspended屬性設(shè)置成false就是說(shuō)明現(xiàn)在立刻運(yùn)行。所到這里的時(shí)候我們就已經(jīng)可以知道這個(gè)queue是存放這Request完成請(qǐng)求以后需要完成的東西。那么這個(gè)是什么東西呢?

Example

這個(gè)東西就是我們?cè)谑褂肁lamofire的時(shí)候所調(diào)用的.progress方法和response方法等等。在調(diào)用這兩個(gè)方法的時(shí)候會(huì)將我們需要執(zhí)行的代碼打包成closure存入queue中等拿到了服務(wù)器的回復(fù)后在讓queue運(yùn)行存放在里面的closure。

所以到這里為止本篇文章的目的已經(jīng)達(dá)到了。因?yàn)槠邢薏豢赡苊婷婢愕?,只能向大家解釋基本的流程。至于Features里面的內(nèi)容大部分是Manager和Request的擴(kuò)展。建議大家如果感興趣的話,還是閱讀源碼比較好。

如果大家有什么不明白的可以問(wèn)我,文章寫(xiě)的不好勿噴。

最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,632評(píng)論 4 61
  • 通知的概念 一些基本的概念就不做介紹了,應(yīng)該都明白,好了,直接上代碼為了方便查看,發(fā)送通知和接受通知就放在同一個(gè)文...
    edison0428閱讀 6,161評(píng)論 4 15
  • 年會(huì)的結(jié)束,也曾讓我一度以為這也是我在ios系統(tǒng)里的結(jié)束,去轉(zhuǎn)戰(zhàn)安卓的開(kāi)端。[流淚] 只可惜,只是因?yàn)橐徊恍⌒亩嗫?..
    HEROCJJ閱讀 519評(píng)論 0 2
  • 語(yǔ)言文字都是人類達(dá)意表情的工具:達(dá)意達(dá)的好,表情表的妙,便是文學(xué)。這是胡適在“什么是文學(xué)”中的原話。 最近在研究《...
    秋的歸來(lái)閱讀 501評(píng)論 0 0
  • 閑聊天,我們應(yīng)該都有過(guò)這樣的經(jīng)歷,幾個(gè)朋友在一起沒(méi)什么事,就各種聊,各種嗨。但是我從沒(méi)想過(guò)“閑聊天”能夠成為一個(gè)節(jié)...
    語(yǔ)見(jiàn)生活閱讀 1,100評(píng)論 0 3

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