一、AFN架構(gòu)的最上層是AFHTTPSessionManager
AFHTTPSessionManager繼承于AFURLSessionManager抒钱,它所做的主要工作是收集HTTP請(qǐng)求的URL翘魄、Parameters鼎天、成功的回調(diào)、失敗的回調(diào)四個(gè)參數(shù)暑竟。然后自己的屬性requestSerializer根據(jù)前兩個(gè)參數(shù)URL和Parameter生成一個(gè)NSMutableURLRequest類的對(duì)象斋射。然后把它交個(gè)父類處理,父類會(huì)返回一個(gè)NSURLSessionDataTask類的對(duì)象task光羞,然后調(diào)用[task resume]
發(fā)起請(qǐng)求绩鸣。
該過(guò)程對(duì)應(yīng)的源碼:
// AFHTTPSessionManager就是拿到這個(gè)方法產(chǎn)生的對(duì)象發(fā)起請(qǐng)求的
- (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;
// #1:URL&Parameters --> [requestSerializer] --> Request
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
if (serializationError) {
if (failure) {
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
}
return nil;
}
__block NSURLSessionDataTask *dataTask = nil;
// #2:Request --> [AFURLSessionManager.session] --> DataTask
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;
}
二、AFN架構(gòu)的核心類AFURLSessionManager
AFURLSessionManager就像一個(gè)“工廠”纱兑,NSURLSessionDelegate一系列代理方法就是“流水線”呀闻,task是“原料”,responseObject是產(chǎn)出的“產(chǎn)品”潜慎。#2這一流程就是由AFURLSessionManager完成的捡多。
它的核心屬性有
- sessionConfiguration:會(huì)話對(duì)象的配置信息類,默認(rèn)使用的是default模式铐炫;
- session:會(huì)話對(duì)象垒手,用于產(chǎn)生任務(wù)對(duì)象task;
- operationQueue:創(chuàng)建session會(huì)話對(duì)象的指定的隊(duì)列倒信,這是一個(gè)串行隊(duì)列(最大并發(fā)數(shù)是1)科贬;
- responseSerializer:返回對(duì)象的序列化,主要負(fù)責(zé)狀態(tài)判斷、解析等任務(wù)榜掌;
- 四個(gè)xxxTasks數(shù)組:只讀屬性优妙,存放的是請(qǐng)求任務(wù);
- mutableTaskDelegatesKeyedByTaskIdentifier:以鍵值對(duì)的形式向task關(guān)聯(lián)一些回調(diào)函數(shù)憎账,key是taskIdentifier套硼,value是回調(diào)組成的AFURLSessionManagerTaskDelegate類的對(duì)象;
- reachabilityManager:監(jiān)管網(wǎng)絡(luò)狀態(tài)的對(duì)象胞皱;
- completionQueue:請(qǐng)求并解析完成后將在該隊(duì)列中交付數(shù)據(jù)(調(diào)用請(qǐng)求的completionHandler)邪意,默認(rèn)是主串行隊(duì)列;
- completionGroup:交付數(shù)據(jù)(調(diào)用請(qǐng)求的completionHandler)時(shí)指定的任務(wù)組反砌,AFN默認(rèn)是一個(gè)靜態(tài)的
dispatch_group_t
雾鬼。該分組允許用戶創(chuàng)建task1、task2...于颖,當(dāng)他們都完成時(shí)通過(guò)dispatch_group_notify()
再進(jìn)行后續(xù)操作呆贿。
創(chuàng)建的靜態(tài)對(duì)象有:
-
af_url_session_manager_creation_queue
:串行隊(duì)列,將session創(chuàng)建task的任務(wù)交付到該隊(duì)列森渐;注:此隊(duì)列是修復(fù)在iOS8.0之前并行創(chuàng)建task時(shí)得到的taskIdentifier異常的情況做入,iOS8.0系統(tǒng)已經(jīng)修復(fù)了該bug。
-
af_url_session_manager_processing_queue
:專門(mén)對(duì)返回?cái)?shù)據(jù)進(jìn)行解析的隊(duì)列同衣。這是一個(gè)并行隊(duì)列竟块,能夠更高效的完成數(shù)據(jù)解析任務(wù); -
af_url_session_manager_completion_group
:將completionHandler歸為該任務(wù)組耐齐,上述9中默認(rèn)的靜態(tài)任務(wù)組就是它浪秘。
#2流程細(xì)分:
step_1
:創(chuàng)建會(huì)話session,將會(huì)話的代理指定為自己(AFURLSessionManager有相當(dāng)一部分代碼是session對(duì)象的代理方法)埠况,創(chuàng)建串行隊(duì)列耸携,指定session回調(diào)在該隊(duì)列中處理;
step_2
:根據(jù)Request創(chuàng)建任務(wù)task辕翰,同時(shí)創(chuàng)建AFURLSessionManagerTaskDelegate類的對(duì)象(它和task一一對(duì)應(yīng))夺衍。這個(gè)對(duì)象包含了Request對(duì)應(yīng)的回調(diào)方法,它還有一個(gè)重要的任務(wù)就是存儲(chǔ)和拼接服務(wù)器返回的數(shù)據(jù)喜命,保存在mutableData中沟沙;
step_3
:根據(jù)task的標(biāo)識(shí)taskIdentifier存儲(chǔ)step_2
產(chǎn)生的對(duì)象,保存在字典中壁榕;
step_4
:當(dāng)請(qǐng)求任務(wù)發(fā)起后矛紫,會(huì)有觸發(fā)session的一系列代理方法,其中就附帶了標(biāo)識(shí)是哪個(gè)task的信息牌里。當(dāng)請(qǐng)求返回?cái)?shù)據(jù)時(shí)根據(jù)task的taskIdentifier在step_3
產(chǎn)生的字典中找到對(duì)應(yīng)的代理颊咬,讓代理拼接數(shù)據(jù);
step_5
:當(dāng)請(qǐng)求完成時(shí)讓任務(wù)的代理根據(jù)session的responseSerializer完成數(shù)據(jù)解析任務(wù)(該代理有一個(gè)對(duì)創(chuàng)建任務(wù)的會(huì)話的弱引用);
step_6
:執(zhí)行completionHandler向外拋出數(shù)據(jù)贪染。
核心代碼:
- (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;
//step_2:生成task
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
//step_3:生成task關(guān)聯(lián)的對(duì)象缓呛,將upload/downloadProgressBlock、completionHandler讓關(guān)聯(lián)對(duì)象管理
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
- (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;//反向的弱引用杭隙,指向存儲(chǔ)自己的類
delegate.completionHandler = completionHandler;
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
[self setDelegate:delegate forTask:dataTask];//用字典構(gòu)建dataTask與delegate的對(duì)應(yīng)關(guān)系
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
step_1
在NSURLSessionManager對(duì)象的初始化中完成。step_4
是一個(gè)“循環(huán)”因妙,不斷的產(chǎn)生數(shù)據(jù)痰憎,它以及step_5
、step_6
下文有詳細(xì)描述攀涵。
三铣耘、NSURLSessionDelegate方法的執(zhí)行以及后續(xù)任務(wù)的輪轉(zhuǎn)
接收數(shù)據(jù)的代理方法
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data {
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
[delegate URLSession:session dataTask:dataTask didReceiveData:data];
if (self.dataTaskDidReceiveData) {
self.dataTaskDidReceiveData(session, dataTask, data);
}
}
[self delegateForTask:dataTask]
就是根據(jù)dataTask的任務(wù)標(biāo)識(shí)找到與它對(duì)用的代理對(duì)象,代理對(duì)象將data拼接到mutableData中保存以故。
請(qǐng)求完成時(shí)的代理方法
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
if (delegate) {
[delegate URLSession:session task:task didCompleteWithError:error];
[self removeDelegateForTask:task];
}
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
請(qǐng)求完成后task的代理會(huì)對(duì)mutableData做異步的解析操作蜗细,[self removeDelegateForTask:task]
會(huì)移除與代理的一切通知,然后從字典中移除怒详。
四炉媒、數(shù)據(jù)的解析和交付responseObject
先從源碼看起:
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
__strong AFURLSessionManager *manager = self.manager;
__block id responseObject = nil;
NSData *data = nil;
if (self.mutableData) {
data = [self.mutableData copy];//將NSMutableData拷貝以備解析之用
self.mutableData = nil;//釋放內(nèi)存空間
}
/* 構(gòu)建通知的userInfo */
if (!error) {
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
/* 構(gòu)建通知的userInfo */
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{// 交付數(shù)據(jù)
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, serializationError);
}
dispatch_async(dispatch_get_main_queue(), ^{//發(fā)通知
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
});
}
}
貼出的源碼刪去了構(gòu)建通知userInfo和請(qǐng)求異常分支的處理流程(比成功時(shí)少了一個(gè)解析操作)。第一個(gè)dispatch_async()
包含了解析操作昆烁,解析完成后在主串行隊(duì)列(解析完成后吊骤,用戶拿到數(shù)據(jù)一般就要顯示了)執(zhí)行block把數(shù)據(jù)交付出去,然后在主隊(duì)列發(fā)出任務(wù)完成的通知静尼,通知的userInfo信息中AFNetworkingTaskDidCompleteSerializedResponseKey對(duì)應(yīng)也是解析后的數(shù)據(jù)白粉。
五、其他
5.1 關(guān)于AFURLSessionManagerTaskDelegate
它是NSURLSessionManager中的一個(gè)私有類鼠渺,里面有兩個(gè)關(guān)于上傳和下載進(jìn)度的屬性:uploadProgress鸭巴、downloadProgress,它通過(guò)把自己添加為對(duì)用task的觀察者來(lái)實(shí)現(xiàn)自己的progress的值改變拦盹。
[task addObserver:self//自己(taskDelegate)將觀察task的countOfBytesSent屬性的變化情況
forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))
options:NSKeyValueObservingOptionNew
context:NULL];
[self.uploadProgress addObserver:self//自己觀察 進(jìn)度(Progress)的“完成比例屬性”的變化情況
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionNew
context:NULL];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
// 當(dāng)被觀察對(duì)象是任務(wù)時(shí)鹃祖,更新自己的progress值
if ([object isKindOfClass:[NSURLSessionTask class]] || [object isKindOfClass:[NSURLSessionDownloadTask class]]) {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) {
self.uploadProgress.completedUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
}
} else //當(dāng)被觀察對(duì)象是自己的progress時(shí),執(zhí)行上傳下載的進(jìn)度有更新的代理掌敬,并發(fā)進(jìn)度以NSProgress對(duì)象的方式傳遞出去
if ([object isEqual:self.downloadProgress]) {
if (self.downloadProgressBlock) {
self.downloadProgressBlock(object);
}
}
}
新數(shù)據(jù)下載/上傳 --> task的屬性發(fā)生變化 --> taskDelegate的progress同步該變化 --> progress的完成百分比就發(fā)生變化 --> taskDelegate發(fā)出通知
5.2 關(guān)系梳理:NSURLSessionManager惯豆、NSURLSession、AFURLSessionManagerTaskDelegate奔害、NSURLSessionTask
持有1:屬性持有楷兽;
持有2:通過(guò)集合屬性持有;
持有3:雖然NSURLSession的.h文件沒(méi)有給出存儲(chǔ)它創(chuàng)建的task的集合屬性华临,但有理由相信它也是采用持有2的形式存儲(chǔ)的芯杀。
代理1:通過(guò)直接設(shè)置代理對(duì)象的方式實(shí)現(xiàn);
代理2:通過(guò)key-value的方式建立聯(lián)系,然后task有一些任務(wù)(數(shù)據(jù)拼接揭厚、進(jìn)度管理)要處理的時(shí)候通過(guò)該聯(lián)系找打taskDelegate却特,讓它負(fù)責(zé)完成。
5.3獲取Session創(chuàng)建的Task
方法:
- (void)getTasksWithCompletionHandler:(void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler
筛圆,這是一個(gè)異步的方法裂明,通過(guò)在Session的代理隊(duì)列中執(zhí)行回調(diào)的方式交付處理的結(jié)果。3個(gè)數(shù)組中包含的是有效的(未開(kāi)始和進(jìn)行中)task太援。大膽猜測(cè)一下它的實(shí)現(xiàn):
- (void)getTasksWithCompletionHandler:(void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler {
dispatch_barrier_async(self.workQueue, ^{
NSMutableArray *dataTasks = [NSMutableArray array];
NSMutableArray *uploadTasks = [NSMutableArray array];
NSMutableArray *downloadTasks = [NSMutableArray array];
for (NSURLSessionTask *task in self.allTasks) {
if (task.state == NSURLSessionTaskStateRunning || task.state == NSURLSessionTaskStateSuspended) {
if ([task isKindOfClass:[NSURLSessionDataTask class]]) {
[dataTasks addObject:task];
} else if ([task isKindOfClass:[NSURLSessionUploadTask class]]) {
[uploadTasks addObject:task];
} else if ([task isKindOfClass:[NSURLSessionDownloadTask class]]) {
[downloadTasks addObject:task];
}
}
}
dispatch_async(self.delegateQueue, ^{
if (completionHandler) {
completionHandler(dataTasks, uploadTasks, downloadTasks);
}
})
})
}
當(dāng)用戶通過(guò)屬性獲取task的時(shí)候闽晦,NSURLSessionManager用了一個(gè)信號(hào)量,等待該異步操作操作的完成提岔,然后返回給用戶仙蛉。
- (NSArray *)tasksForKeyPath:(NSString *)keyPath {
__block NSArray *tasks = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//令牌數(shù)為0
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) {
tasks = dataTasks;
}/* 刪減了其他分支 */
dispatch_semaphore_signal(semaphore);//放入一個(gè)令牌
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//令牌>0時(shí)向下執(zhí)行,否者等待
return tasks;
}
六碱蒙、總結(jié)
AFNetworking框架UIKit模塊提供了View層的擴(kuò)展荠瘪,方便使用。Serialization模塊負(fù)責(zé)請(qǐng)求和返回?cái)?shù)據(jù)的序列化赛惩,Security模塊負(fù)責(zé)網(wǎng)絡(luò)安全哀墓,Reachability模塊負(fù)責(zé)網(wǎng)絡(luò)環(huán)境監(jiān)測(cè),NSURLSession模塊將其他模塊有機(jī)的組織在一起協(xié)同工作坊秸。