在開始介紹之前先明確一點(diǎn)蒋纬,本篇寫的不是關(guān)于Alamofire是怎么使用的腋颠,而是我仔細(xì)看了Alamofire框架代碼后的一點(diǎn)感受與大家分享闺阱。寫的不好也請(qǐng)大家見諒崖蜜。如果是想要學(xué)習(xí)怎么使用的話還是建議直接閱讀github上面的文檔Alamofire documentation從基本到高級(jí)都講解的很詳細(xì)焰雕。
Alamofire
對(duì)于使用oc的同學(xué)來說一定十分熟悉AFNetworking這個(gè)框架衷笋,因?yàn)楝F(xiàn)在我們的app只要是有關(guān)于網(wǎng)絡(luò)訪問的部分大部分都會(huì)通過這個(gè)框架來進(jìn)行網(wǎng)絡(luò)的訪問。而本篇要說的Alamofire就是swift版本的AFNetworking拉矩屁。所以Alamofire也是進(jìn)行網(wǎng)絡(luò)訪問的框架辟宗。
整體架構(gòu)
從github上下載Alamofire用Xcode打開可以看到如下的結(jié)構(gòu)目錄:
其中主要分為3部分:
- Alamofire.swift文件
- Core核心部分
- Features部分
我主要是分析Core部分的代碼,而Features部分的代碼我只會(huì)分析一部分吝秕,因?yàn)镕eatures部分的代碼是大同小異的只要理解了其中一部分的代碼是怎么寫的其他的只要在稍稍閱讀下就可以了泊脐,當(dāng)然每個(gè)部分的代碼都有其精彩之處。希望大家有時(shí)間也可以自己再去閱讀下大家多交流交流??烁峭。
Alamofire.swift分析
在Alamofire.swift文件主要有兩個(gè)功能:1. 提供了整個(gè)框架的入口容客。2. 向整個(gè)框架提供了方便的工具方法。
整個(gè)Alamofire.swift文件在內(nèi)容上面也主要分成了兩部分:
第一部分:
在這一部分中主要是定義了兩個(gè)Convertible協(xié)議和一個(gè)Convenience方法
兩個(gè)個(gè)Convertible協(xié)議代碼如下:
這個(gè)協(xié)議是規(guī)定了其他類轉(zhuǎn)化為URLString的方法從而可以使用這個(gè)來構(gòu)造URLRequest约郁。這么做得目的是將個(gè)各類的轉(zhuǎn)化方法和方式分散到個(gè)各類中各自實(shí)現(xiàn)耘柱,就可以避免出現(xiàn)一大坨的轉(zhuǎn)化方法,實(shí)現(xiàn)代碼的美觀棍现。同理在接下來的URLRequestConvertible也是這個(gè)道理
接下來就是工具方法了
這個(gè)方法是用來構(gòu)造NSURLRequest的簡便方法调煎,其中有一個(gè)參數(shù)就是URLStringConvitible類型的。所以如果我們自己的某個(gè)類也實(shí)現(xiàn)了URLStringConvertible協(xié)議也是可以通過這個(gè)方法構(gòu)造NSURLRequest的己肮。在有一個(gè)Method類型這個(gè)類型是
定義在ParameterEncoding.swift文件中士袄。
接下來就是提供了整個(gè)框架的入口方法,這里就先不做介紹等下面的Core部分懂了那么這部分就很自然的懂了
Core部分
在正式介紹整個(gè)核心部分之前谎僻,必須要有NSURLSession的基礎(chǔ)知識(shí)娄柳,因?yàn)檎麄€(gè)Alamofire框架其實(shí)是對(duì)NSURLSession進(jìn)行封裝的。如果對(duì)這一方面的只是缺乏還是建議先去補(bǔ)充一下艘绍,不然的話你會(huì)不知道接下來為什么要這么做赤拒。
在3個(gè)文件中總共是有Manager類、Request類和ParameterEncoding枚舉類型。
Manager類:封裝了NSURLSession以及相對(duì)應(yīng)的代理方法
Request類: 封裝了NSURLSessionTask以及Task的基本的代理方法
ParameterEncodeing:負(fù)責(zé)對(duì)HTTP請(qǐng)求的參數(shù)進(jìn)行編碼
框架總體流程是:
這個(gè)是發(fā)送的流程挎挖,我們調(diào)用Alamofire.swift里的方法这敬,而Alamofire里的方法其實(shí)是創(chuàng)建一個(gè)Manager調(diào)用Manager里的方法將得到的NSURLSessionTask封裝成Request實(shí)例,發(fā)送并且返回Request實(shí)例蕉朵。
在消息發(fā)送成功了崔涂,服務(wù)器處理好以后,需要將處理好的回復(fù)發(fā)送回來那么在發(fā)送回來的時(shí)候首先是調(diào)用了Manager的代理方法始衅,然后在Manager中調(diào)用Request類的方法冷蚂,最后才是掉用response方法和progress方法等。
那么在我們進(jìn)行網(wǎng)絡(luò)訪問的時(shí)候一定不是只是發(fā)一個(gè)Request這么簡單汛闸,而是有很多個(gè)Request那么在有回調(diào)的時(shí)候Manager是怎么知道是哪個(gè)Request的回調(diào)呢蝙茶?那么接下來這就要求我們知道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方法
在兩個(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í)候可以使用畸肆。
接下來就是Manage類里面的重頭戲宦芦,session的代理。
先看SessionDelegate類的屬性部分轴脐,但在此之前先跟大家提一下這個(gè)類是Manager的內(nèi)部類调卑,而且它的修飾符是final,這就意味著這個(gè)類是不可被繼承的大咱。那為什么是內(nèi)部類呢恬涧?這里就留給大家好好體會(huì)??
在SessionDelegate類里面有字典subdelegates這個(gè)就是在request里面用來存放request的delegate的。而下面的subdelegateQueue則是保證對(duì)字典的線程安全碴巾。在這里我們還注意到SessionDelegate還實(shí)現(xiàn)了subscript下標(biāo)主要是為了存取方便溯捆,也順便吧線程安全的操作一起寫入。
同時(shí)厦瓢,我們也可以注意到SessionDelegate實(shí)現(xiàn)了所有NSURLSession應(yīng)該實(shí)現(xiàn)的所有協(xié)議NSURLSessionDelegate提揍、NSURLSessionTaskDelegate、NSURLSessionDataDelegate和NSURLSessionDownloadDelegate煮仇。那么接下來我們看他是怎么實(shí)現(xiàn)的
因?yàn)樘L了所以我只截取了NSURLSessionDelegate部分劳跃。大家可以注意到在這里主要有兩大塊一塊是Override Closures部分,另一塊是DelegateMethod部分浙垫,而且這兩塊是相互對(duì)應(yīng)的刨仑。那么為什么這么做呢郑诺?因?yàn)榭梢宰屖褂谜邔?duì)其中一些方法進(jìn)行自定義同時(shí)也建議大家看看這篇文章更輕量的 View Controllers。每一部分Delegate都是以這種形式寫的杉武。所以Alamofire給使用者提供了很大的自定義的空間辙诞。
Request
同樣的Request類在處理上面也是有內(nèi)部來處理代理的主要結(jié)構(gòu)入下圖所示:
在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中我們最主要的是關(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忍坷,說明不希望隊(duì)列里面的任務(wù)立刻執(zhí)行粘舟。那么什么時(shí)候執(zhí)行呢?我們直接跳到Delegate的代理方法
在代理方法didCompleteWithError的時(shí)候?qū)ueue的suspended屬性設(shè)置成false就是說明現(xiàn)在立刻運(yùn)行佩研。所到這里的時(shí)候我們就已經(jīng)可以知道這個(gè)queue是存放這Request完成請(qǐng)求以后需要完成的東西柑肴。那么這個(gè)是什么東西呢?
這個(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)槠邢薏豢赡苊婷婢愕桨硇颍荒芟虼蠹医忉尰镜牧鞒趟队摺V劣贔eatures里面的內(nèi)容大部分是Manager和Request的擴(kuò)展。建議大家如果感興趣的話政模,還是閱讀源碼比較好岗宣。
如果大家有什么不明白的可以問我,文章寫的不好勿噴淋样。