该文章阅读的AFNetworking的版本为3.2.0。git
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
复制代码
在AFHTTPSessionManager
类中全部的初始化方法最终都会调用到- (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration
方法中github
- (instancetype)initWithBaseURL:(NSURL *)url
sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
// 首先调用了父类AFURLSessionManager的初始化方法
self = [super initWithSessionConfiguration:configuration];
if (!self) {
return nil;
}
// 若是有效的url后没有正斜线“/”就添加上正斜线“/”
if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
url = [url URLByAppendingPathComponent:@""];
}
// 记录url
self.baseURL = url;
// 实例化请求和响应序列化对象
self.requestSerializer = [AFHTTPRequestSerializer serializer];
self.responseSerializer = [AFJSONResponseSerializer serializer];
return self;
}
复制代码
在其父类AFURLSessionManager
类中的- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration
中作了基本属性的初始化数组
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
// 初始化NSURLSessionConfiguration若是没有传则用默认
if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.sessionConfiguration = configuration;
// 初始化一个操做队列并设置最大线程并发数为1
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
// 利用已经初始化好的NSURLSessionConfiguration和NSOperationQueue初始化NSURLSession并遵照了代理
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
// 初始化JSON响应序列对象
self.responseSerializer = [AFJSONResponseSerializer serializer];
// 初始化安全策略
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
// 初始化网络状态监测对象
#if !TARGET_OS_WATCH
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif
// 初始化可变字典保存NSURLSessionTask和其对应的delegate,并以NSURLSessionTask的属性taskIdentifier作key,以NSURLSession的delegate作value
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
// 初始化self.mutableTaskDelegatesKeyedByTaskIdentifier可变字典的锁,确保字典在多线程访问时的线程安全
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;
// 异步的获取当前session的全部未完成的task,并进行置空处理,主要是为了从后台切换到前台时从新初始化session
[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;
}
复制代码
以GET请求为例安全
[manager GET:URLString parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(@"下载进度:%@", downloadProgress);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"响应对象:%@", responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"错误:%@", error);
}];
复制代码
点击进入方法中bash
- (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对象
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
URLString:URLString
parameters:parameters
uploadProgress:nil
downloadProgress:downloadProgress
success:success
failure:failure];
// 开始任务
[dataTask resume];
return dataTask;
}
复制代码
发现全部的请求方法不管是GET、POST仍是其余都调用了同一个方法服务器
- (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
{
// 把全部的参数解析拼接生成一个NSMutableURLRequest对象,若是没法解析则回调返回错误
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) {
#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;
}
// 用生成的NSMutableURLRequest对象生成一个NSURLSessionDataTask对象并回调成功或失败
__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;
}
复制代码
先看在AFURLRequestSerialization
类中如何利用各类参数生成NSMutableURLRequest
对象网络
- (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对象并设置请求方式
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
mutableRequest.HTTPMethod = method;
// 遍历AFHTTPRequestSerializer的各个属性
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
// 若是发现有正在被观察的属性
if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
// 把本类对应属性的值赋给NSMutableURLRequest对应的属性
[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
}
}
// 将传入的parameters添加到mutableRequest中
mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
return mutableRequest;
}
复制代码
static NSArray *AFHTTPRequestSerializerObservedKeyPaths()
这个函数其实是将AFHTTPRequestSerializer
类中一些属性的名字封装成字符串并以数组形式返回self.mutableObservedChangedKeyPaths
这个属性在AFURLRequestSerialization
的初始化方法- (instancetype)init
中进行了初始化self.mutableObservedChangedKeyPaths = [NSMutableSet set];
// 观察AFHTTPRequestSerializerObservedKeyPaths()函数返回的属性
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
}
}
复制代码
并在KVO方法中进行赋值session
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(__unused id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == AFHTTPRequestSerializerObserverContext) {
// 若是给当前属性赋的值不为null就添加到self.mutableObservedChangedKeyPaths中,不然从其中移除
if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
[self.mutableObservedChangedKeyPaths removeObject:keyPath];
} else {
[self.mutableObservedChangedKeyPaths addObject:keyPath];
}
}
}
复制代码
由此因此咱们能够得知self.mutableObservedChangedKeyPaths
中保存的就是咱们设置的AFHTTPRequestSerializer
对象的属性的集合多线程
[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error]
把parameters
编码并设置到mutableRequest中- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
// 在debug模式下若是缺乏NSURLRequest对象则会crash
NSParameterAssert(request);
NSMutableURLRequest *mutableRequest = [request mutableCopy];
// 遍历并对request没有的属性进行赋值
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
// 把parameters编码成字符串
NSString *query = nil;
if (parameters) {
// 若是自定义了参数编码方式
if (self.queryStringSerialization) {
NSError *serializationError;
// 用户可经过block自定义参数的编码方式
query = self.queryStringSerialization(request, parameters, &serializationError);
if (serializationError) {
if (error) {
*error = serializationError;
}
return nil;
}
// 使用默认的参数编码方式
} else {
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParameters(parameters);
break;
}
}
}
// 判断是不是GET、HEAD、DELETE请求,self.HTTPMethodsEncodingParametersInURI这个属性在AFURLRequestSerialization的初始化方法- (instancetype)init中进行了初始化
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]];
}
// 若是是POST、PUT请求
} else {
// #2864: an empty string is a valid x-www-form-urlencoded payload
if (!query) {
query = @"";
}
if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}
// 把编码好的参数拼到http的body中
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
}
return mutableRequest;
}
复制代码
大概的看一下AFNetworking
默认的的参数编码方式,AFQueryStringFromParameters()
点进去之后能够看到是三个方法并发
NSString * AFQueryStringFromParameters(NSDictionary *parameters) {
NSMutableArray *mutablePairs = [NSMutableArray array];
// 遍历由集合对象处理成AFQueryStringPair元素组成的数组
for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
// 把AFQueryStringPair元素的属性拼接成字符串添加到mutablePairs中,若是有value值就拼接成“field=value”的形式,不然为“field”
[mutablePairs addObject:[pair URLEncodedStringValue]];
}
// 把mutablePairs中的字符串用&连接成一个字符串
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是NSDictionary
if ([value isKindOfClass:[NSDictionary class]]) {
// 将NSDictionary的key按照首字母升序排列后遍历出nestedKey及其对应的nestedValue,而后递归调用AFQueryStringPairsFromKeyAndValue()方法,若是有key值则传(key[nestedKey], nestedValue),不然传(nestedKey, nestedValue)
NSDictionary *dictionary = value;
for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
id nestedValue = dictionary[nestedKey];
if (nestedValue) {
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
}
}
// 若是value是NSArray
} else if ([value isKindOfClass:[NSArray class]]) {
// 直接遍历取出nestedValue,而后递归调用AFQueryStringPairsFromKeyAndValue()方法,若是有key值则传递(key[], nestedValue),不然传((null)[], nestedValue)
NSArray *array = value;
for (id nestedValue in array) {
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
}
// 若是value是NSSet
} else if ([value isKindOfClass:[NSSet class]]) {
// 将NSSet的值按照首字母升序排列后遍历出值obj,而后递归调用AFQueryStringPairsFromKeyAndValue()方法,若是有key值则传(key, obj),不然传((null), obj)
NSSet *set = value;
for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
}
// 若是value不是集合对象
} else {
实例化AFQueryStringPair对象添加到mutableQueryStringComponents数组中,也就是说AFQueryStringPairsFromKeyAndValue()这个方法执行结束后,返回的是由集合对象转化为AFQueryStringPair对象的元素组成的数组
[mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
}
return mutableQueryStringComponents;
}
复制代码
至此,实例化NSMutableURLRequest
对象的任务就结束了,而后就须要再回到- (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
这个方法中,利用上一步实例化好的NSURLSessionDataTask
对象request
生成网络请求任务NSURLSessionDataTask
- (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;
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
复制代码
发现dataTask并非直接建立,而是在一个block中建立,点进url_session_manager_create_task_safely
能够看到这实际上是作了一个版本的兼容
static void url_session_manager_create_task_safely(dispatch_block_t block) {
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
// 苹果在iOS8的时候已经解决了这个bug,这是为了兼容iOS8以前
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;
}
复制代码
所以,能够发现若是是在iOS8以前的版本建立dataTask
是在一个同步串行队列里,经过查找资料,能够知道在iOS8以前- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
这个方法是异步并发执行的,因此会出现实际回调completionHandlers
并非当初task
的回调,而是另外一个task
的回调。
接下来是对生成的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的对象并和NSURLSessionDataTask对象以及AFURLSessionManager对象相关联
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
delegate.manager = self;
delegate.completionHandler = completionHandler;
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
[self setDelegate:delegate forTask:dataTask];
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
复制代码
接着点[self setDelegate:delegate forTask:dataTask];
进去
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
// 在debug模式下若是缺乏参数则会crash
NSParameterAssert(task);
NSParameterAssert(delegate);
// 加锁保证对字典的操做线程安全
[self.lock lock];
// 将NSURLSessionTask对象的taskIdentifier做为key,将与之对应的AFURLSessionManagerTaskDelegate对象做为value,存放到字典中
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
// 为task添加开始与暂停通知
[self addNotificationObserverForTask:task];
[self.lock unlock];
}
复制代码
1.在[self addNotificationObserverForTask:task];
方法中添加对task相关通知的接收
- (void)addNotificationObserverForTask:(NSURLSessionTask *)task {
// 接收task开启和暂停的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidResume:) name:AFNSURLSessionTaskDidResumeNotification object:task];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidSuspend:) name:AFNSURLSessionTaskDidSuspendNotification object:task];
}
复制代码
在通知的响应方法中转化为AFNetworking
对外暴漏的通知AFNetworkingTaskDidResumeNotification
和AFNetworkingTaskDidSuspendNotification
- (void)taskDidResume:(NSNotification *)notification {
NSURLSessionTask *task = notification.object;
if ([task respondsToSelector:@selector(taskDescription)]) {
if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task];
});
}
}
}
- (void)taskDidSuspend:(NSNotification *)notification {
NSURLSessionTask *task = notification.object;
if ([task respondsToSelector:@selector(taskDescription)]) {
if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task];
});
}
}
}
复制代码
为何不直接发送通知,而是先接收通知而后通过处理后再发送通知呢?这是由于AFNetworking
把NSURLSessionTask
的suspend
和resume
方法利用runtime
的Method Swizzling
交换为af_suspend
和af_resume
,并在交换后的方法中发送通知以实现对task
开始与暂停的监听, 可是在一个项目中可能有的网络请求不是当前session
的,因此要经过task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks
进行判断这个网络请求task是否来自当前session
,其中self.taskDescriptionForSessionTasks
其实就是AFURLSessionManager
对象的指针字符串
- (NSString *)taskDescriptionForSessionTasks {
return [NSString stringWithFormat:@"%p", self];
}
复制代码
到此为止,对task的处理就结束了。
AFURLSessionManager
遵照了<NSURLSessionDelegate> <NSURLSessionTaskDelegate> <NSURLSessionDataDelegate> <NSURLSessionDownloadDelegate>
四个代理并实现了15个代理方法
AFURLSessionManagerTaskDelegate
只实现了其中6个
- (void)URLSession:(__unused NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
的实现
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
// 由于self.manager属性关键字是weak,因此为了防止被释放就用__strong
__strong AFURLSessionManager *manager = self.manager;
// 用来保存请求返回的数据,为了能够在block中进行修改,用了__block
__block id responseObject = nil;
// 用来保存发送通知时传递的数据,为了能够在block中进行修改,用了__block,并进行赋值
__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_notify实现对回调完成的监控
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;
}
// 传递响应序列化对象
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];
});
});
});
}
}
复制代码
2.第二个代理- (void)URLSession:(__unused NSURLSession *)session dataTask:(__unused NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
的实现相对简单
- (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];
}
复制代码
3.第三个代理- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
是在向服务器传递数据时调用
- (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;
}
复制代码
4.第四个代理是在执行下载任务时,按期调用的
- (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;
}
复制代码
5.第五个代理在重启下载时调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
// 更新下载进度对象的属性
self.downloadProgress.totalUnitCount = expectedTotalBytes;
self.downloadProgress.completedUnitCount = fileOffset;
}
复制代码
6.第六个代理- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
是下载任务完成后的回调
- (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];
}
}
}
}
复制代码
到此为止,一个GET请求就结束了,总结一下AFNetworking
作的事情
AFHTTPSessionManager
利用参数method
、URLString
和parameters
生成一个NSMutableURLRequest
对象request
AFURLSessionManager
利用生成的request
生成一个NSURLSessionDataTask
对象dataTask
dataTask
和AFURLSessionManagerTaskDelegate
的对象delegate
利用字典一一对应保存,将delegate
的进度属性的取消、暂停和开始和dataTask
相对的方法相关联,并对delegate
和dataTask
的相关属性添加观察者对delegate
的上传下载进度属性赋值dataTask
的开始于中止添加通知监听,并向外部发送通知dataTask
的resume
方法进行网络请求AFURLSessionManagerTaskDelegate
的对象delegate
实现的六个代理方法监听进度以及处理请求返回的数据,若是须要解析数据会在异步并发队列中进行,而后在最开始生成的最大并发数为1的NSOperationQueue
的对象operationQueue
串行回调结果。源码阅读系列:AFNetworking
源码阅读:AFNetworking(二)——AFURLRequestSerialization
源码阅读:AFNetworking(三)——AFURLResponseSerialization
源码阅读:AFNetworking(四)——AFSecurityPolicy
源码阅读:AFNetworking(五)——AFNetworkReachabilityManager
源码阅读:AFNetworking(六)——AFURLSessionManager
源码阅读:AFNetworking(七)——AFHTTPSessionManager
源码阅读:AFNetworking(八)——AFAutoPurgingImageCache
源码阅读:AFNetworking(九)——AFImageDownloader
源码阅读:AFNetworking(十)——AFNetworkActivityIndicatorManager
源码阅读:AFNetworking(十一)——UIActivityIndicatorView+AFNetworking
源码阅读:AFNetworking(十二)——UIButton+AFNetworking
源码阅读:AFNetworking(十三)——UIImageView+AFNetworking
源码阅读:AFNetworking(十四)——UIProgressView+AFNetworking