概述
AFNetworking3.x 其實(shí)是對 NSUrlSession 的封裝;
-
AFNetworking 總共分為 5 個(gè)模塊:
- 通信模塊 AFHTTPSessionManager, AFURLSessionManager ;
- 網(wǎng)絡(luò)檢測模塊 AFNetworkReachabilityManager ;
- 網(wǎng)絡(luò)安全https模塊 AFSecurityPolicy ;
- 序列化和反序列化模塊 Serialization ;
- ui組件封裝模塊 ;
AFHTTPSessionManager *manage = [[AFHTTPSessionManager alloc] init];
[manage GET:@"http://www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
解析通信模塊
AFHTTPSessionManager 是 AFURLSessionManager 子類,提供給外界使用的網(wǎng)路請求類;
AFHTTPSessionManager在初始化時(shí), 設(shè)置了默認(rèn)的序列對象為AFHTTPRequestSerializer,反序列化對象為AFJSONResponseSerializer,并且調(diào)用父類的初始化方法;
在父類的初始化方法中,創(chuàng)建了一個(gè)隊(duì)列,并發(fā)量為 1,是為了保證請求在回調(diào)時(shí),串行執(zhí)行,防止數(shù)據(jù)錯(cuò)落;但為何不設(shè)置并發(fā)量為n,然后回調(diào)時(shí)用NSLock來防止數(shù)據(jù)錯(cuò)亂問題呢?
使用NSLock來鎖住、解鎖,會增加等待加鎖和解鎖時(shí)間,并且開銷額外的線程開支,所以使用并發(fā)量為1,解決這個(gè)問題;
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.sessionConfiguration = configuration;
// 定義一個(gè)并發(fā)量為1 的隊(duì)列, 用來保證響應(yīng)數(shù)據(jù)的回調(diào)是串行的,但是數(shù)據(jù)解析還是并發(fā)執(zhí)行的
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
self.responseSerializer = [AFJSONResponseSerializer serializer];
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
雖然請求的回調(diào)是串行回調(diào),但是請求完成后的數(shù)據(jù)解析是并發(fā)解析的,后續(xù)會分析...
- 進(jìn)入AFHTTPSessionManager的GET 或 POST方法內(nèi)部,可以看到內(nèi)部是返回一個(gè) NSURLSessionDataTask 對象,并且直接開始請求 resume ;
- (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;
}
- dataTaskWithHTTPMethod 方法首先會創(chuàng)建一個(gè) NSMutableURLRequest 的對象, 并對傳進(jìn)來的參數(shù)進(jìn)行合成,如get方法將參數(shù)放置于url,post將參數(shù)放置在請求體;其次會創(chuàng)建一個(gè) NSURLSessionDataTask 對象,并返回;
- (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
{
// 1. 生成NSMutableURLRequest, 對參數(shù)進(jìn)行合成
NSError *serializationError = nil;
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
if (serializationError) {
if (failure) {
// 有錯(cuò)誤就返回自定義的隊(duì)列回調(diào), 如果沒有自定的隊(duì)列就主隊(duì)列回調(diào)
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
}
return nil;
}
// 2. 生成NSURLSessionDataTask任務(wù)對象, 并返回
__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;
}
- 進(jìn)入 requestWithMethod 看內(nèi)部如何實(shí)現(xiàn),可以看出在該方法中創(chuàng)建了 NSMutableURLRequest 對象,然后遍歷 mutableObservedChangedKeyPaths 集合,該集合是存放了外界自定義的一些屬性,比如超時(shí)時(shí)間等,然后根據(jù)外界傳輸?shù)恼埱髷?shù)據(jù)格式,調(diào)用不同的代理方法,生成不一樣的Request對象;
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSParameterAssert(method);
NSParameterAssert(URLString);
NSURL *url = [NSURL URLWithString:URLString];
NSParameterAssert(url);
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
mutableRequest.HTTPMethod = method;
// 將用戶自定義的屬性放到mutableRequest,比如超時(shí)時(shí)間,是否允許蜂窩網(wǎng)絡(luò)請求等
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
// 生成NSMutableURLRequest,下面這個(gè)方法是代理方法,每個(gè)請求的數(shù)據(jù)格式不一樣,所以看子類的繼承 Content-Type , NSDate 會不一樣
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
return mutableRequest;
}
- 介紹完如何NSMutableURLRequest的創(chuàng)建,來看看 NSURLSessionDataTask 的創(chuàng)建做了哪些事,進(jìn)入dataTaskWithRequest方法內(nèi)部;
- 可以看到首先創(chuàng)建了NSURLSessionDataTask對象,但是由于iOS8.0以下版本由于并發(fā)創(chuàng)建NSURLSessionDataTask會導(dǎo)致taskId不唯一,所以在iOS8.0以下,需要在 同步串行隊(duì)列 中創(chuàng)建;
- 然后調(diào)用 addDelegateForDataTask 創(chuàng)建代理對象;
- 該代理對象主要作用是用來 解偶 AFURLSessionManager對象的,將回調(diào),數(shù)據(jù)解析等都放置到代理對象中;
- 可以看到manage = self ,是對應(yīng)AFURLSessionManager對象的,然后將代理對象存放著在 mutableTaskDelegatesKeyedByTaskIdentifier 字典中,self.mutableTaskDelegatesKeyedByTaskIdentifier[@(taskIdentifier)] = delegate;
- (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 {
// 1. 安全創(chuàng)建NSURLSessionDataTask對象
// 1.1 因?yàn)閕OS8.0之前的系統(tǒng),不能保證在并發(fā)線程中taskId唯一,所以用同步、串行隊(duì)列進(jìn)行創(chuàng)建
__block NSURLSessionDataTask *dataTask = nil;
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
// 2. 創(chuàng)建代理對象,用來處理請求完成回調(diào)
[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] initWithTask:dataTask];
delegate.manager = self;
delegate.completionHandler = completionHandler;
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
[self setDelegate:delegate forTask:dataTask];
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
- 然后介紹請求回調(diào),可以看到AFURLSessionManager中的請求回調(diào),都是將數(shù)據(jù)轉(zhuǎn)發(fā)給 AFURLSessionManagerTaskDelegate 代理,然后讓這個(gè)代理進(jìn)行回調(diào)給外界;
- (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);
}
}
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
// 1. 請求完成后,回調(diào)到AFURLSessionManagerTaskDelegate中,進(jìn)行數(shù)據(jù)處理后,將數(shù)據(jù)回調(diào)到最初的get回調(diào)(用戶)
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// delegate may be nil when completing a task in the background
if (delegate) {
[delegate URLSession:session task:task didCompleteWithError:error];
// 1.1 請求完成后,需要移除delegate
[self removeDelegateForTask:task];
}
// 2. 用戶自定義的回調(diào)
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
- 轉(zhuǎn)到 AFURLSessionManagerTaskDelegate 代理方法中,可以看到初始化了一個(gè)字典,存放解析的數(shù)據(jù),回調(diào)有 block 和 通知 兩種;響應(yīng)數(shù)據(jù)的解析放在 異步并發(fā)隊(duì)列 中執(zhí)行,然后以block和通知方式回調(diào)給外界使用,整個(gè)請求過程結(jié)束,然后移除delegate對象;
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
// 1. 合成userInfo 的通知信息
__strong AFURLSessionManager *manager = self.manager;
__block id responseObject = nil;
__block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
//Performance Improvement from #2672
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;
}
if (self.downloadFileURL) {
userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
} else if (data) {
userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
}
if (error) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
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);
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
} else {
// 2. 并發(fā)解析數(shù)據(jù)
dispatch_async(url_session_manager_processing_queue(), ^{
// 3. 使用代理方法, 解析響應(yīng)的數(shù)據(jù)
NSError *serializationError = nil;
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
}
if (responseObject) {
userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
}
if (serializationError) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
}
// 4. 回調(diào)給用戶解析后的數(shù)據(jù), 整個(gè)請求結(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];
});
});
});
}
}
上述只是通信模塊的分析,其余模塊后續(xù)補(bǔ)上。。。。。