源码分析一共分为三个部分:
- 介绍 AFNetworking 发起网络请求的主流程;
- 介绍 AFNetworking 网络安全、网络状态及其他类实现细节;
- 介绍 AFNetworking 中涉及到的分类;
源码解析之AFNetworking3.x(一)
源码解析之AFNetworking3.x(二)
源码解析之AFNetworking3.x(三)
本文主要分析利用 AFNetworking 发请网络请求的主流程,主要内容包括:
- 概述
- AFHTTPSessionManager 初始化
- NSURLRequest 的创建
- NSURLSessionDataTask 的创建
- 请求回调的处理
1. 概述
AFNetworking 框架基于 NSURLSession,如果对 NSURLSession 不太熟悉,戳这里。先祭出 AFNetworking 的结构图。
从图中可以看出,业务层通过AFHTTPSessionManager
发起网络请求,AFURLSessionManager
封装网络请求的核心功能,包括NSURLSession
和请求代理的处理。请求参数序列化、响应数据序列化、网络安全验证和网络状态的监控分别通过类进行功能的封装。
分析 AFNetworking 前,先回顾下 NSURLSession 发起网络请求的流程:
- 创建
NSURLRequest
; - 处理请求参数和 HTTPHeader;
- 创建
NSURLSession
; - 通过
NSURLSession
创建NSURLSessionTask
; - 启动
NSURLSessionTask
; - 设置网络回调,处理 respone 信息;
AFNetworking 对 NSURLSession 封装后,请求流程相对简单很多。如下述代码所示,主要工作变成了创建AFHTTPSessionManager
,调用相关方法发送网络请求,并设置请求参数、请求成功/失败的回调。
NSURL *url = [[NSURL alloc] initWithString:@"www.baidu.com"];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
[manager GET:@"test.json" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@" ,responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@", error);
}];
接下来本文会依照网络请求的发起到接收流程,分析 AFNetworking 的处理过程。
2. AFHTTPSessionManager 初始化
AFHTTPSessionManager
继承自AFURLSessionManager
,AFURLSessionManager
封装了NSURLSession
的基础功能,而 AFHTTPSessionManager
则实现了 HTTP 请求相关的配置。我们从 AFHTTPSessionManager
的头文件可以看出,其主要定义了各种网络请求方法。
AFHTTPSessionManager
所有的初始化方法最终都会调到initWithBaseURL: sessionConfiguration:
。该方法首先调用父类进行初始化,接着处理 url,最后初始化requestSerializer
和responseSerializer
。
细心的同学可能注意到,子类和父类都有self.responseSerializer = [AFJSONResponseSerializer serializer];
,实现的功能相同,为什么子类还要初始化一次呢。我想这得从框架结构的角度来分析,子类不能依赖父类responseSerializer
的初始化。因为AFURLSessionManager
作为父类,提供的是通用功能,目前仅有一个子类。但如果后期有多个子类呢,父类中的responseSerializer
可能会采用不同的方式实现,这也是为什么子类和父类中responseSerializer
类型不同的原因。父类的responseSerializer
是实现了AFURLResponseSerialization
接口的 id 类型,而父类是实现了AFURLResponseSerialization
接口的AFHTTPResponseSerializer
类型。
- (instancetype)initWithBaseURL:(NSURL *)url
sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
self = [super initWithSessionConfiguration:configuration];
if (!self) {
return nil;
}
// 保证 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;
}
父类初始化方法处理的内容则相对较多:包括NSURLSession
、响应queue
、 responseSerializer
、 securityPolicy
的初始化。其中较重要的是响应queue
的处理和getTasksWithCompletionHandler:
的调用。
通常情况下 AFNetworking 接口的调用包括resume
方法的调用都在主线程中。这里NSURLSession
代理回调线程的最大并发数为 1,是为了使代理方法回调都在一个串行队列中,只有这样才能保证代理方法的回调顺序。因为NSURLSession
代理方法回调是异步的,所以这里采用了“异步+串行队列”方式处理。
getTasksWithCompletionHandler:
用于异步获取 session 中所有未完成的 task,按理说在初始化中调用这个方法应该不会有 task,但存在这个 issue。所以这里的处理是为了防止 app 从后台回来重新初始化 session 时,一些之前的后台请求导致的 crash。
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
...
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1; // 最大并发数为1
...
[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];
}
}];
...
}
3. NSURLRequest 的创建
AFHTTPSessionManager
初始化完成后,会调用各种网络请求方法发起请求:
- GET:parameters:success:failure:
- GET:parameters:progress:success:failure:
- HEAD:parameters:success:failure:
- POST:parameters:success:failure:
- POST:parameters:progress:success:failure:
- POST:parameters:constructingBodyWithBlock:success:failure:
- POST:parameters:constructingBodyWithBlock:progress:success:failure:
- PUT:parameters:success:failure:
- PATCH:parameters:success:failure:
- DELETE:parameters:success:failure:
这里所有的网络请求,最终会落到这两个方法上:
- dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:
- POST:parameters:constructingBodyWithBlock:progress:success:failure:
拆分为两个方式是因为在数据上传时,可以采用表单拼接的方式,这种方式与通用的网络请求有所差异,所以需要剥离出来。
我们先看第一个方法,该方法完成了两件事情:创建NSURLRequest
、 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
{
// 通过 requestSerializer 创建 NSMutableURLRequest
NSError *serializationError = nil;
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
...
// 创建 task
__block NSURLSessionDataTask *dataTask = nil;
dataTask = [self dataTaskWithRequest:request
uploadProgress:uploadProgress
downloadProgress:downloadProgress
completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
...
}];
return dataTask;
}
NSURLRequest
的创建是由AFHTTPRequestSerializer
完成,其继承体系:
最上层的AFURLRequestSerialization
为接口,定义的是序列化对象中最重要的用于创建NSURLRequest
的方法。基于该协议,AFNetworking 提供了 3 种不同数据形式的序列化类。
-
AFHTTPRequestSerializer
: 定义了一些通用方法,参数格式是通用的字典、数组等。实际上我们在进行网络请求时,参数都会封装在字典中,所以该类使用的最多。 -
AFJSONRequestSerializer
: 参数格式是 json; -
AFPropertyListRequestSerializer
: 参数格式是 plist;
AFHTTPRequestSerializer
初始化方法完成了请求头 User-Agent 的配置。同时AFHTTPRequestSerializer
中定义了一些NSURLRequest
属性,并对这些属性设置了 KVO,当对属性进行修改时,会记录哪些属性修改过,并在创建NSURLRequest
时统一设置到NSURLRequest
中,其中主要包括请求配置属性。
- (instancetype)init {
...
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
}
}
...
}
// 需要进行监听的属性,这些属性都设置到 NSURLRequest 中去
static NSArray * AFHTTPRequestSerializerObservedKeyPaths() {
static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_AFHTTPRequestSerializerObservedKeyPaths = @[
NSStringFromSelector(@selector(allowsCellularAccess)),
NSStringFromSelector(@selector(cachePolicy)),
NSStringFromSelector(@selector(HTTPShouldHandleCookies)),
NSStringFromSelector(@selector(HTTPShouldUsePipelining)),
NSStringFromSelector(@selector(networkServiceType)),
NSStringFromSelector(@selector(timeoutInterval))];
});
return _AFHTTPRequestSerializerObservedKeyPaths;
}
创建NSURLRequest
的重要函数是requestWithMethod:URLString:parameters:error:
,它完成了NSURLRequest
的创建、NSURLRequest
相关属性设置、HTTP Method 和 HTTP Header 的设置、参数序列化等工作。
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSURL *url = [NSURL URLWithString:URLString];
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
// 设置请求方法
mutableRequest.HTTPMethod = method;
// 设置AFHTTPRequestSerializer对象修改过的属性
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
// 完成参数序列化,并设置到 mutableRequest 中
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
return mutableRequest;
}
requestBySerializingRequest:withParameters:error:
首先为请求设置部分请求头信息,包括 User-Agent 和 Authorization,接着完成请求中 query 部分的参数拼接,最后判断当前请求是否是默认设置的 GET、HEAD、DELETE,如果是则将 query 部分添加到请求 url 上,否则放在请求 body 中。
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
// User-Agent 和 Authorization 设置
NSMutableURLRequest *mutableRequest = [request mutableCopy];
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
...
if (self.queryStringSerialization) {
// 自定义参数拼接
query = self.queryStringSerialization(request, parameters, &serializationError);
...
} else {
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
// 默认参数拼接
query = AFQueryStringFromParameters(parameters);
break;
}
}
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
if (query && query.length > 0) {
// 将参数设置到 url 中
mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
}
} else {
...
// 将参数设置到 http body 中
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
}
return mutableRequest;
}
4. NSURLSessionDataTask 的创建
NSURLRequest
创建完成后,就需要创建 task。task 的创建主要涉及dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
。task 可以直接采用NSURLSession
的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;
// 这里是为了解决iOS8以下task会在异步创建的问题
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
// 设置请求回调
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
5. 请求回调的处理
NSURLSession
中涉及的网络代理较多,包括:
- NSURLSessionDelegate :所有代理的基类,定义了网络请求最基础的代理方法。
- NSURLSessionTaskDelegate :定义了网络请求任务相关的代理方法。
- NSURLSessionDownloadDelegate :用于下载任务相关的代理方法,比如下载进度等等。
- NSURLSessionDataDelegate :用于普通数据任务和上传任务。
AFNetworking 中机会对几乎所有代理方法进行了处理:
1. NSURLSessionDelegate
- URLSession:didBecomeInvalidWithError:
- URLSession:didReceiveChallenge:completionHandler:
- URLSessionDidFinishEventsForBackgroundURLSession: // 后台下载相关
2. NSURLSessionTaskDelegate
- URLSession:task:didCompleteWithError:
- URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:
- URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
- URLSession:task:needNewBodyStream:
- URLSession:task:didReceiveChallenge:completionHandler:`
/// 未实现的方法:
- URLSession:task:willBeginDelayedRequest:completionHandler:
- URLSession:taskIsWaitingForConnectivity:
- URLSession:task:didFinishCollectingMetrics:
3. NSURLSessionDataDelegate
- URLSession:dataTask:didReceiveResponse:completionHandler:
- URLSession:dataTask:didBecomeDownloadTask:
- URLSession:dataTask:didReceiveData:
- URLSession:dataTask:willCacheResponse:completionHandler:
/// 未实现的方法:
- URLSession:dataTask:didBecomeStreamTask:
4. NSURLSessionDownloadDelegate
- URLSession:downloadTask:didFinishDownloadingToURL:
- URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
- URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
上述回调方法的处理均是在AFURLSessionManager
中完成的。为了功能的划分 AFNetworking 将与请求状态相关的代理分发到了AFURLSessionManagerTaskDelegate
中,包括上传/下载进度和请求完成的回调。
// NSURLSessionTaskDelegate 网络请求任务相关的代理方法
- URLSession:task:didCompleteWithError:
- URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
// NSURLSessionDataDelegate 普通数据任务和上传任务代理方法
- URLSession:dataTask:didReceiveData:
// NSURLSessionDownloadDelegate 下载任务相关的代理方法
- URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
- URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
- URLSession:downloadTask:didFinishDownloadingToURL:
所以代理处理的整体结构如图:
设置代理的方法由addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler:
完成,该方法设置了上传/下载进度和请求完成的回调。并将delegate
与task
的对应关系保存在字典mutableTaskDelegatesKeyedByTaskIdentifier
中。在AFURLSessionManager
中网络回调触发时,通过task
获取对应的delegate
,然后处理或调整delegate
中相关内容。
- (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;
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
// 保存 delegate 和 task 间的映射关系
[self setDelegate:delegate forTask:dataTask];
}
AFURLSessionManagerTaskDelegate
声明的属性中除了包含各种回调,还包括两个NSProgress
,它们分别用于处理上传和下载进度。我们重点关注URLSession:task:didCompleteWithError:
回调,其他回调主要处理上传/下载 block 。从代码中我们可以看出该回调中主要处理这几件事情:
- 收集请求完成时通知相关信息;
- 通过
responseSerializer
处理响应数据; - 执行
completionHandler
回调; - 发送请求完成的通知
AFNetworkingTaskDidCompleteNotification
;
这里有几个问题需要注意。
- 3、4 是在
dispatch_group_async
中执行的,同时其 group 和 queue 均可以通过业务方设置,这就说明这里的 dispatch_group 主要是提供给业务方使用的,如果单纯的从回调执行来看,则不需要通过 dispatch_group 处理; - 通知的发送。通知的接收线程和发起线程是同一个线程,所以这里采用了 dispatch 到主线程的方式完成。当然也可以通过
NSMachPort
进行处理。
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
__strong AFURLSessionManager *manager = self.manager;
__block id responseObject = nil;
// 1. 收集通知信息
__block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
...
if (error) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
// 3. 执行`completionHandler`回调;
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, error);
}
// 4. 发送请求完成的通知
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
} else {
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
// 2. 通过`responseSerializer`处理响应数据
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
...
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
// 3. 执行`completionHandler`回调;
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, serializationError);
}
// 4. 发送请求完成的通知
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
});
}
}
响应数据的反序列化由AFHTTPResponseSerializer
完成,该类实现了AFURLResponseSerialization
协议,协议仅有一个函数,函数功能包括:解析返回数据、检查数据是否合法、解析服务器返回的NSData
对象。
AFHTTPResponseSerializer
并有多个子类:
-
AFJSONResponseSerializer
: 采用NSJSONSerialization
解析 json 格式; -
AFXMLParserResponseSerializer
: 采用NSXMLParser
解析 xml 格式; -
AFXMLDocumentResponseSerializer
: 采用NSXMLDocument
解析 xml 格式; -
AFPropertyListResponseSerializer
: 解析 plist 格式; -
AFImageResponseSerializer
: 解析图片; -
AFCompoundResponseSerializer
: 组合解析器,可以将多个解析器组合起来,以同时支持多种格式的数据解析;
AFHTTPResponseSerializer
作为基类,提供了基础的验证数据是否合法的方法validateResponse:data:error:
。从头文件中定义的属性acceptableStatusCodes
和acceptableContentTypes
,可以猜测验证的是 accept-type 和 code 的合法性,实际也是如此。AFHTTPResponseSerializer
的子类负责设置对应的 accept-type,code 则在基类中处理,仅接受 2XX 的 code。
- (BOOL)validateResponse:(NSHTTPURLResponse *)response
data:(NSData *)data
error:(NSError * __autoreleasing *)error
{
BOOL responseIsValid = YES;
NSError *validationError = nil;
if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
// 处理 accept-type 类型错误
if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]] &&
!([response MIMEType] == nil && [data length] == 0)) {
if ([data length] > 0 && [response URL]) {
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
if (data) {
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
}
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);
}
responseIsValid = NO;
}
// 处理响应 code 错误
if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
if (data) {
mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
}
validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
responseIsValid = NO;
}
}
if (error && !responseIsValid) {
*error = validationError;
}
return responseIsValid;
}
6. 小结
至此,通过 AFNetworking 发起网络请求的整体流程就梳理完了。网络的流程是:
- 创建
AFHTTPSessionManager
; - 设置请求参数和回调,调用
AFHTTPSessionManager
方法发起请求;
从本文的分析可以看出,采用 AFNetworking 与 NSURLSession 发起网络请求的区别就很明显了:
- 对通用的网络回调,用 block 替代 delegate 对网络回调进行处理;对非通用的网络回调通过 NSNotification 的方式发送到业务层;
- AFNetworking 帮我们封装了请求参数序列化和响应参数反序列化相关的类,我们可以直接使用,也可自定义;
当然还有一些其他功能,比如 HTTPS 请求证书的验证,multipart 请求数据的拼接,网络状态的监听等会再接下来的内容中介绍。