AFNetWorking源碼解讀(持續(xù)更新...)

多閱讀別人的源碼是一種學(xué)習(xí),尤其是牛掰人的源碼,可惜自己是個渣渣進(jìn)不了BAT這種大廠俯画,所以只能靠閱讀優(yōu)秀的第三方框架來增長自己的知識面了蜕径,就算是這樣也是才開始两踏,不過亡羊補(bǔ)牢未為晚矣,啥時候醒悟都不晚兜喻,所以堅(jiān)持堅(jiān)持梦染,

如題所示,首先看上的就是AFNetWorking的源碼朴皆,重要性不多說了帕识,我覺得iOS程序員百分百都用過了,沒用過估計(jì)不是大牛遂铡,就是異類啦肮疗,封裝的沒的說,我這水平也難一下子窺其全貌扒接,在上班時間偷偷的看了幾天才總算了解各大概伪货,寫下了不求有多少人會看到们衙,但求把自己的理解寫下來避免忘記,水平再差也算一點(diǎn)心得嘛碱呼。
不多說先上圖拉出來溜溜:

AFNetworking.png

先說個大概蒙挑,然后每個類分別展開,最后在分析一下運(yùn)行過程愚臀,我覺得能掌握到這步就差不多啦忆蚀,剩下再多的,就看你的內(nèi)功如何了懊悯。

AFHTTPSessionManager

為啥說AFN牛逼呢蜓谋,就是因?yàn)樗o用戶提供的接口很簡單,只要傳入簡單的參數(shù)就可以在block中拿到數(shù)據(jù)炭分,非常方便桃焕,然后這種方便不代表實(shí)現(xiàn)起來方便(有點(diǎn)跑題)。AFHTTPSessionManager就是暴露給用戶的最外層封裝捧毛,給用戶很簡單的函數(shù)接口观堂,來實(shí)現(xiàn)很cool的功能。

AFHTTPSessionManager提供的接口.png

平時使用率95%的get 和 post 接口一目了然呀忧。前面幾函數(shù)都是初始化函數(shù)师痕,最后接種到此函數(shù)對,URLSession 進(jìn)行簡單的配置而账。

初始化AFHTTPSessionManage.png

AFHTTPSessionManager類繼承自AFURLSessionManager類胰坟,所以在此類可以看到很多super方法,這些都是配置URLSession的泞辐,這個下面在展開笔横。
經(jīng)過初始化后當(dāng)用戶想要調(diào)用網(wǎng)絡(luò)請求時,只要一個函數(shù)即可

調(diào)用get請求.png

其實(shí)所有的網(wǎng)絡(luò)請求都是調(diào)用中間的一個函數(shù)咐吼,封裝出來這么多函數(shù)就只能怪oc固有的坑了吹缔,

AFURLSessionManager

此類為AFN的核心類,封裝了URLSession 歷史不多說啦锯茄,如果有不明白的親們可以Google 一下URLSession厢塘,蘋果爸爸全面推薦,已經(jīng)把老的廢除了肌幽,同時還推薦一本入門好書晚碾,讀了它腰不酸,腿不疼了牍颈,一口氣擼一天也不需要營養(yǎng)快線了迄薄。

圖解HTTP

接著言歸正傳,正式初始化AFURLSessionManager的時候煮岁,干了幾件事

初始化AFURLSessionManager

最開始初始化了一個默認(rèn)的配置[NSURLSessionConfiguration defaultSessionConfiguration] 讥蔽,這貨簡單就是可以配置http請求的涣易,這跟URLSession的設(shè)計(jì)有關(guān),每個請求都可以獨(dú)立配置冶伞。
然后創(chuàng)建了一個最大運(yùn)行數(shù)為1的隊(duì)列新症,說白了就是同步的啊,這樣我覺得可以避免資源競爭响禽,而且可以節(jié)省資源徒爹,(注:AFN2的時候此處是創(chuàng)建一條常駐線程,其實(shí)效果是一樣的芋类,如果每次請求的時候都開線程隆嗅,請求后再關(guān)閉,這期間就會浪費(fèi)好多資源啊侯繁,所以單開一個常駐線程宾肺,這樣所有的請求來的時候都走這一個線程雾狈,省資源祖娘,這也算一個曝光率比較高的面試題掷倔,寫到這想到了所以說一下)。
然后初始化了一個NSURLSession進(jìn)行網(wǎng)絡(luò)通信用咕别。然后初始化一個解析返回報文體的實(shí)例技健,默認(rèn)初始化的是json解析的(大部分網(wǎng)絡(luò)都是這個套路)。
然后初始化一個AFSecurityPolicy類惰拱,這個類是負(fù)責(zé)https加密雌贱,以及協(xié)商秘鑰xxx等操作的,后學(xué)再講偿短,因?yàn)檫@個類是單獨(dú)的帽芽,不知道它并不影響其他的學(xué)習(xí)。
然后開始又初始化了網(wǎng)絡(luò)監(jiān)控AFNetworkReachabilityManager翔冀,這貨也是可以單獨(dú)使用的,功能說白了很簡單披泪,就是通過橋接bridge 來監(jiān)控當(dāng)前的網(wǎng)絡(luò)狀態(tài):無網(wǎng)纤子、未知網(wǎng)絡(luò)、WiFi款票、手機(jī)網(wǎng)絡(luò)等控硼。
然后初始化一個字典,會把該session下的所有Task通過ID存到字典里艾少,并且初始化一個NSLock卡乾,這把鎖基本上就是鎖住這個字典的,因?yàn)锳FN整體上來說是異步的缚够,避免數(shù)據(jù)混亂造成資源競爭幔妨。
一個session里面可能存在三種Task: 數(shù)據(jù)傳輸鹦赎、下載、上傳误堡。便利session 把緩存的session 都存到字典里古话。并且為task設(shè)置delegate。

設(shè)置代理

此函數(shù)先進(jìn)行了初始化了代理AFURLSessionManagerTaskDelegate锁施,主要的是初始化了一個NSProgress實(shí)例(我之前也沒用過陪踩,是封裝的管理進(jìn)度的類,主要是用于管理下載悉抵,和上傳進(jìn)度的)肩狂,

初始化AFURLSessionManagerTaskDelegate

然后把Task的代理用字典保存起來,在此處加鎖姥饰,為了防止資源混亂原因不說啦傻谁,然后設(shè)置通知,讓外界可以觀察到這一變化媳否。


設(shè)置代理

三種代理設(shè)置代理的方式基本上相同栅螟,只不過在添加下載代理中添加了如果有下載的資源為其單獨(dú)添加下載資源的回調(diào)。


下載資源回調(diào)

再往后不得不說創(chuàng)建Task任務(wù)了
創(chuàng)建Task任務(wù)

再此處創(chuàng)建了一個全局的串行隊(duì)列篱竭,保證發(fā)出請求不會錯亂(本人所在公司是帶藍(lán)牙硬件的力图,前人遺留的‘財富’中根本沒有這東西,導(dǎo)致經(jīng)常會出現(xiàn)很詭異的數(shù)據(jù)問題掺逼,滿滿的都是坑啊),還有個人認(rèn)為這種用static的這種方式不錯吃媒,可以多用呢

創(chuàng)建串行隊(duì)列

同樣如之前的代碼,創(chuàng)建Task也分三種吕喘,每種都有一點(diǎn)不一樣

創(chuàng)建uploadTask

創(chuàng)建uploadTask中添加了對最大上傳數(shù)的判斷赘那,AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask最大默認(rèn)上傳數(shù)為3 而且根據(jù)上傳的是文件還是data還有不同的封裝,
剩下封裝了一堆NSURLSessionDataDelegate 和NSURLSessionDownloadDelegate 基本了氯质,基本上都是通過回調(diào)的方式搞的募舟,讓用戶能比較方便的使用AFN闻察,這玩意可以參看這蘋果官方api慢慢看,功能一目了然辕漂。
剩下還有AFURLSessionManagerTaskDelegate在前面也介紹了,他的初始化钉嘹,簡單的來說URLSession 就是通過NSURLSessionConfiguration實(shí)現(xiàn)對網(wǎng)絡(luò)條件的配置鸯乃,通過NSURLSession創(chuàng)建加載http請求的信息跋涣,通過Task來實(shí)現(xiàn)動作鸟悴。這是我個人的理解不一定對哈,但是最少簡單明了宏蛉,感覺又說跑了哈遣臼。
這個類中最關(guān)鍵的就是接收到數(shù)據(jù)傳輸解析數(shù)據(jù)的方法啦

接收數(shù)據(jù)解析過程

實(shí)現(xiàn)了**- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask )task didCompleteWithError:(NSError )error;代理,官方解釋

告訴代理任務(wù)完成傳輸數(shù)據(jù)揍堰。
服務(wù)器錯誤不會通過錯誤參數(shù)報告嗅义。代表通過錯誤參數(shù)收到的唯一錯誤是客戶端錯誤,例如無法解析主機(jī)名或連接到主機(jī)之碗。

說白了就是http請求完成后的回調(diào)。代碼創(chuàng)建了一個字典存了一下有關(guān)網(wǎng)絡(luò)請求的信息幽纷,包括返回的值等self.mutableData 是在接收返回數(shù)據(jù)的代理中被賦值的博敬,如果有錯誤信息則把錯誤拋回去(例如:code=1022,iOS9后不支持http請求等,xxx信息)偏窝。如果沒有錯誤信息即認(rèn)為是正確的。

這一句把返回的數(shù)據(jù)穿進(jìn)去伦意,其實(shí)就是兜一圈根據(jù)你的初始化解析報文體什么格式的數(shù)據(jù)就按照什么格式的解析硼补,最后傳回來。最后把返回的數(shù)據(jù)通過回調(diào)趕回去已骇,這就是一個接收過程就完事啦疾捍。拼的字典最后通過通知傳出去了栏妖,給需要的類,或者自己接收也行啊吊趾。如果不嫌麻煩的話??瑟啃。
在下面就是對于下載數(shù)據(jù)的一些代理封裝揩尸,怎么拼數(shù)據(jù)啥的,不多敘述

_AFURLSessionTaskSwizzling

這個類用到了runtime的高級api 替換函數(shù)错负,主要是替換Task 中的resume勇边、suspend方法犹撒,加上通知,當(dāng)此函數(shù)執(zhí)行后可以發(fā)出通知告知業(yè)務(wù)類粒褒。借鑒網(wǎng)上的說法识颊,這是一個神奇的類奕坟,為啥說神奇月杉,不多說直接上代碼 在load方法時就開始搞事情了。

替換resume方法

到此AFURLSessionManager這個類就說的差不多奠伪,我這也只能窺其部分首懈。不能窺其全貌啊,不過這個類算AFN的核心類了究履,其他的類都是為他服務(wù)的最仑,一定要多看幾遍。

AFURLResponseSerialization

這個類意在根據(jù)不同的返回體解析數(shù)據(jù)泥彤。所有的子類都需要實(shí)現(xiàn)AFURLResponseSerialization代理方法,這個代理有且只有一個這個方法菱父。

實(shí)現(xiàn)代理

在AFHTTPResponseSerializer類中init方法很簡單 就是初始化了一個NSIndexSet浙宜。acceptableContentTypes參數(shù)為所每種響應(yīng)格式所以解析的返回頭中的信息
然后就是一個公共的驗(yàn)證響應(yīng)有效性的方法啦

驗(yàn)證響應(yīng)有效性

剩下的類目都是事先代理方法,根據(jù)不同數(shù)據(jù)格式進(jìn)行解析同仆,沒啥好解釋的啦裙品,大家自己看啦。

AFHTTPRequestSerializer

這個類是拼裝請求頭清酥,和請求體焰轻,具體的http協(xié)議的知識,如果不清楚的請看我推薦的書辱志,我后面會發(fā)個鏈接供大家下載。

初始化

初始化的時候默認(rèn)使用UTF-8 拼接出來的信息都存在了mutableHTTPRequestHeaders字典中什乙。其中HTTPMethodsEncodingParametersInURI初始化了通用拼裝的請求類型 已球,大家知道post是所以的信息是不會頻道URL里的而是放到請求體里的智亮。然后初始化了幾個URLSession的參數(shù).

 allowsCellularAccess       會根據(jù)電量和電源燈情況自動設(shè)置最佳值
 cachePolicy                設(shè)置緩存策略 NSURLRequestUseProtocolCachePolicy 對特定的 URL 請求使用網(wǎng)絡(luò)協(xié)議中實(shí)現(xiàn)的緩存邏輯。這是默認(rèn)的策略  使用默認(rèn)的緩存策略,用kvo監(jiān)聽這幾個值的變化阔蛉,從而知道用戶的需求,這種方法我覺得是不想暴露最核心的URLSession聋呢。
HTTPShouldHandleCookies    設(shè)置cookies
HTTPShouldUsePipelining    保證每個URLSession 都會開啟一個單獨(dú)的連接池
 networkServiceType
 timeoutInterval

在每次發(fā)起網(wǎng)絡(luò)請求時都會調(diào)用此方法輕裝請求頭颠区,這也算核心方法

拼裝協(xié)議頭

中間的for循環(huán)是根據(jù)kvo獲取到的值用kvc 的方式加載到NSMutableURLRequest中毕莱,設(shè)置屬性测暗,最后需要把保存到字典里的方法格式化橙http請求所用到的格式

格式化請求頭

首先把已有格式轉(zhuǎn)換成字典 如果parameters附帶信息不為空磨澡,使用NSString * AFQueryStringFromParameters(NSDictionary *parameters)字典轉(zhuǎn)出URL編碼形式质和,URL編碼就是一堆%的那種格式,不知道自己Google吧最后做個判斷如果不是post形式的就把參數(shù)拼接到URL的后面 如果為post的就拼接到請求體中厦酬。
剩下的是拼裝body 我也不是特別明白了瘫想,一般的情況下不需要,等我了解后把這部分補(bǔ)上减噪,只能說我也學(xué)習(xí)不夠啊车吹,還在不斷的看書中,

AFNetworkReachabilityManager

AFSecurityPolicy

這兩個類我也不是特別懂了朝卒,都是用底層C語言去封裝的乐埠,要是硬著頭皮來需要看好久,我推薦大家看看大牛的講解就好了瑞眼,對于我這種渣渣來說實(shí)在是有心無力啊扯罐,不過還好這兩個類都是單獨(dú)的,不了解的話也不影響你對AFN核心業(yè)務(wù)的理解歹河。

總結(jié):其實(shí)看完AFN我還是感觸頗多秸歧,之前對http不是很了解,逼著自己去看源碼還是很起作用的键菱,感覺受益良多,AFN除了主業(yè)務(wù)以外還有一些分類補(bǔ)充UIKit UIKit+AFNetworking 這個我會后續(xù)再寫一篇拭抬,自私的說不為別人,為自己也得寫一篇傅蹂,我覺得把東西寫出來后可以很好的補(bǔ)充一下當(dāng)時被忽略的東西算凿,很有用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婚夫,一起剝皮案震驚了整個濱河市署鸡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侍筛,老刑警劉巖撒穷,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異禽笑,居然都是意外死亡蛤奥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門蟀伸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缅刽,“玉大人,你說我怎么就攤上這事迟蜜》仁。” “怎么了髓霞?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵方库,是天一觀的道長障斋。 經(jīng)常有香客問我,道長配喳,這世上最難降的妖魔是什么凳干? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任救赐,我火速辦了婚禮,結(jié)果婚禮上经磅,老公的妹妹穿的比我還像新娘预厌。我一直安慰自己,他們只是感情好轧叽,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布炭晒。 她就那樣靜靜地躺著,像睡著了一般网严。 火紅的嫁衣襯著肌膚如雪震束。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天休雌,我揣著相機(jī)與錄音肝断,去河邊找鬼驰凛。 笑死担扑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胚宦。 我是一名探鬼主播燕垃,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼您旁!你這毒婦竟也來了轴捎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤侦锯,失蹤者是張志新(化名)和其女友劉穎秦驯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葱蝗,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡细燎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年玻驻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片璧瞬。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡嗤锉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘟忱,到底是詐尸還是另有隱情,我是刑警寧澤垫挨,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布九榔,位于F島的核電站哀峻,受9級特大地震影響剩蟀,放射性物質(zhì)發(fā)生泄漏切威。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望槽袄。 院中可真熱鬧,春花似錦截酷、人聲如沸乾戏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呐能。三九已至,卻和暖如春摆出,著一層夾襖步出監(jiān)牢的瞬間偎漫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工温亲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铸豁。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓节芥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親头镊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容