AFNetworking这个第三方网络库,相信大家都很熟悉,但是他究竟做了什么?让我们一起来研究下。
AFNetworking结构
从上图,可以看到AFNetworking主要分为五个模块组成:
- 网络通信模块(AFHTTPSessionManager、AFURLSessionManager)
- 网络状态监听模块(AFNetworkReachabilityManager)
- 网络通信安全策略模块(AFSecurityPolicy)
- 网络通信信息序列化、反序列化模块(AFURLRequestSerialization、AFURLResponseSerialization)
- UIKit库的扩展(UIKit+AFNetworking)
AFNetworking 3.x的核心AFURLSessionManager是基于NSURLSession来封装的。
@interface AFURLSessionManager : NSObject
模块对应关系图如下:
interface AFHTTPSessionManager : AFURLSessionManager
可以看到AFHTTPSessionManager是继承于AFURLSessionManager,只是做了一些简单的封装。
AFNetworking初始化
get请求:
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:@"https://" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
初始化manager:
+ (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
{
self = [super initWithSessionConfiguration:configuration];
if (!self) {
return nil;
}
//对baseURL进行处理,url有值且最后不包含@"/",url加上@"/"
if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
//URLByAppendingPathComponent添加的是路径 @“” -> /@""
url = [url URLByAppendingPathComponent:@""];
}
self.baseURL = url;
self.requestSerializer = [AFHTTPRequestSerializer serializer];
self.responseSerializer = [AFJSONResponseSerializer serializer];
return self;
}
可以看见创建的时候都调用了- (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration
方法。
AFURLSessionManager初始化方法:
- (instancetype)init {
return [self initWithSessionConfiguration:nil];
}
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.sessionConfiguration = configuration;
self.operationQueue = [[NSOperationQueue alloc] init];
/*
默认是并发队列,如果最大并发数>1,并发
如果最大并发数==1,串行
系统默认的并发数是-1,所有任务全部并发执行
*/
self.operationQueue.maxConcurrentOperationCount = 1;
//代理
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
//该字典存放着每一个task对应的AFURLSessionManagerTaskDelegate
//self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
//为mutableTaskDelegatesKeyedByTaskIdentifier加锁,确保在多线程访问时线程安全
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;
//将task相关代理置为nil
[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;
}
网络请求
原生请求:
//创建session对象
NSURLSession *session = [NSURLSession sharedSession];
//添加网络任务
NSURLSessionTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://"]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
//开始任务
[task resume];
AFNetworking
- (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;
}
dataTaskWithHTTPMethod
:
- (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;
//生成NSMutableURLRequest
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;
//获取NSURLSessionDataTask
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;
}
requestWithMethod
:
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
//增加断言debug模式下有效当一下参数为空的时候停止程序并打印错误日志
NSParameterAssert(method);
NSParameterAssert(URLString);
NSURL *url = [NSURL URLWithString:URLString];
//如果根据传入的参数创建出来的url为空则停止程序打印错误日志
NSParameterAssert(url);
//通过以上断言,成功通过之后根据正确的url创建mutableRequest对象
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
//设置mutableRequest的请求方式(GET、POST、HEAD、DELETE、PUT等)
mutableRequest.HTTPMethod = method;
/*
设置mutableRequest的属性 AFHTTPRequestSerializerObservedKeyPaths()函数创建参数数组
①allowsCellularAccess 是否允许使用蜂窝网络
②cachePolicy 缓存策略
1:NSURLRequestUseProtocolCachePolicy (默认的缓存策略,如果本地缓存不存在,直接从服务端获取。如果缓存存在,会根据response中的Cache-Control字段判断下一步操作,如: Cache-Control字段为must-revalidata, 则询问服务端该数据是否有更新,无更新的话直接返回给用户缓存数据,若已更新,则请求服务端)
2:NSURLRequestReloadIgnoringLocalCacheData (忽略本地缓存数据,直接请求服务端)
3:NSURLRequestReloadIgnoringLocalAndRemoteCacheData(忽略本地缓存,代理服务器以及其他中介,直接请求源服务端)
4:NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData
5:NSURLRequestReturnCacheDataElseLoad(有缓存就使用,不管其有效性(即忽略Cache-Control字段), 无则请求服务端)
6:NSURLRequestReturnCacheDataDontLoad (只使用cache数据,如果不存在cache,请求失败;用于没有建立网络连接离线模式)
7:NSURLRequestReloadRevalidatingCacheData //目前未实现
③HTTPShouldHandleCookies//设置请求不保存cookie
④HTTPShouldUsePipelining //是否使用流水线式请求作业(当前请求的发送需要等待上一个请求发送处理完成之后)
⑤networkServiceType //网络服务类型表示当前请求是处理那种类型的业务
1:NSURLNetworkServiceTypeDefault // Standard internet traffic
2:NSURLNetworkServiceTypeVoIP //Voice over IP control traffic
3:NSURLNetworkServiceTypeVideo // Video traffic
4:NSURLNetworkServiceTypeBackground // Background traffic
5:NSURLNetworkServiceTypeVoice // Voice data
6:NSURLNetworkServiceTypeCallSignaling // Call Signaling
timeoutInterval- 默认超时时间是60s
]
*/
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
//mutableRequest设置缓存策略
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
//parameters编码并添加到reques中
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
return mutableRequest;
}
来看看AFHTTPRequestSerializerObservedKeyPaths()
:
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;
}
看下self.mutableObservedChangedKeyPaths
:
@property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths;
那么这个集合创建的地方:
/*
mutableObservedChangedKeyPaths 这个数组在初始化的时候创建:
self.mutableObservedChangedKeyPaths = [NSMutableSet set];
使用set避免重复出现keypath
mutableObservedChangedKeyPaths 添加keypath的时机,NSKeyValueObserving
*/
self.mutableObservedChangedKeyPaths = [NSMutableSet set];
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
//添加KVO观察者
[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
}
}
KVO触发:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(__unused id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == AFHTTPRequestSerializerObserverContext) {
//为空移除,不为空添加到集合里面
if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
[self.mutableObservedChangedKeyPaths removeObject:keyPath];
} else {
[self.mutableObservedChangedKeyPaths addObject:keyPath];
}
}
}
requestBySerializingRequest
:
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSParameterAssert(request);
NSMutableURLRequest *mutableRequest = [request mutableCopy];
//遍历
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
//设置request的请求头
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
//参数拼接成字符串
NSString *query = nil;
if (parameters) {
//自定义解析
if (self.queryStringSerialization) {
NSError *serializationError;
query = self.queryStringSerialization(request, parameters, &serializationError);
if (serializationError) {
if (error) {
*error = serializationError;
}
return nil;
}
} else {
//默认解析
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParameters(parameters);
break;
}
}
}
//判断该HTTPMethodsEncodingParametersInURI中是否包含了GET、HEAD、DELETE。(self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil];)
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
if (query && query.length > 0) {
//GET、HEAD、DELETE,把参数quey是拼接到url后面的。
mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
}
} else {
//POST、PUT是把query拼接到http body中
// #2864: an empty string is a valid x-www-form-urlencoded payload
if (!query) {
query = @"";
}
//设置Content-Type 默认application/x-www-form-urlencoded
if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}
//设置HTTPBody请求体
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
}
return mutableRequest;
}
默认的解析方法:
NSString * AFQueryStringFromParameters(NSDictionary *parameters) {
NSMutableArray *mutablePairs = [NSMutableArray array];
/*
AFQueryStringPair:(两个属性:field,value)
AFQueryStringPairsFromDictionary:将Dictionary转成Array(AFQueryStringPair)
URLEncodedStringValue:@"%@=%@"
*/
for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
[mutablePairs addObject:[pair URLEncodedStringValue]];
}
return [mutablePairs componentsJoinedByString:@"&"];
}
NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
return AFQueryStringPairsFromKeyAndValue(nil, dictionary);
}
NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
//根据对象的description来进行升序排列
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
//判断vaLue类型,递归调用,将得到的参数数组返回。
if ([value isKindOfClass:[NSDictionary class]]) {
NSDictionary *dictionary = value;
// Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
id nestedValue = dictionary[nestedKey];
if (nestedValue) {
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
}
}
} else if ([value isKindOfClass:[NSArray class]]) {
NSArray *array = value;
for (id nestedValue in array) {
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
}
} else if ([value isKindOfClass:[NSSet class]]) {
NSSet *set = value;
for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
}
} else {
[mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
}
return mutableQueryStringComponents;
}
回到dataTaskWithHTTPMethod
:
- (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;
//生成NSMutableURLRequest
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;
//获取NSURLSessionDataTask
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;
}
看下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;
//创建NSURLSessionDataTask(修复iOS8以下taskIdentifiers,函数创建task对象)
url_session_manager_create_task_safely(^{
//dataTaskWithRequest 生成dataTask
dataTask = [self.session dataTaskWithRequest:request];
});
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
url_session_manager_create_task_safely()
函数:
static void url_session_manager_create_task_safely(dispatch_block_t block) {
/*
判断系统版本号,防止iOS8以下内部的dataTaskWithRequest是并发创建的。
并发创建就会导致taskIdentifiers不唯一,而taskIdentifiers作为delegate的key必须是唯一的。
*/
if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
// Fix of bug
// Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
// Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
//dispatch_sync(),同步添加操作,等待添加进队列里面的操作完成之后再继续执行。
//线程等待,直到生成dataTask
dispatch_sync(url_session_manager_creation_queue(), block);
} else {
block();
}
}
static dispatch_queue_t url_session_manager_creation_queue() {
static dispatch_queue_t af_url_session_manager_creation_queue;
static dispatch_once_t onceToken;
//保证只创建一次
dispatch_once(&onceToken, ^{
af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL);
});
return af_url_session_manager_creation_queue;
}
接着addDelegateForDataTask
:
- (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
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
//赋值,AFURLSessionManagerTaskDelegate和AFURLSessionManager建立关系
delegate.manager = self;
//block
delegate.completionHandler = completionHandler;
//taskDescription属性为任务提供描述性标签
//taskDescriptionForSessionTasks当前指针地址,用来发送开始和挂起通知
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
//delegate和dataTask建立关系
[self setDelegate:delegate forTask:dataTask];
//上传下载进度回调
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
initWithTask
:
- (instancetype)initWithTask:(NSURLSessionTask *)task {
self = [super init];
if (!self) {
return nil;
}
_mutableData = [NSMutableData data];
//创建Progress
_uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
_downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
__weak __typeof__(task) weakTask = task;
//上传下载cancel、suspend、resume进度条
for (NSProgress *progress in @[ _uploadProgress, _downloadProgress ])
{
progress.totalUnitCount = NSURLSessionTransferSizeUnknown;
progress.cancellable = YES;
progress.cancellationHandler = ^{
[weakTask cancel];
};
progress.pausable = YES;
progress.pausingHandler = ^{
[weakTask suspend];
};
if ([progress respondsToSelector:@selector(setResumingHandler:)]) {
progress.resumingHandler = ^{
[weakTask resume];
};
}
//观察progress
[progress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionNew
context:NULL];
}
return self;
}
//触发
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
//Progress改变,回调
if ([object isEqual:self.downloadProgress]) {
if (self.downloadProgressBlock) {
self.downloadProgressBlock(object);
}
}
else if ([object isEqual:self.uploadProgress]) {
if (self.uploadProgressBlock) {
self.uploadProgressBlock(object);
}
}
}
setDelegate
:
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
//断言
NSParameterAssert(task);
NSParameterAssert(delegate);
//加锁,保证字典线程安全
[self.lock lock];
//键值对-> key:taskIdentifier value:delegate
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
//添加通知,监听task的progress
[self addNotificationObserverForTask:task];
//解除锁定
[self.lock unlock];
}
到这里task处理就完成了。接着task就开始请求网络了,AFURLSessionManager的initWithSessionConfiguration
方法:
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
这里AFURLSessionManager作为了所有task的delegate,当开始请求的时候,调用了那些代理呢?
NSURLSessionDelegate
代理:
/*
当不再需要连接调用Session的invalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:这个事件。Delegate收到这个事件之后会被解引用。
*/
- (void)URLSession:(NSURLSession *)session
didBecomeInvalidWithError:(NSError *)error
{
if (self.sessionDidBecomeInvalid) {
self.sessionDidBecomeInvalid(session, error);
}
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session];
}
/*
只要访问的是HTTPS的路径就会调用
该方法的作用就是处理服务器返回的证书, 需要在该方法中告诉系统是否需要安装服务器返回的证书
NSURLAuthenticationChallenge : 授权质问
*/
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
if (self.sessionDidReceiveAuthenticationChallenge) {
disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential);
} else {
//从服务器返回的受保护空间中拿到证书的类型
//判断服务器返回的证书是否是服务器信任的
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//基于客户端的安全策略来决定是否信任该服务器
if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
/*
根据服务器返回的受保护空间创建一个证书
void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)
代理方法的completionHandler block接收两个参数:
第一个参数: 代表如何处理证书
第二个参数: 代表需要处理哪个证书
*/
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
/*如何处理证书
NSURLSessionAuthChallengePerformDefaultHandling:默认方式处理
NSURLSessionAuthChallengeUseCredential:使用指定的证书
NSURLSessionAuthChallengeCancelAuthenticationChallenge:取消请求
*/
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
}
//安装证书
if (completionHandler) {
completionHandler(disposition, credential);
}
}
NSURLSessionTaskDelegate
代理:
//在接收HTTP重定向响应时调用
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest *))completionHandler
{
NSURLRequest *redirectRequest = request;
//重定向
if (self.taskWillPerformHTTPRedirection) {
redirectRequest = self.taskWillPerformHTTPRedirection(session, task, response, request);
}
if (completionHandler) {
//重新请求request
completionHandler(redirectRequest);
}
}
/*
和- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler类似
区别:上一个是是session-level级别的认证,而这个是non-session-level级别的
多添加了一个task参数,可以根据task自定义https认证方式
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
if (self.taskDidReceiveAuthenticationChallenge) {
disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential);
} else {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
disposition = NSURLSessionAuthChallengeUseCredential;
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
}
if (completionHandler) {
completionHandler(disposition, credential);
}
}
//发送新的BodyStream(传输流数据)
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
{
NSInputStream *inputStream = nil;
//采用自定义的taskNeedNewBodyStream
if (self.taskNeedNewBodyStream) {
inputStream = self.taskNeedNewBodyStream(session, task);
} else if (task.originalRequest.HTTPBodyStream && [task.originalRequest.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
//默认的HTTPBodyStream
inputStream = [task.originalRequest.HTTPBodyStream copy];
}
if (completionHandler) {
completionHandler(inputStream);
}
}
//定期收到URLSession任务,回调上传的进度
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
int64_t totalUnitCount = totalBytesExpectedToSend;
//如果totalUnitCount获取失败,就使用header中的Content-Length作为totalUnitCount
if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"];
if(contentLength) {
totalUnitCount = (int64_t) [contentLength longLongValue];
}
}
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
if (delegate) {
[delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend];
}
if (self.taskDidSendBodyData) {
self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount);
}
}
//任何任务完成时调用
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
//根据task的taskIdentifier获取delegate
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// delegate may be nil when completing a task in the background
if (delegate) {
//转发delegate
[delegate URLSession:session task:task didCompleteWithError:error];
//移除
[self removeDelegateForTask:task];
}
//block回调
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
NSURLSessionDataDelegate
代理:
//接收数据或下载数据时调用
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
//默认情况下,当接收到服务器响应之后,服务器认为客户端不需要接收数据,所以后面的代理方法不会调用
//如果需要继续接收服务器返回的数据,那么需要调用block,并传入对应的策略
/*
NSURLSessionResponseCancel = 0, 取消任务
NSURLSessionResponseAllow = 1, 接收任务
NSURLSessionResponseBecomeDownload = 2, 转变成下载
NSURLSessionResponseBecomeStream NS_ENUM_AVAILABLE(10_11, 9_0) = 3, 转变成流
*/
NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
//自定义
if (self.dataTaskDidReceiveResponse) {
disposition = self.dataTaskDidReceiveResponse(session, dataTask, response);
}
if (completionHandler) {
completionHandler(disposition);
}
}
//如果你的应用程序选择任务的数据转换为一个下载任务时调用
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
{
//重新根据task的taskIdentifier获取delegate
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
if (delegate) {
//移除
[self removeDelegateForTask:dataTask];
//重新设置
[self setDelegate:delegate forTask:downloadTask];
}
//自定义block
if (self.dataTaskDidBecomeDownloadTask) {
self.dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask);
}
}
//接收数据时候调用
- (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);
}
}
/*
对于一个数据任务,NSURLSession对象调用委托的
URLSession:dataTask:willCacheResponse:completionHandler:方法。应用程序然后决定是否应该允许缓
存。如果你不实现这个方法,默认行为是使用会话缓存策略中指定的配置对象。
*/
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler
{
NSCachedURLResponse *cachedResponse = proposedResponse;
if (self.dataTaskWillCacheResponse) {
cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse);
}
if (completionHandler) {
completionHandler(cachedResponse);
}
}
/*
在切到后台之后,Session的Delegate不会再收到,Task相关的消息,直到所有Task全都完成后,系统会调用
ApplicationDelegate的
application:handleEventsForBackgroundURLSession:completionHandler:回调,之后“汇报”下载工
作,对于每一个后台下载的Task调用Session的Delegate中的
URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和
URLSession:task:didCompleteWithError:(成功或者失败都会调用)。
之后调用Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession:。
*/
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
if (self.didFinishEventsForBackgroundURLSession) {
dispatch_async(dispatch_get_main_queue(), ^{
self.didFinishEventsForBackgroundURLSession(session);
});
}
}
#pragma mark - NSURLSessionDownloadDelegate
//下载完成的时候调用
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (self.downloadTaskDidFinishDownloading) {
//获取文件存储地址
NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
if (fileURL) {
delegate.downloadFileURL = fileURL;
NSError *error = nil;
//从临时的下载路径移动至我们需要的路径
if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error]) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
}
return;
}
}
//转发
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
}
}
/*
当接收到下载数据的时候调用,可以在该方法中监听文件下载的进度
该方法会被调用多次
totalBytesWritten:已经写入到文件中的数据大小
totalBytesExpectedToWrite:目前文件的总大小
bytesWritten:本次下载的文件数据大小
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didWriteData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
}
if (self.downloadTaskDidWriteData) {
self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}
}
/*
恢复下载的时候调用该方法
fileOffset:恢复之后,要从文件的什么地方开发下载
expectedTotalBytes:该文件数据的总大小
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didResumeAtOffset:fileOffset expectedTotalBytes:expectedTotalBytes];
}
if (self.downloadTaskDidResume) {
self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
}
}
从上面可以看到有些代理方法转发到AFNetworking中自己的代理了,下面来看看AFNetworking是怎么处理数据的:
//URLSession转发
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
//强引用,防止被释放(@property (nonatomic, weak) AFURLSessionManager *manager;)
__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;
}
//userInfo赋值
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 {
//并行队列 加快数据的处理速度
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
//数据解析
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
//下载文件路径
if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
}
//userInfo赋值
if (responseObject) {
userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
}
//解析出现问题
if (serializationError) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
}
//回调结果
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];
});
});
});
}
}
- (void)URLSession:(__unused NSURLSession *)session
dataTask:(__unused NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data
{
//下载总进度
self.downloadProgress.totalUnitCount = dataTask.countOfBytesExpectedToReceive;
//下载完成进度
self.downloadProgress.completedUnitCount = dataTask.countOfBytesReceived;
//拼接数据
[self.mutableData appendData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
//上传总进度
self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
//上传完成进度
self.uploadProgress.completedUnitCount = task.countOfBytesSent;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
self.downloadProgress.totalUnitCount = totalBytesExpectedToWrite;
self.downloadProgress.completedUnitCount = totalBytesWritten;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
self.downloadProgress.totalUnitCount = expectedTotalBytes;
self.downloadProgress.completedUnitCount = fileOffset;
}
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
self.downloadFileURL = nil;
if (self.downloadTaskDidFinishDownloading) {
self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
if (self.downloadFileURL) {
NSError *fileManagerError = nil;
//把下载路径移动到我们自定义的下载路径
if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError]) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo];
}
}
}
}
到此,AFNetworking代理也说完了。
数据解析
数据解析responseObjectForResponse
主要有:
其中
[AFURLResponseSerialization responseObjectForResponse: data: error:]
是一个协议方法
@protocol AFURLResponseSerialization
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
data:(nullable NSData *)data
error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
@end
而其他的类都是遵守这个协议方法来进行数据解析。
- AFURLResponseSerialization
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error
{
[self validateResponse:(NSHTTPURLResponse *)response data:data error:error];
return data;
}
- AFHTTPResponseSerializer
//判断数据类型是否符合要求
- (BOOL)validateResponse:(NSHTTPURLResponse *)response
data:(NSData *)data
error:(NSError * __autoreleasing *)error
{
//response是否合法标志
BOOL responseIsValid = YES;
//error
NSError *validationError = nil;
//response不为空并且属于NSHTTPURLResponse
if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
//判断可以接受的数据类型和response的数据类型是否匹配,
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;
}
//判断是否是可接受
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;
}
}
//error赋值
if (error && !responseIsValid) {
*error = validationError;
}
//返回error
return responseIsValid;
}
- AFJSONResponseSerializer
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error
{
//判断类型
if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
return nil;
}
}
// Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
// See https://github.com/rails/rails/issues/1742
BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
if (data.length == 0 || isSpace) {
return nil;
}
NSError *serializationError = nil;
//json解析
id responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
//responseObject为空,返回json解析错误的error
if (!responseObject)
{
if (error) {
*error = AFErrorWithUnderlyingError(serializationError, *error);
}
return nil;
}
//是否移除空值
if (self.removesKeysWithNullValues) {
return AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
}
//返回解析结果
return responseObject;
}
其他解析方法,就可以自己阅读源码了。