AFNetworking
AFNetworking 主要组成
AFNetworking除去Support Files
,可以看到AF
分为如下5
个功能模块:
NSURLSession : 网络通信模块,包含AFURLSessionManager
、AFHTTPSessionManger
Reachability : 网络状态监听模块,包含AFNetworkReachabilityManage
Security : 网络通信安全策略模块,包含 AFSecurityPolicy
Serialization : 网络通信信息序列化/反序列化模块,包括AFURLRequestSerialization
,AFURLResponesSerialization
UIKit : 对于iOS UIKit
库的扩展
其核心当然是网络通信模块NSURLSessionManager
。大家都知道,AF3.x
是基于NSURLSession
来封装的。所以这个类围绕着NSURLSession
做了一系列的封装。而其余的四个模块,均是为了配合网络通信或对已有UIKit
的一个扩展工具包。
AFNetworking请求流程分析
// 简单的get 请求
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]init];
[manager GET:@"http://localhost" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
初始化AFHTTPSessionManager 对象
// AFHTTPSessionManager相关的初始化方法
+ (instancetype)manager {
return [[[self class] alloc] initWithBaseURL:nil];
}
- (instancetype)init {
return [self initWithBaseURL:nil];
}
- (instancetype)initWithBaseURL:(NSURL *)url {
return [self initWithBaseURL:url sessionConfiguration:nil];
}
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
return [self initWithBaseURL:nil sessionConfiguration:configuration];
}
// 初始化实现
- (instancetype)initWithBaseURL:(NSURL *)url
sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
// 调用父类AFURLSessionManage 的初始化方法 initWithSessionConfiguration:
self = [super initWithSessionConfiguration:configuration];
if (!self) {
return nil;
}
//对传过来的BaseUrl进行处理,如果有值且最后不包含/,url加上"/"
if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
url = [url URLByAppendingPathComponent:@""];
}
self.baseURL = url;
// 生成请求序列化对象
self.requestSerializer = [AFHTTPRequestSerializer serializer];
// 生成响应序列化对象
self.responseSerializer = [AFJSONResponseSerializer serializer];
return self;
}
初始化最终都 - (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration
方法,
其实初始化方法都调用父类(AFURLSessionManager)的初始化方法。
除此之外,方法中把baseURL存了起来,还生成了一个请求序列对象和一个响应序列对象。
直接来到父类AFURLSessionManager
的初始化方法:
- (instancetype)init {
return [self initWithSessionConfiguration:nil];
}
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
// (1)初始化会话配置(session configuration),默认为defaultSessionConfiguration
if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.sessionConfiguration = configuration;
// (2)初始化队列,设置队列的最大并发数
self.operationQueue = [[NSOperationQueue alloc] init];
//queue并发线程数设置为1
self.operationQueue.maxConcurrentOperationCount = 1;
(3)初始化会话(session),并将session的代理对象设置为self(也就是当前AFURLSessionManager对象),并将代理队列设置为(2)中创建的队列。
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
//各种响应转码
self.responseSerializer = [AFJSONResponseSerializer serializer];
//设置默认安全策略
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
#if !TARGET_OS_WATCH
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif
// 设置存储NSURL task与AFURLSessionManagerTaskDelegate的词典(重点,在AFNet中,每一个task都会被匹配一个AFURLSessionManagerTaskDelegate 来做task的delegate事件处理) ===============
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
// 设置AFURLSessionManagerTaskDelegate 词典的锁,确保词典在多线程访问时的线程安全
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;
// 置空task关联的代理
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
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;
}
在该初始化方法中,它做了这么几件事:
(1)初始化会话配置(session configuration
),默认为defaultSessionConfiguration
(2)初始化队列,设置队列的最大并发数
(3)初始化会话(session
),并将session
的代理对象设置为self
(也就是当前AFURLSessionManager对象
),并将代理队列设置为(2)中创建的队列。
(4)初始化响应序列化
(5)初始化安全认证
(6)初始化网络状态监控
(7)初始化保存NSURLSessionDataTask
和AFURLSessionManagerTaskDelegate
的字典
(8)初始化线程锁
(9)为已经存在的task
设置delegate
,置空task关联的代理
// AFHTTPSessionManager 中 get 方法
- (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
{
//生成一个task
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
URLString:URLString
parameters:parameters
uploadProgress:nil
downloadProgress:downloadProgress
success:success
failure:failure];
//开始网络请求
[dataTask resume];
return dataTask;
}
方法走到类AFHTTPSessionManager
中来,调用父类,也就是我们整个AF3.x
的核心类AFURLSessionManager
的方法,生成了一个系统的NSURLSessionDataTask
实例,并且开始网络请求。
我们继续往父类里看,看看这个方法到底做了什么:
AFHTTPSessionManager
- (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;
//把参数,还有各种东西转化为一个request
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;
}
__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;
}
这个方法做了两件事:
- 用self.requestSerializer和各种参数去获取了NSMutableURLRequest请求实例。
- 调用另外一个方法dataTaskWithRequest去拿到我们最终需要的NSURLSessionDataTask实例,并且在完成的回调里,调用我们传过来的成功和失败的回调。
说到底AFHTTPSessionManager
中 这个方法还是没有做实事,我们继续到requestSerializer
方法里去看,看看AF
到底如何拼接成我们需要的request
的:
接着我们跑到AFURLRequestSerialization
类中:
// AFURLRequestSerialization
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
//断言,debug模式下,如果缺少改参数,crash
NSParameterAssert(method);
NSParameterAssert(URLString);
NSURL *url = [NSURL URLWithString:URLString];
NSParameterAssert(url);
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
mutableRequest.HTTPMethod = method;
//将request的各种属性循环遍历
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
//如果自己观察到的发生变化的属性,在这些方法里
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
//把给自己设置的属性给request设置
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
//将传入的parameters进行编码,并添加到request中
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
return mutableRequest;
}