菜鳥簡單解讀AFNetworking

對于客戶端開發(fā)來說韵卤,同網絡請求相關的代碼總是相對復雜的,因為它牽扯到request的序列化啡专,response的解析,繁多的異常錯誤處理和多線程的調度……
很多iOS的開發(fā)人員制圈,或許不知道NSURLConnection(現在官方已經不鼓勵使用)们童、NSURLSession、NSURLSessionTask……但肯定知道AFNetworking(OC)與Alamofire(Swift)鲸鹦。在iOS端幾乎所有與網絡請求相關的處理慧库,都會牽扯到這兩個開源庫。公司的網絡層馋嗜,會根據實際的業(yè)務的需要齐板,在AFNetworking/Alamofire的基礎上繼續(xù)封裝。
這里說一點兒題外話,之前我還不是特別理解為何要做過度封裝甘磨,最近有所感受橡羞,主要原因有兩點:

  1. 同一套底層設計,由于不同的業(yè)務需求會表現出明顯的差異济舆,因此需要在第三庫的基礎上卿泽,進一步封裝成方便業(yè)務層代碼調用的API。
  2. 無法保證第三庫會有持續(xù)的維護滋觉,它可能會出現性能問題签夭、bug或者版本的更迭。若自己封裝過一層椎侠,那么在這些情況出現的時候第租,只需要對中間層進行維護,讓業(yè)務層無感知我纪。

先來想一想如果我們自己要寫一個網絡請求的庫慎宾,它需要具備哪些功能:

  1. request的序列化:URL的拼接,參數解析并拼接成query宣羊,根據網絡請求的方法(get璧诵、post、head……)生成正確的request
  2. 監(jiān)聽網絡狀況:當前的網絡環(huán)境(WiFi還是cellular)仇冯,網絡安全狀況(證書問題)
  3. 監(jiān)聽網絡請求中的各個環(huán)節(jié)之宿。例如:請求是否完成,客戶端是否收到數據苛坚,是否發(fā)生錯誤等
  4. 針對與網絡請求中的各個環(huán)節(jié)比被,要有相應的默認處理,最重要的是對各種異常錯誤的處理泼舱,保證到最后用戶拿到的是想要的數據
  5. 對response的解析等缀,各種格式JSON、XML等

針對第3點娇昙,看一看在AFNetworking是怎么實現尺迂。
這里不對代碼中的一些細節(jié)作解釋,若想一行一行地深究細節(jié)冒掌,推薦涂耀輝 - 簡書大神寫的AF解讀系列噪裕。

AFNetworking是圍繞著NSURLSession做了一層封裝,先來看看NSURLSession的作用:

With the NSURLSession API, your app creates one or more sessions, each of which coordinates a group of related data transfer tasks. For example, if you are writing a web browser, your app might create one session per tab or window, or one session for interactive use and another session for background downloads. Within each session, your app adds a series of tasks, each of which represents a request for a specific URL (following HTTP redirects if necessary).
NSURLSession

同我們在做web開發(fā)時的session聯(lián)系了起來股毫,它是用來管理一系列的NSURLSessionTask膳音,而我們的每一個request都會經由NSURLSession生成一個NSURLSessionTask。這樣就明白了铃诬,NSURLSession就是用來管理一系列request的祭陷,至于如何管理苍凛,就不用管啦。事實上兵志,蘋果發(fā)布的NSURLSession的概念應該是從AF2.x借鑒過來的醇蝴。當年的AF2.x是圍繞著NSURLConnection做封裝,結合NSOperation實現了網絡請求的資源分配和線程調度想罕。而如今哑蔫,這一切都被內置的NSURLSession給實現了。而一個NSURLSession需要一個delegate弧呐,并實現一系列的NSURLSessionDelegate方法,這些方法就是在請求的各個環(huán)節(jié)被系統(tǒng)回調的嵌纲,也就對應著第4個功能點俘枫。

在AF中,最核心的類是AFURLSessionManager逮走,幾乎所有同網絡請求相關的核心操作都是由這個類完成或是調度完成的鸠蚪。我們常用的AFHTTPSessionManager是這個類的子類,子類只是封裝了一下父類中的方法师溅,其實并沒有干實事茅信。而在這個類中,就維護了一個NSURLSession類型的session墓臭。
先看看使用AF如何發(fā)出一個網絡請求:

AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"example.com"] sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

首先需要初始化一個AFURLSessionManager蘸鲸,也就在這個時候,內部的初始化函數創(chuàng)建了一個NSURLSession窿锉,而這個session的delegate也就是維護它的manager:

self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

隨后酌摇,我們通過這個manager發(fā)出一個網絡請求:

[manager GET:@"schema" parameters:nil progress:nil success:nil failure:nil];

在這段代碼的背后,manager會通過傳進來的URL和parameters序列化一個request嗡载,更進一步窑多,manager中維護的session會為每一個request生成一個dataTask:

dataTask = [self.session dataTaskWithRequest:request];

最后只需要[dataTask resume]就可以觸發(fā)這次網絡請求任務了。
那么最關鍵的問題就變成了manager如何管理這些dataTask了洼滚。
我個人覺得埂息,這就是AF中最關鍵的地方了:manager會為每一個dataTask配置一個AFURLSessionManagerTaskDelegate。
AFURLSessionManagerTaskDelegate中只不過是將NSURLSessionDelegate中的三個方法提取了出來遥巴,提供了完整的實現千康,這三個方法的簽名是:

- URLSession:task:didCompleteWithError:
- URLSession:dataTask:didReceiveData:
- (void)URLSession:downloadTask:didFinishDownloadingToURL:

AFURLSessionManager本可以實現NSURLSessionDelegate的全部接口,那么為什么偏偏要把這三個方法提取出來挪哄,提供另外一個代理接口吧秕?主要原因可能是這樣的:每一個dataTask都是很不一樣的,若對一個session管理的所有dataTask都設置成同一個delegate(即manager)迹炼,那么用戶如何取到不同dataTask回調回來的不同信息砸彬?因此颠毙,我們需要把那些會針對不同dataTask返回不同數據信息的回調函數單獨抽出來(因為不同dataTask返回的數據信息是不一樣的),為每一個dataTask都配置一個delegate砂碉,而對于一些公共環(huán)節(jié)的處理則交給manager做統(tǒng)一處理蛀蜜。
感覺干看上面這段話,挺難懂的增蹭,貼圖說明:

image.png

到這里為止滴某,manager已經實現了對每一個dataTask的監(jiān)聽功能。當然我的解釋很簡短滋迈,AF中的細節(jié)實現還有大大的可以深究的地方(大神寫的代碼確實牛逼)霎奢,但是細節(jié)方面需要粘貼大段的代碼,筆者不是提別喜歡這種方式饼灿,強烈推薦涂耀輝 - 簡書大神的《AFNetworking到底做了什么》系列幕侠。

本文章后續(xù)會有增修。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末碍彭,一起剝皮案震驚了整個濱河市晤硕,隨后出現的幾起案子,更是在濱河造成了極大的恐慌庇忌,老刑警劉巖舞箍,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異皆疹,居然都是意外死亡疏橄,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門略就,熙熙樓的掌柜王于貴愁眉苦臉地迎上來软族,“玉大人,你說我怎么就攤上這事残制×⒃遥” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵初茶,是天一觀的道長颗祝。 經常有香客問我,道長恼布,這世上最難降的妖魔是什么螺戳? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮折汞,結果婚禮上倔幼,老公的妹妹穿的比我還像新娘。我一直安慰自己爽待,他們只是感情好损同,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布翩腐。 她就那樣靜靜地躺著,像睡著了一般膏燃。 火紅的嫁衣襯著肌膚如雪茂卦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天组哩,我揣著相機與錄音等龙,去河邊找鬼。 笑死伶贰,一個胖子當著我的面吹牛蛛砰,可吹牛的內容都是我干的。 我是一名探鬼主播黍衙,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼暴备,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了们豌?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浅妆,失蹤者是張志新(化名)和其女友劉穎望迎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體凌外,經...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡辩尊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了康辑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摄欲。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖疮薇,靈堂內的尸體忽然破棺而出胸墙,到底是詐尸還是另有隱情,我是刑警寧澤按咒,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布迟隅,位于F島的核電站,受9級特大地震影響励七,放射性物質發(fā)生泄漏智袭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一掠抬、第九天 我趴在偏房一處隱蔽的房頂上張望吼野。 院中可真熱鬧,春花似錦两波、人聲如沸瞳步。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谚攒。三九已至阳准,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間馏臭,已是汗流浹背野蝇。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留括儒,地道東北人绕沈。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像帮寻,于是被迫代替她去往敵國和親乍狐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容