AFNetworking源碼解讀

最近一直在研究AFN坏瘩,覺(jué)得有必要記錄一下自己的心得,一是可以自己加深印象,二是可以幫助一下不太了解AFN的人柬脸,都是自己的一些觀點(diǎn)他去,若有錯(cuò)誤之處,還請(qǐng)大神幫忙指出來(lái)倒堕!覺(jué)得雞肋的請(qǐng)略過(guò)灾测,謝謝!

AFN最新版本已經(jīng)來(lái)到了3.x了垦巴,也從以前基于NSURLConnection重構(gòu)到基于NSURLSession的新版本媳搪。新版本的AFN更加簡(jiǎn)潔你只需要知道幾個(gè)主要的類就可以了解AFN的工作流程。先列舉一下:

1骤宣、AFURLSessionManager;

2秦爆、AFHTTPSessionManager;

3、AFURLRequestSerialization憔披;

4等限、AFURLResponseSerialization;

AFURLSessionManager 是AFN的核心文件芬膝,集成了管理請(qǐng)求的建立望门、管理、銷毀锰霜、安全筹误、請(qǐng)求重定向、請(qǐng)求重啟等功能癣缅。主要實(shí)現(xiàn)了對(duì)NSURLSession和NSURLSessionTask的封裝厨剪,以及重定向處理結(jié)果。

AFHTTPSessionManager 是AFURLSessionManager的子類友存,主要用于處理HTTP和HTTPS的請(qǐng)求丽惶,我們平時(shí)用的最多的也是這個(gè)類,對(duì)這個(gè)類做一個(gè)二次封裝爬立,然后完成我們請(qǐng)求接口的業(yè)務(wù)。

AFURLRequestSerialization這個(gè)類說(shuō)白了就是創(chuàng)建一個(gè)NSURLRequest請(qǐng)求體万哪,AFN直接把這一塊給抽離出來(lái)侠驯,把所有關(guān)于request的業(yè)務(wù)都放在了這里,如設(shè)置GET\POST方法奕巍,設(shè)置請(qǐng)求頭吟策、超時(shí)時(shí)間、請(qǐng)求的緩存策略的止、如何處理請(qǐng)求參數(shù)(GET與POST的方法不同)檩坚,清晰明了!

AFURLResponseSerialization 很明顯這個(gè)類是用來(lái)處理網(wǎng)絡(luò)請(qǐng)求的返回值的。對(duì)返回?cái)?shù)據(jù)序列化匾委、編碼解碼拖叙、數(shù)據(jù)處理等。這里AFURLResponseSerialization只是一個(gè)協(xié)議赂乐,AFHTTPResponseSerializer類遵守這個(gè)協(xié)議薯鳍,實(shí)現(xiàn)了協(xié)議方法,還有其他幾個(gè)類繼承了AFHTTPResponseSerializer挨措,如:AFJSONResponseSerializer挖滤、AFXMLParserResponseSerializer、AFPropertyListResponseSerializer浅役、AFImageResponseSerializer斩松,所以在處理數(shù)據(jù)的時(shí)候,看你的返回值是什么類型的就用那個(gè)類去處理就好了觉既,AFN使用的是AFJSONResponseSerializer惧盹。

廢話不多說(shuō),上代碼:

1奋救、AFHTTPSessionManager中岭参,常用的兩個(gè)請(qǐng)求方法,POST\GET方法

- (NSURLSessionDataTask *)POST:(NSString *)URLString

? ? ? ? ? ? ? ? ? ? parameters:(id)parameters

? ? ? ? ? ? ? ? ? ? ? progress:(void (^)(NSProgress * _Nonnull))uploadProgress

? ? ? ? ? ? ? ? ? ? ? success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success

? ? ? ? ? ? ? ? ? ? ? failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure

{

? ? NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];

? ? [dataTask resume];

? ? return dataTask;

}

- (NSURLSessionDataTask *)GET:(NSString *)URLString

? ? ? ? ? ? ? ? ? parameters:(id)parameters

? ? ? ? ? ? ? ? ? ? progress:(void (^)(NSProgress * _Nonnull))downloadProgress

? ? ? ? ? ? ? ? ? ? ? success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success

? ? ? ? ? ? ? ? ? ? ? failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure

{

? ? NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? URLString:URLString

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? parameters:parameters

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uploadProgress:nil

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? downloadProgress:downloadProgress

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? success:success

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? failure:failure];

? ? [dataTask resume];

? ? return dataTask;

}

//兩個(gè)方法都調(diào)用了dataTaskWithHTTPMethod:這個(gè)方法尝艘,返回一個(gè)task,這個(gè)task就是我們的請(qǐng)求任務(wù)演侯。拿到這個(gè)//task我們還可以Cancel請(qǐng)求。下面去看看?dataTaskWithHTTPMethod:這個(gè)方法背亥。

- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
?????????????????????????????????????? URLString:(NSString *)URLString
????????????????????????????????????? parameters:(id)parameters
????????????????????????????????? uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
??????????????????????????????? downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
???????????????????????????????????????? success:(void (^)(NSURLSessionDataTask *, id))success
???????????????????????????????????????? failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
{
??? NSError *serializationError = nil;

//這里使用requestSerialize 去獲取一個(gè)request請(qǐng)求體秒际,如果是post就把參數(shù)設(shè)置在body里,如果是get就把鍵值對(duì)添加到url后面,關(guān)于baseURL使用的時(shí)候可以去SDK的介紹中去看看狡汉,介紹的很清楚娄徊。

??? NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
??? if (serializationError) {
??????? if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
??????????? dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
??????????????? failure(nil, serializationError);
??????????? });
#pragma clang diagnostic pop
??????? }

??????? return nil;
??? }
//這里創(chuàng)建下載任務(wù)、跳轉(zhuǎn)到AFURLSessionManager去執(zhí)行方法盾戴,block是成功和失敗的回調(diào)寄锐。注意success參數(shù)是task,responseObject,failure的參數(shù)的task和error尖啡;
??? __block NSURLSessionDataTask *dataTask = nil;
??? dataTask = [self dataTaskWithRequest:request
????????????????????????? uploadProgress:uploadProgress
??????????????????????? downloadProgress:downloadProgress
?????????????????????? completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
??????? if (error) {
??????????? if (failure) {
??????????????? failure(dataTask, error);
??????????? }
??????? } else {
??????????? if (success) {
??????????????? success(dataTask, responseObject);
??????????? }
??????? }
??? }];

??? return dataTask;
}

接下來(lái)去AFURLSessionManger中去看生成task的方法橄仆。

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock

? ? ? ? ? ? ? ? ? ? ? ? ? ? downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock

? ? ? ? ? ? ? ? ? ? ? ? ? ? completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,? NSError * _Nullable error))completionHandler {

? ? __block NSURLSessionDataTask *dataTask = nil;

//很明顯,在這里生成了task衅斩,self.session就是NSURLSession盆顾,在創(chuàng)建AFURLSessionManger的是就創(chuàng)建了,這里session是默認(rèn)是defaultSessionConfiguration格式的畏梆,AFURLSessionManger會(huì)實(shí)現(xiàn)session的代理方法您宪,不過(guò)奈懒,不會(huì)在這里處理這些方法返回的數(shù)據(jù),而是做了一個(gè)重定向宪巨,轉(zhuǎn)到別的地方去處理了磷杏。具體在哪處理,往下看揖铜。茴丰。。

? ? url_session_manager_create_task_safely(^{

? ? ? ? dataTask = [self.session dataTaskWithRequest:request];

? ? });

//這里是定義的處理重定向數(shù)據(jù)的代理

? ? [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

? ? return dataTask;

}

//生成代理對(duì)象天吓,注意:這里只有一個(gè)session贿肩,卻生成了多個(gè)task。代理方法返回的數(shù)據(jù)可以根據(jù)task.taskIdentifier來(lái)區(qū)分是那個(gè)任務(wù)返回?cái)?shù)據(jù)了龄寞。之所以使用一個(gè)session汰规,http的底層其實(shí)也是通過(guò)TCP/IP完成的,只不過(guò)http是一問(wèn)一答物邑,回答以后就結(jié)束鏈接了溜哮,但是在建立鏈接和斷開(kāi)連接的時(shí)候需要三次握手、四次揮手色解,每次建立鏈接會(huì)消耗一定的內(nèi)存茂嗓。但是在使用NSURLSession以后,可以復(fù)用TCP鏈接科阎。這也是iOS9以后述吸,NSURLConnection背棄的原因之一吧。

- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
??????????????? uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
????????????? downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
???????????? completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
??? AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
??? delegate.manager = self;
??? delegate.completionHandler = completionHandler;

??? dataTask.taskDescription = self.taskDescriptionForSessionTasks;
??? [self setDelegate:delegate forTask:dataTask];

??? delegate.uploadProgressBlock = uploadProgressBlock;
??? delegate.downloadProgressBlock = downloadProgressBlock;
}

- (void)addDelegateForUploadTask:(NSURLSessionUploadTask *)uploadTask
??????????????????????? progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
?????????????? completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
??? AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
??? delegate.manager = self;
??? delegate.completionHandler = completionHandler;

??? uploadTask.taskDescription = self.taskDescriptionForSessionTasks;

??? [self setDelegate:delegate forTask:uploadTask];

??? delegate.uploadProgressBlock = uploadProgressBlock;
}

AFURLSessionManagerTaskDelegate這個(gè)就是重定向去處理回調(diào)數(shù)據(jù)的類锣笨。AFURLSessionManagerTaskDelegat里面會(huì)有很多對(duì) task屬性的KVO監(jiān)聽(tīng)蝌矛,以此來(lái)保證數(shù)據(jù)的實(shí)時(shí)性。當(dāng)task任務(wù)完成以后错英,通過(guò)block回調(diào)數(shù)據(jù)入撒,然后移除KVO.

暫時(shí)寫(xiě)到這里,大概就是一個(gè)流水賬椭岩,主要是自己加深印象茅逮,有問(wèn)題的請(qǐng)指出,覺(jué)得很雞肋的請(qǐng)略過(guò)判哥!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末氮唯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子姨伟,更是在濱河造成了極大的恐慌,老刑警劉巖豆励,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夺荒,死亡現(xiàn)場(chǎng)離奇詭異瞒渠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)技扼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)伍玖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人剿吻,你說(shuō)我怎么就攤上這事窍箍。” “怎么了丽旅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵椰棘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我榄笙,道長(zhǎng)邪狞,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任茅撞,我火速辦了婚禮帆卓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘米丘。我一直安慰自己剑令,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布拄查。 她就那樣靜靜地躺著吁津,像睡著了一般。 火紅的嫁衣襯著肌膚如雪靶累。 梳的紋絲不亂的頭發(fā)上腺毫,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音挣柬,去河邊找鬼潮酒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邪蛔,可吹牛的內(nèi)容都是我干的急黎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侧到,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼勃教!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起匠抗,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤故源,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后汞贸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绳军,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡印机,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了门驾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片射赛。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奶是,靈堂內(nèi)的尸體忽然破棺而出楣责,到底是詐尸還是另有隱情,我是刑警寧澤聂沙,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布秆麸,位于F島的核電站,受9級(jí)特大地震影響逐纬,放射性物質(zhì)發(fā)生泄漏蛔屹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧等龙,春花似錦、人聲如沸育叁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)豪嗽。三九已至,卻和暖如春豌骏,著一層夾襖步出監(jiān)牢的瞬間龟梦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工窃躲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留计贰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓蒂窒,卻偏偏與公主長(zhǎng)得像躁倒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洒琢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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