AFN2.0 和3.0的區(qū)別和改動(dòng)
AFN2.0:
1.對(duì)NSURLSession的封裝
2.對(duì)AFURLConnection的封裝
3.對(duì)HTTPS網(wǎng)絡(luò)安全請(qǐng)求做了一個(gè)包裝
4.做了一個(gè)網(wǎng)絡(luò)連接管理的一個(gè)包裝,
AFN3.0:
1>添加進(jìn)度回調(diào)
2> 去掉所有AFURLConnection
AF的5個(gè)功能模塊:
- 網(wǎng)絡(luò)通信模塊(AFURLSessionManager、AFHTTPSessionManger)
- 網(wǎng)絡(luò)狀態(tài)監(jiān)聽模塊(Reachability)
- 網(wǎng)絡(luò)通信安全策略模塊(Security)
- 網(wǎng)絡(luò)通信信息序列化/反序列化模塊(Serialization)
- 對(duì)于iOS UIKit庫的擴(kuò)展(UIKit)
核心模塊:網(wǎng)絡(luò)通信模塊AFURLSessionManager
AF3.x是基于NSURLSession來封裝的。所以這個(gè)類圍繞著NSURLSession做了一系列的上層封裝。而其余的四個(gè)模塊,均是為了配合AFURLSessionManager類的網(wǎng)絡(luò)通信做一些必要的處理工作。結(jié)構(gòu)關(guān)系如下:

其中AFHTTPSessionManager是繼承于AFURLSessionManager的
我們一般做網(wǎng)絡(luò)請(qǐng)求都是用這個(gè)類,但是它本身是沒有做實(shí)事的,只是做了一些簡(jiǎn)單的封裝,把請(qǐng)求邏輯分發(fā)給父類AFURLSessionManager去做。
一.其中AFHTTPSessionManager做的事情是:
1.創(chuàng)建管理對(duì)象,封裝對(duì)外接口
2.在GET和POST方法中,調(diào)用父類方法把從父類獲取到的task ,resume
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);
}
}
}];
3.把傳過來的參數(shù),編碼成我們請(qǐng)求時(shí)需要的request,并且傳給父類去做網(wǎng)絡(luò)請(qǐng)求
做這個(gè)事情的代碼如下:
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
//斷言,debug模式下,如果缺少改參數(shù),crash
NSParameterAssert(method);
NSParameterAssert(URLString);
NSURL *url = [NSURL URLWithString:URLString];
NSParameterAssert(url);
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
mutableRequest.HTTPMethod = method;
//將request的各種屬性循環(huán)遍歷
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
//如果自己觀察到的發(fā)生變化的屬性,在這些方法里
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
//把給自己設(shè)置的屬性給request設(shè)置
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
//將傳入的parameters進(jìn)行編碼,并添加到request中
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
return mutableRequest;
}
在AFN中,每一個(gè)task都會(huì)被匹配一個(gè)AFURLSessionManagerTaskDelegate 來做task的delegate事件處理
二.AFURLSessionManager的初始化方法
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.sessionConfiguration = configuration;
self.operationQueue = [[NSOperationQueue alloc] init];
//queue并發(fā)線程數(shù)為1,這個(gè)是代理回調(diào)的queue
self.operationQueue.maxConcurrentOperationCount = 1;
//注意代理,代理的繼承,實(shí)際上NSURLSession去判斷了,你實(shí)現(xiàn)了哪個(gè)方法會(huì)去調(diào)用,包括子代理的方法!
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
//各種響應(yīng)轉(zhuǎn)碼
self.responseSerializer = [AFJSONResponseSerializer serializer];
//ssl證書,是驗(yàn)證證書,還是公鑰,還是不用
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
#if !TARGET_OS_WATCH
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif
// 設(shè)置存儲(chǔ)NSURL task與AFURLSessionManagerTaskDelegate的詞典(重點(diǎn),在AFNet中,每一個(gè)task都會(huì)被匹配一個(gè)AFURLSessionManagerTaskDelegate 來做task的delegate事件處理) ===============
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
// =============== 設(shè)置AFURLSessionManagerTaskDelegate 詞典的鎖,確保詞典在多線程訪問時(shí)的線程安全===============
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;
// =============== 為所管理的session的所有task設(shè)置完成塊,此方法為生成session之后就調(diào)用
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
//開始的時(shí)候應(yīng)該什么都沒有
for (NSURLSessionDataTask *task in dataTasks) {
[self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
}
for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
[self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
}
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
}
}];
return self;
}
其中兩個(gè)方法比較重要:
1. self.operationQueue.maxConcurrentOperationCount = 1;
2. [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
//置空處理
}];
其作用為:
- 第一是讓回調(diào)的代理queue是串行的,即請(qǐng)求完成的task只能一個(gè)個(gè)被回調(diào)。
- 第二是清空了session中所有task。
其目的:
第一個(gè):
第二個(gè):我們知道這里是初始化方法,按理說session中不會(huì)有任何task。但是我們有一種后臺(tái)session,當(dāng)從后臺(tái)回來的時(shí)候,根據(jù)一個(gè)ID,就可以重新恢復(fù)這個(gè)session,這時(shí)候其中就會(huì)有之前未完成的task了。
所以:
而這里這么做的目的就是防止一些之前的后臺(tái)請(qǐng)求任務(wù),導(dǎo)致程序的crash
接著是dataTaskWithRequest方法:
- (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;
//第一件事,創(chuàng)建NSURLSessionDataTask,里面適配了Ios8以下taskIdentifiers,函數(shù)創(chuàng)建task對(duì)象。
//其實(shí)現(xiàn)應(yīng)該是因?yàn)閕OS 8.0以下版本中會(huì)并發(fā)地創(chuàng)建多個(gè)task對(duì)象,而同步有沒有做好,導(dǎo)致taskIdentifiers 不唯一…這邊做了一個(gè)串行處理
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
這里所做的有兩件事:
1.調(diào)用session的方法,傳request過去去生成task。
- 給每個(gè)task創(chuàng)建并對(duì)應(yīng)一個(gè)AF的代理對(duì)象,這基本上是這個(gè)類的核心所在了,這個(gè)代理對(duì)象為其對(duì)應(yīng)的task做數(shù)據(jù)拼接及成功回調(diào)。
正如上面所說,AFN中每一個(gè)task都會(huì)被對(duì)應(yīng)生成一個(gè)delegate并與之匹配,其所有核心方法都為代理調(diào)用
- (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];
// AFURLSessionManagerTaskDelegate與AFURLSessionManager建立相互關(guān)系
delegate.manager = self;
delegate.completionHandler = completionHandler;
//這個(gè)taskDescriptionForSessionTasks用來發(fā)送開始和掛起通知的時(shí)候會(huì)用到,就是用這個(gè)值來Post通知,來兩者對(duì)應(yīng)
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
// ***** 將AF delegate對(duì)象與 dataTask建立關(guān)系
[self setDelegate:delegate forTask:dataTask];
// 設(shè)置AF delegate的上傳進(jìn)度,下載進(jìn)度塊。
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
//斷言,如果沒有這個(gè)參數(shù),debug下crash在這
NSParameterAssert(task);
NSParameterAssert(delegate);
//加鎖保證字典線程安全
[self.lock lock];
// 將AF delegate放入以taskIdentifier標(biāo)記的詞典中(同一個(gè)NSURLSession中的taskIdentifier是唯一的)
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
// 為AF delegate 設(shè)置task 的progress監(jiān)聽
[delegate setupProgressForTask:task];
//添加task開始和暫停的通知
[self addNotificationObserverForTask:task];
[self.lock unlock];
}
就這么兩個(gè)方法創(chuàng)建了一個(gè)AFURLSessionManagerTaskDelegate的代理,把這個(gè)代理和task的taskIdentifier一一對(duì)應(yīng),放在我們最早初始化(initWithSessionConfiguration方法中創(chuàng)建的mutableTaskDelegatesKeyedByTaskIdentifier)的字典里,建立起映射。
這里所做的還包括對(duì)task進(jìn)度的監(jiān)聽和掛起與重新開始的通知。
做完以上操作后,在AFHTTPSessionManager中調(diào)用resume方法
[dataTask resume];
其中主要的三個(gè)代理有:
1.完成的代理
2.收到數(shù)據(jù)的代理
3.以及下載完成的代理
AFN中還為每個(gè)代理方法,聲明了對(duì)應(yīng)的屬性Block,我們可以利用這些Block,做一些自定義的處理,Block會(huì)隨著代理調(diào)用而被調(diào)用,這些代理幫我們做了一些類似數(shù)據(jù)分片、斷電續(xù)傳、https認(rèn)證等工作
以其中一個(gè)為例:
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
//根據(jù)task去取我們一開始創(chuàng)建綁定的delegate
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// delegate may be nil when completing a task in the background
if (delegate) {
//把代理轉(zhuǎn)發(fā)給我們綁定的delegate
[delegate URLSession:session task:task didCompleteWithError:error];
//轉(zhuǎn)發(fā)完移除delegate
[self removeDelegateForTask:task];
}
//公用Block回調(diào)
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
其中的代理調(diào)用的方法實(shí)現(xiàn)如下:
//AF實(shí)現(xiàn)的代理!被從urlsession那轉(zhuǎn)發(fā)到這
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
//1)強(qiáng)引用self.manager,防止被提前釋放;因?yàn)閟elf.manager聲明為weak,類似Block
__strong AFURLSessionManager *manager = self.manager;
__block id responseObject = nil;
//用來存儲(chǔ)一些相關(guān)信息,來發(fā)送通知用的
__block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
//存儲(chǔ)responseSerializer響應(yīng)解析對(duì)象
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
//Performance Improvement from #2672
//注意這行代碼的用法,感覺寫的很Nice...把請(qǐng)求到的數(shù)據(jù)data傳出去,然后就不要這個(gè)值了釋放內(nèi)存
NSData *data = nil;
if (self.mutableData) {
data = [self.mutableData copy];
//We no longer need the reference, so nil it out to gain back some memory.
self.mutableData = nil;
}
//繼續(xù)給userinfo填數(shù)據(jù)
if (self.downloadFileURL) {
userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
} else if (data) {
userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
}
//錯(cuò)誤處理
if (error) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
//可以自己自定義完成組 和自定義完成queue,完成回調(diào)
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, error);
}
//主線程中發(fā)送完成通知
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
} else {
//url_session_manager_processing_queue AF的并行隊(duì)列
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
//解析數(shù)據(jù)
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
//如果是下載文件,那么responseObject為下載的路徑
if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
}
//寫入userInfo
if (responseObject) {
userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
}
//如果解析錯(cuò)誤
if (serializationError) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
}
//回調(diào)結(jié)果
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, serializationError);
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
});
}
#pragma clang diagnostic pop
}