该文章阅读的AFNetworking的版本为3.2.0。html
完成了前面对AFURLRequestSerialization
、AFURLResponseSerialization
、AFSecurityPolicy
和AFNetworkReachabilityManager
类的阅读,接下来就能够阅读AFNetworking
的核心类AFURLSessionManager
啦。经过一开始对头文件的引用,就能够知道AFURLSessionManager
类的核心地位:ios
#import "AFURLResponseSerialization.h"
#import "AFURLRequestSerialization.h"
#import "AFSecurityPolicy.h"
#if !TARGET_OS_WATCH
#import "AFNetworkReachabilityManager.h"
#endif
复制代码
以前对上述类的阅读,就是为了给本类阅读作铺垫。git
/**
网络会话管理者,属性是只读的。想要了解NSURLSession的使用能够看这篇文章:使用NSURLSession(https://www.jianshu.com/p/fafc67475c73)
*/
@property (readonly, nonatomic, strong) NSURLSession *session;
/**
操做队列,也是只读的,最大并发被设置为1,用于代理回调
*/
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;
/**
响应数据序列化对象,默认为`AFJSONResponseSerializer`,即处理json类型数据,不能设置为`nil`
*/
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
/**
用于确保安全链接的安全策略对象,默认为`defaultPolicy`
*/
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;
/**
网络情况监控管理者,默认为`sharedManager`
*/
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
复制代码
/**
当前`session`建立的全部的任务,至关于下面三个属性的和
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;
/**
当前`session`建立的全部的`dataTasks`
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;
/**
当前`session`建立的全部的`uploadTasks`
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;
/**
当前`session`建立的全部的`downloadTasks`
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;
复制代码
/**
任务回调队列,默认或者为NULL时,就是在主队列
*/
@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;
/**
任务回调组,默认或者为NULL时,就生成一个私有队列
*/
@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;
复制代码
/**
从iOS 7.0开始,建立后台上传任务有时候会返回为nil,若是设置为YES,AFNetworking遵循了苹果的建议,若是建立失败会从新建立,默认尝试三次。默认为NO
*/
@property (nonatomic, assign) BOOL attemptsToRecreateUploadTasksForBackgroundSessions;
复制代码
/**
经过指定NSURLSessionConfiguration对象初始化对象
*/
- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
/**
当传YES,就当即关闭当前网络会话;当传NO,等待当前任务完成后再关闭当前对话
*/
- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks;
复制代码
/**
以指定的NSURLRequest对象建立NSURLSessionDataTask
*/
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler DEPRECATED_ATTRIBUTE;
/**
以指定的NSURLRequest对象建立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;
复制代码
/**
以指定的NSURLRequest对象和要上传的本地文件的URL建立NSURLSessionUploadTask,一样,上传进度的回调是在子线程中
*/
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromFile:(NSURL *)fileURL
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
/**
以指定的NSURLRequest对象和要上传的二进制类型数据建立NSURLSessionUploadTask,上传进度的回调也是在子线程中
*/
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromData:(nullable NSData *)bodyData
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
/**
以指定数据流的NSURLRequest对象建立NSURLSessionUploadTask,上传进度的回调也是在子线程中
*/
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
复制代码
/**
以指定的NSURLRequest对象建立NSURLSessionDownloadTask,上传进度的回调是在子线程中,在下载的过程当中会先将文件放到一个临时的路径targetPath,在下载完成后,会将文件移动到用户设置的路径上,并自动删除原路径上的文件。
可是,若是当初建立session的参数configuration设置的是后台模式的话,在应用被杀死时destination中的信息会丢失,因此最好在-setDownloadTaskDidFinishDownloadingBlock:方法中设置下载文件的保存路径
*/
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;
/**
经过以前下载的数据建立NSURLSessionDownloadTask,恢复下载,其余的和上面的方法相同
*/
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;
复制代码
/**
获取指定task的上传进度
*/
- (nullable NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task;
/**
获取指定task的下载进度
*/
- (nullable NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task;
复制代码
/**
设置当session无效时的block回调,这个block回调用在NSURLSessionDelegate的方法URLSession:didBecomeInvalidWithError:中
*/
- (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block;
/**
设置当session接收到验证请求时的block回调,这个block回调用在NSURLSessionDelegate的方法URLSession:didReceiveChallenge:completionHandler:中
*/
- (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
复制代码
/**
设置当task须要一个新的输入流时的block回调,这个block回调用在NSURLSessionTaskDelegate的方法URLSession:task:needNewBodyStream:中
*/
- (void)setTaskNeedNewBodyStreamBlock:(nullable NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block;
/**
设置当一个HTTP请求试图执行重定向到一个不一样的URL时的block回调,这个block回调用在NSURLSessionTaskDelegate的方法URLSession:willPerformHTTPRedirection:newRequest:completionHandler:中
*/
- (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * _Nullable (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block;
/**
设置当task接收到身份验证时的block回调,这个block回调用在NSURLSessionTaskDelegate的方法URLSession:task:didReceiveChallenge:completionHandler:中
*/
- (void)setTaskDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
/**
设置一个block回调来按期跟踪上传进度,这个block回调用在NSURLSessionTaskDelegate的方法URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:中
*/
- (void)setTaskDidSendBodyDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block;
/**
设置当task执行完成时的block回调,这个block回调用在NSURLSessionTaskDelegate的方法URLSession:task:didCompleteWithError:中
*/
- (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * _Nullable error))block;
复制代码
/**
设置当dataTask接收到响应时的block回调,这个block回调用在NSURLSessionDataDelegate的方法URLSession:dataTask:didReceiveResponse:completionHandler:中
*/
- (void)setDataTaskDidReceiveResponseBlock:(nullable NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block;
/**
设置当dataTask变成downloadTask时的block回调,这个block回调用在NSURLSessionDataDelegate的方法URLSession:dataTask:didBecomeDownloadTask:中
*/
- (void)setDataTaskDidBecomeDownloadTaskBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block;
/**
设置当dataTask接收到数据时的block回调,这个block回调用在NSURLSessionDataDelegate的方法URLSession:dataTask:didReceiveData:中
*/
- (void)setDataTaskDidReceiveDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block;
/**
设置当dataTask将要对响应进行缓存时的block回调,这个block回调用在NSURLSessionDataDelegate的方法URLSession:dataTask:willCacheResponse:completionHandler:中
*/
- (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block;
/**
设置当session队列中全部的消息都发送出去时的block回调,这个block回调用在NSURLSessionDataDelegate的方法URLSessionDidFinishEventsForBackgroundURLSession:中
*/
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block;
复制代码
/**
设置当downloadTask完成一个下载时的block回调,这个block回调用在NSURLSessionDownloadDelegate的方法URLSession:downloadTask:didFinishDownloadingToURL:中
*/
- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * _Nullable (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block;
/**
设置一个block回调来按期跟踪下载进度,这个block回调用在NSURLSessionDownloadDelegate的方法URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:中
*/
- (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block;
/**
设置当downloadTask从新开始下载时的block回调,这个block回调用在NSURLSessionDownloadDelegate的方法URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:中
*/
- (void)setDownloadTaskDidResumeBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block;
复制代码
/**
当一个task从新开始时就会发送这个通知
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification;
/**
当一个task执行完成时就会发送这个通知
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteNotification;
/**
当一个task暂停时就会发送这个通知
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidSuspendNotification;
/**
当一个session无效时就会发送这个通知
*/
FOUNDATION_EXPORT NSString * const AFURLSessionDidInvalidateNotification;
/**
当sessionDownloadTask将下载在临时路径的文件移动到用户指定路径出错时就是发送这个通知
*/
FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification;
复制代码
/**
经过这个key能够从AFNetworkingTaskDidCompleteNotification通知所传递的userInfo字典类型数据中取出任务响应的原始数据
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseDataKey;
/**
若是响应已经序列化,经过这个key能够从AFNetworkingTaskDidCompleteNotification通知所传递的userInfo字典类型数据中取出任务响应的序列化数据
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey;
/**
若是响应序列化对象,经过这个key能够从AFNetworkingTaskDidCompleteNotification通知所传递的userInfo字典类型数据中取出任务响应序列化对象
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey;
/**
若是相应数据已经直接存储到磁盘,经过这个key能够从AFNetworkingTaskDidCompleteNotification通知所传递的userInfo字典类型数据中取出下载数据的存储路径
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey;
/**
若是存在错误,,经过这个key能够从AFNetworkingTaskDidCompleteNotification通知所传递的userInfo字典类型数据中取出与task或者是响应序列化相关的错误
*/
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey;
复制代码
#ifndef NSFoundationVersionNumber_iOS_8_0
#define NSFoundationVersionNumber_With_Fixed_5871104061079552_bug 1140.11
#else
#define NSFoundationVersionNumber_With_Fixed_5871104061079552_bug NSFoundationVersionNumber_iOS_8_0
#endif
复制代码
这个宏经过NSFoundation
的版原本判断当前系统的版本,总之就是将NSFoundationVersionNumber_With_Fixed_5871104061079552_bug
定义为iOS8.0github
/**
建立一个单例串行队列,用于建立task
*/
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以前的系统bug,具体的缘由在第一篇“AFNetworking源码阅读(一)——从使用入手”文章中有解释
*/
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
dispatch_sync(url_session_manager_creation_queue(), block);
} else {
block();
}
}
/**
建立一个单利并发队列,用于处理返回的数据
*/
static dispatch_queue_t url_session_manager_processing_queue() {
static dispatch_queue_t af_url_session_manager_processing_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
af_url_session_manager_processing_queue = dispatch_queue_create("com.alamofire.networking.session.manager.processing", DISPATCH_QUEUE_CONCURRENT);
});
return af_url_session_manager_processing_queue;
}
/**
建立一个单利组,用于处理回调,用户可经过dispatch_group_notify实现对回调完成的监控
*/
static dispatch_group_t url_session_manager_completion_group() {
static dispatch_group_t af_url_session_manager_completion_group;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
af_url_session_manager_completion_group = dispatch_group_create();
});
return af_url_session_manager_completion_group;
}
复制代码
NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
NSString * const AFNetworkingTaskDidCompleteNotification = @"com.alamofire.networking.task.complete";
NSString * const AFNetworkingTaskDidSuspendNotification = @"com.alamofire.networking.task.suspend";
NSString * const AFURLSessionDidInvalidateNotification = @"com.alamofire.networking.session.invalidate";
NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification = @"com.alamofire.networking.session.download.file-manager-error";
NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey = @"com.alamofire.networking.task.complete.serializedresponse";
NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey = @"com.alamofire.networking.task.complete.responseserializer";
NSString * const AFNetworkingTaskDidCompleteResponseDataKey = @"com.alamofire.networking.complete.finish.responsedata";
NSString * const AFNetworkingTaskDidCompleteErrorKey = @"com.alamofire.networking.task.complete.error";
NSString * const AFNetworkingTaskDidCompleteAssetPathKey = @"com.alamofire.networking.task.complete.assetpath";
复制代码
static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";
复制代码
.h
文件解释属性attemptsToRecreateUploadTasksForBackgroundSessions中提到的尝试三次static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3;
复制代码
.h
文件中设置的回调方法中为接收传入的block起的别名typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error);
typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
typedef NSURLRequest * (^AFURLSessionTaskWillPerformHTTPRedirectionBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request);
typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionTaskDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session);
typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task);
typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
typedef void (^AFURLSessionTaskDidCompleteBlock)(NSURLSession *session, NSURLSessionTask *task, NSError *error);
typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response);
typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);
typedef void (^AFURLSessionDataTaskDidReceiveDataBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data);
typedef NSCachedURLResponse * (^AFURLSessionDataTaskWillCacheResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse);
typedef NSURL * (^AFURLSessionDownloadTaskDidFinishDownloadingBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location);
typedef void (^AFURLSessionDownloadTaskDidWriteDataBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
typedef void (^AFURLSessionDownloadTaskDidResumeBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes);
复制代码
typedef void (^AFURLSessionTaskProgressBlock)(NSProgress *);
复制代码
typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id responseObject, NSError *error);
复制代码
/**
网路会话管理者,为了防止循环引用这里用了weak
*/
@property (nonatomic, weak) AFURLSessionManager *manager;
/**
保存接收到的数据
*/
@property (nonatomic, strong) NSMutableData *mutableData;
/**
上传进度
*/
@property (nonatomic, strong) NSProgress *uploadProgress;
/**
下载进度
*/
@property (nonatomic, strong) NSProgress *downloadProgress;
/**
下载保存路径
*/
@property (nonatomic, copy) NSURL *downloadFileURL;
/**
保存下载完成回调block
*/
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
/**
保存上传进度回调block
*/
@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
/**
保存下载进度回调block
*/
@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
/**
保存任务完成回调block
*/
@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
复制代码
/**
以指定NSURLSessionTask对象初始化方法
*/
- (instancetype)initWithTask:(NSURLSessionTask *)task;
复制代码
- (instancetype)initWithTask:(NSURLSessionTask *)task {
self = [super init];
if (!self) {
return nil;
}
// 初始化属性
_mutableData = [NSMutableData data];
_uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
_downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
// 将传入的task的取消、暂停和重启与进度对象相应的操做进行绑定
__weak __typeof__(task) weakTask = task;
for (NSProgress *progress in @[ _uploadProgress, _downloadProgress ])
{
progress.totalUnitCount = NSURLSessionTransferSizeUnknown;
progress.cancellable = YES;
progress.cancellationHandler = ^{
[weakTask cancel];
};
progress.pausable = YES;
progress.pausingHandler = ^{
[weakTask suspend];
};
#if __has_warning("-Wunguarded-availability-new")
if (@available(iOS 9, macOS 10.11, *)) {
#else
if ([progress respondsToSelector:@selector(setResumingHandler:)]) {
#endif
progress.resumingHandler = ^{
[weakTask resume];
};
}
// 观察进度对象的进度
[progress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
options:NSKeyValueObservingOptionNew
context:NULL];
}
return self;
}
- (void)dealloc {
// 移除进度对象的观察
[self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
[self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
}
复制代码
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
// 当进度对象的进度发生改变时,回调对应的block
if ([object isEqual:self.downloadProgress]) {
if (self.downloadProgressBlock) {
self.downloadProgressBlock(object);
}
} else if ([object isEqual:self.uploadProgress]) {
if (self.uploadProgressBlock) {
self.uploadProgressBlock(object);
}
}
}
复制代码
/**
当`NSURLSessionTaskDelegate`的这个方法被调用时,意味着这个`task`已经执行完成,不管是否出错
*/
- (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];
});
});
});
}
}
复制代码
/**
当`NSURLSessionDataDelegate`的这个方法被调用时,意味着已经接收到服务器返回的数据了
*/
- (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];
}
/**
当`NSURLSessionDataDelegate`的这个方法被调用时,意味着已经向服务器上传了数据
*/
- (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;
}
复制代码
/**
当执行下载任务时,`NSURLSessionDownloadDelegate`的这个方法会按期调用,传递当前下载进度
*/
- (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;
}
/**
当`NSURLSessionDataDelegate`的这个方法被调用时,表示下载已重启
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
// 更新下载进度对象的属性
self.downloadProgress.totalUnitCount = expectedTotalBytes;
self.downloadProgress.completedUnitCount = fileOffset;
}
/**
当`NSURLSessionDataDelegate`的这个方法被调用时,表示已完成下载
*/
- (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];
}
}
}
}
复制代码
由此,能够看出AFURLSessionManagerTaskDelegate
这个类主要是用来监控上传与下载的进度,以及对task
完成后数据的处理和回调。json
/**
交换某个类两个方法的实现
*/
static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
/**
给一个类添加一个方法
*/
static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) {
return class_addMethod(theClass, selector, method_getImplementation(method), method_getTypeEncoding(method));
}
复制代码
/**
当一个task从新开始时就会发送这个通知
*/
static NSString * const AFNSURLSessionTaskDidResumeNotification = @"com.alamofire.networking.nsurlsessiontask.resume";
/**
当一个task暂停时就会发送这个通知
*/
static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofire.networking.nsurlsessiontask.suspend";
复制代码
+ (void)load {
/**
WARNING: Trouble Ahead
https://github.com/AFNetworking/AFNetworking/pull/2702
*/
// 判断是否有NSURLSessionTask这个类
if (NSClassFromString(@"NSURLSessionTask")) {
/**
NSURLSessionTask的实如今iOS 7和iOS 8中有所不一样,这使得下面代码实现起来有些棘手。
已经作了许多单元测试来验证这个方法的可行性。
目前咱们所知道的是:
- NSURLSessionTasks是经过类簇设计模式实现的,这就意味着你经过这个类提供的接口得到的类并非这个类。
- 简单的经过 ‘[NSURLSessionTask class]’ 方法并不起做用,你须要经过NSURLSession建立一个task,才能获取它所在的类。
- 在iOS 7中,‘localDataTask’是的类型是‘__NSCFLocalDataTask’,它的继承关系是:__NSCFLocalDataTask -> __NSCFLocalSessionTask -> __NSCFURLSessionTask。
- 在iOS 8中,‘localDataTask’是的类型是‘__NSCFLocalDataTask’,它的继承关系是:__NSCFLocalDataTask -> __NSCFLocalSessionTask -> NSURLSessionTask。
- 在iOS 7中,只有‘__NSCFLocalSessionTask’和其父类‘__NSCFURLSessionTask’这两个类实现了它们的‘resume’和‘suspend’方法,而且在方法实现里‘__NSCFLocalSessionTask’类并无调用其父类的方法,这就意味着两个类都要进行方法交换。
- 在iOS 8中,只有‘NSURLSessionTask’类实现了‘resume’和‘suspend’方法,这就意味着只对该类进行方法交换便可。
- 由于‘NSURLSessionTask’类并非在每一个iOS的版本中都存在,全部在这个虚构类里能够更容易添加和管理交换方法
一些假设前提:
- ‘resume’和‘suspend’方法在实现时,并无调用其父类的实现方法。但若是在之后的iOS版本中调用了其父类的实现方法,咱们还要再进行处理。
- ‘resume’和‘suspend’方法不会被其余类复写
目前的解决方案:
1) 先经过‘NSURLSession’实例化一个dataTask对象,再经过dataTask对象获取‘__NSCFLocalDataTask’对象。
2) 获取指向‘af_resume’方法原始实现的指针。
3) 检查当前类是否实现了resume方法,若是实现了就继续执行第4步
4) 获取当前类的父类
5) 获取当前类指向‘resume’方法实现的指针。
6) 获取当前类的父类指向‘resume’方法实现的指针。
7) 若是当前类和其父类指向‘resume’方法实现的指针不一致,而且当前类指向‘resume’方法实现的指针和指向‘af_resume’方法原始实现的指针也不一致,就进行方法交换
8) 而后再经过步骤3-8检查其父类
*/
// 实例化网络会话配置对象
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
// 实例化网络会话对象
NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration];
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
// 实例化网络会话任务对象
NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil];
#pragma clang diagnostic pop
// 获取指向当前类的af_resume方法原始实现的指针
IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume)));
// 获取网络会话任务对象的具体类
Class currentClass = [localDataTask class];
// 若是这个具体类实现了resume方法则进入循环体
while (class_getInstanceMethod(currentClass, @selector(resume))) {
// 获取这个具体类的父类
Class superClass = [currentClass superclass];
// 获取指向这个具体类的resume方法实现的指针
IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume)));
// 获取指向这个具体类的父类的resume方法实现的指针
IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector(resume)));
// 若是指向这个具体类的resume方法实现的指针,和指向其的父类的resume方法实现的指针,以及指向当前类的af_resume方法原始实现的指针,都不一致
if (classResumeIMP != superclassResumeIMP &&
originalAFResumeIMP != classResumeIMP) {
// 向当前这个具体类添加af_resume和af_suspend方法,并与其resume和suspend方法做交换
[self swizzleResumeAndSuspendMethodForClass:currentClass];
}
// 获取当前这个具体类的父类,继续循环判断其父类
currentClass = [currentClass superclass];
}
// 取消这个网络会话任务
[localDataTask cancel];
// 当即结束这个网络会话
[session finishTasksAndInvalidate];
}
}
/**
为一个了动态添加af_resume和af_suspend方法,并与之对应的resume和suspend作交换
*/
+ (void)swizzleResumeAndSuspendMethodForClass:(Class)theClass {
// 获取本类的af_resume和af_suspend方法
Method afResumeMethod = class_getInstanceMethod(self, @selector(af_resume));
Method afSuspendMethod = class_getInstanceMethod(self, @selector(af_suspend));
// 若是想目标类中成功添加了af_resume方法
if (af_addMethod(theClass, @selector(af_resume), afResumeMethod)) {
// 交换目标类的resume和af_resume方法
af_swizzleSelector(theClass, @selector(resume), @selector(af_resume));
}
// 若是想目标类中成功添加了af_suspend方法
if (af_addMethod(theClass, @selector(af_suspend), afSuspendMethod)) {
// 交换目标类的suspend和af_suspend方法
af_swizzleSelector(theClass, @selector(suspend), @selector(af_suspend));
}
}
- (NSURLSessionTaskState)state {
NSAssert(NO, @"State method should never be called in the actual dummy class");
return NSURLSessionTaskStateCanceling;
}
- (void)af_resume {
// 获取NSURLSessionDataTask对象的state属性,并调用其resume方法
NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
NSURLSessionTaskState state = [self state];
[self af_resume];
// 若是在调用重启方法以前的状态不是正常运行状态,就发送通知
if (state != NSURLSessionTaskStateRunning) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self];
}
}
- (void)af_suspend {
// 获取NSURLSessionDataTask对象的state属性,并调用其suspend方法
NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
NSURLSessionTaskState state = [self state];
[self af_suspend];
// 若是在调用暂停方法以前的状态不是暂停状态,就发送通知
if (state != NSURLSessionTaskStateSuspended) {
[[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidSuspendNotification object:self];
}
}
复制代码
读完这个私有类后,发现一个问题:就是_AFURLSessionTaskSwizzling
并无被调用,甚至没有出如今其余代码的任何一个地方,这就很奇怪。既然没有调用,写了这么一大堆代码是怎么起做用的呢?通过查阅资料发现:当类被引用进项目的时候就会执行load函数(在main函数开始执行以前),与这个类是否被用到无关,每一个类的load函数只会自动调用一次。
要是想要进一步了解有关load方法的话,能够看这篇文章:iOS类方法load和initialize详解,若是想要深刻了解的话能够看这篇文章:你真的了解load方法么?设计模式
/**
保存网络会话配置对象
*/
@property (readwrite, nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
/**
保存回调操做队列对象
*/
@property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue;
/**
保存网络会话对象
*/
@property (readwrite, nonatomic, strong) NSURLSession *session;
/**
保存AFURLSessionManagerTaskDelegate对象和task之间的联系
*/
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;
/**
保存task的taskDescription属性值,在代码中被设置成当前对象的地址值
*/
@property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks;
/**
保存锁对象,这个锁用来保证对mutableTaskDelegatesKeyedByTaskIdentifier存取的线程安全
*/
@property (readwrite, nonatomic, strong) NSLock *lock;
/**
保存session无效时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
/**
保存session接收到验证请求时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
/**
保存session队列中全部的消息都发送出去时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
/**
保存一个HTTP请求试图执行重定向到一个不一样的URL时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
/**
保存task接收到身份验证时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge;
/**
保存task须要一个新的输入流时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
/**
保存一个来按期跟踪上传进度的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
/**
保存task执行完成时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
/**
保存dataTask接收到响应时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
/**
保存dataTask变成downloadTask时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
/**
保存dataTask接收到数据时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
/**
保存dataTask将要对响应进行缓存时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse;
/**
保存downloadTask完成一个下载时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
/**
保存一个来按期跟踪下载进度的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData;
/**
保存downloadTask从新开始下载时的block回调
*/
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume;
复制代码
- (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;
// 实例化一个操做队列并设置最大并发数为1
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
// 经过上面生成的两个对象实例化网络会话对象
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
// 实例化可变字典关联task和其AFURLSessionManagerTaskDelegate对象,使其一一对应
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
// 实例化锁对象,确保上面的可变字典存取线程安全
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;
}
- (void)dealloc {
// 移除通知观察者
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
复制代码
/**
获取当前AFURLSessionManager对象的地址字符串赋值给task的taskDescription属性,目的是经过这个字符串来判断通知监听到的是不是当前AFURLSessionManager对象所拥有的task发出的
*/
- (NSString *)taskDescriptionForSessionTasks {
return [NSString stringWithFormat:@"%p", self];
}
复制代码
/**
当task已经重启的时候会经过通知调用这个方法
*/
- (void)taskDidResume:(NSNotification *)notification {
// 从通知对象中获取到发送这条通知的task
NSURLSessionTask *task = notification.object;
// 若是这个task属于这个AFURLSessionManager对象
if ([task respondsToSelector:@selector(taskDescription)]) {
if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
// 主线程异步发送通知task已经重启
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task];
});
}
}
}
/**
当task已经暂停的时候会经过通知调用这个方法
*/
- (void)taskDidSuspend:(NSNotification *)notification {
// 从通知对象中获取到发送通知的task
NSURLSessionTask *task = notification.object;
// 若是这个task属于这个AFURLSessionManager对象
if ([task respondsToSelector:@selector(taskDescription)]) {
if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
dispatch_async(dispatch_get_main_queue(), ^{
// 主线程异步发送通知task已经暂停
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task];
});
}
}
}
复制代码
/**
经过task对象获取其绑定的AFURLSessionManagerTaskDelegate对象
*/
- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
// 在debug下,缺乏task参数就crash
NSParameterAssert(task);
// 在线程安全的环境下,经过task的taskIdentifier属性,从mutableTaskDelegatesKeyedByTaskIdentifier属性中获取绑定的delegate
AFURLSessionManagerTaskDelegate *delegate = nil;
[self.lock lock];
delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];
[self.lock unlock];
return delegate;
}
/**
为task绑定delegate
*/
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
// 在debug下,缺乏参数就crash
NSParameterAssert(task);
NSParameterAssert(delegate);
// 在线程安全的环境下
[self.lock lock];
// 以task的taskIdentifier属性为key,以delegate为value,保存到mutableTaskDelegatesKeyedByTaskIdentifier属性中。
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
// 添加通知监听task的重启和暂停事件
[self addNotificationObserverForTask:task];
[self.lock unlock];
}
/**
为dataTask绑定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
{
// 经过dataTask实例化delegate对象,并初始化属性
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
delegate.manager = self;
delegate.completionHandler = completionHandler;
// 标记dataTask所属的AFURLSessionManager对象
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
// 为dataTask绑定delegate
[self setDelegate:delegate forTask:dataTask];
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
/**
为uploadTask绑定delegate
*/
- (void)addDelegateForUploadTask:(NSURLSessionUploadTask *)uploadTask
progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
// 经过uploadTask实例化delegate对象,并初始化属性
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:uploadTask];
delegate.manager = self;
delegate.completionHandler = completionHandler;
// 标记uploadTask所属的AFURLSessionManager对象
uploadTask.taskDescription = self.taskDescriptionForSessionTasks;
// 为uploadTask绑定delegate
[self setDelegate:delegate forTask:uploadTask];
delegate.uploadProgressBlock = uploadProgressBlock;
}
/**
为downloadTask绑定delegate
*/
- (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
// 经过downloadTask实例化delegate对象,并初始化属性
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:downloadTask];
delegate.manager = self;
delegate.completionHandler = completionHandler;
// 若是设置了保存下载文件的路径,就赋值给delegate
if (destination) {
delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
return destination(location, task.response);
};
}
// 标记downloadTask所属的AFURLSessionManager对象
downloadTask.taskDescription = self.taskDescriptionForSessionTasks;
// 为downloadTask绑定delegate
[self setDelegate:delegate forTask:downloadTask];
delegate.downloadProgressBlock = downloadProgressBlock;
}
/**
移除task绑定的delegate
*/
- (void)removeDelegateForTask:(NSURLSessionTask *)task {
// 在debug下,缺乏参数就crash
NSParameterAssert(task);
// 在线程安全的环境下
[self.lock lock];
// 移除对task观察的通知
[self removeNotificationObserverForTask:task];
// 从mutableTaskDelegatesKeyedByTaskIdentifier移除task
[self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)];
[self.lock unlock];
}
复制代码
/**
经过传入的不一样类型task的名称获取相应的tasks
*/
- (NSArray *)tasksForKeyPath:(NSString *)keyPath {
// 建立临时变量保存获取到的tasks
__block NSArray *tasks = nil;
// 建立信号量,由于getTasksWithCompletionHandler这个方法是异步获取tasks,为了不还没获取到tasks就返回,就使用信号量进行控制
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
// 根据传入的不一样类型task的名称获取相应的tasks
if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) {
tasks = dataTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) {
tasks = uploadTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) {
tasks = downloadTasks;
} else if ([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) {
// 利用valueForKeyPath合并数组并保留重复值
tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"];
}
// 发送一个信号量,使semaphore变为1,表示已经获取到tasks,能够向下执行
dispatch_semaphore_signal(semaphore);
}];
// 等待信号量变为1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return tasks;
}
/**
获取当前AFURLSessionManager对象的全部tasks
*/
- (NSArray *)tasks {
return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
}
/**
获取当前AFURLSessionManager对象的全部dataTasks
*/
- (NSArray *)dataTasks {
return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
}
/**
获取当前AFURLSessionManager对象的全部uploadTasks
*/
- (NSArray *)uploadTasks {
return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
}
/**
获取当前AFURLSessionManager对象的全部downloadTasks
*/
- (NSArray *)downloadTasks {
return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
}
复制代码
经过tasksForKeyPath:
方法的实现,咱们能够学到如何利用GCD的信号量将异步回调转换为同步执行数组
/**
当传YES,就当即关闭当前网络会话;当传NO,等待当前任务完成后再关闭当前对话
*/
- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks {
if (cancelPendingTasks) {
[self.session invalidateAndCancel];
} else {
[self.session finishTasksAndInvalidate];
}
}
复制代码
- (void)setResponseSerializer:(id <AFURLResponseSerialization>)responseSerializer {
// 在debug下,缺乏参数就crash
NSParameterAssert(responseSerializer);
// 保存设置的参数
_responseSerializer = responseSerializer;
}
复制代码
/**
向task添加观察通知
*/
- (void)addNotificationObserverForTask:(NSURLSessionTask *)task {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidResume:) name:AFNSURLSessionTaskDidResumeNotification object:task];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidSuspend:) name:AFNSURLSessionTaskDidSuspendNotification object:task];
}
/**
移除task的观察通知
*/
- (void)removeNotificationObserverForTask:(NSURLSessionTask *)task {
[[NSNotificationCenter defaultCenter] removeObserver:self name:AFNSURLSessionTaskDidSuspendNotification object:task];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AFNSURLSessionTaskDidResumeNotification object:task];
}
复制代码
在以前看过的那个私有类_AFURLSessionTaskSwizzling
中,AFNetworking
交换了task
的resume
和suspend
方法。缓存
以resume
方法为例说明其内部实现,当调用task
的resume
方法时,实际上调用的是af_resume
方法。安全
在af_resume
方法中,又调用了af_resume
方法,实际上调用的是系统的resume
方法,同时发送了通知AFNSURLSessionTaskDidResumeNotification
。bash
当前AFURLSessionManager
对象经过观察接收到通知后,就调用taskDidResume:
方法。
在taskDidResume:
方法中判断触发的resume
方法是当前AFURLSessionManager
对象所持有的task
后,在主线程异步发送AFNetworkingTaskDidResumeNotification
通知,告诉外界这个task
重启了。
经过这一系列的处理,能够看出AFNetworking
想要实现的,其实就是想在原来方法的功能上,添加向外发送通知功能,已达到监听的目的。只不过因为苹果在不一样系统版本上对NSURLSessionTask
这个类的内部实现不一样,以及类簇的设计模式,致使了实现起来“a bit tricky”
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
// 调用下面的方法
return [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:completionHandler];
}
- (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 {
// 安全的经过传入的request建立一个dataTask
__block NSURLSessionDataTask *dataTask = nil;
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
// 为dataTask绑定AFURLSessionManagerTaskDelegate对象,以监听dataTask的处理进度和处理数据
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
复制代码
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromFile:(NSURL *)fileURL
progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
// 安全的经过传入的request和fileURL建立一个uploadTask
__block NSURLSessionUploadTask *uploadTask = nil;
url_session_manager_create_task_safely(^{
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
// 在iOS7上可能会建立失败
// uploadTask may be nil on iOS7 because uploadTaskWithRequest:fromFile: may return nil despite being documented as nonnull (https://devforums.apple.com/message/926113#926113)
// 若是没有建立成功,且容许从新建立,且NSURLSessionConfiguration对象是经过backgroundSessionConfigurationWithIdentifier:方法建立的,就重复尝试三次
if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) {
for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) {
uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
}
}
});
// 为uploadTask绑定AFURLSessionManagerTaskDelegate对象,以监听uploadTask的处理进度和处理数据
if (uploadTask) {
[self addDelegateForUploadTask:uploadTask
progress:uploadProgressBlock
completionHandler:completionHandler];
}
return uploadTask;
}
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromData:(NSData *)bodyData
progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
// 安全的经过传入的request和bodyData建立一个uploadTask
__block NSURLSessionUploadTask *uploadTask = nil;
url_session_manager_create_task_safely(^{
uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData];
});
// 为uploadTask绑定AFURLSessionManagerTaskDelegate对象,以监听uploadTask的处理进度和处理数据
[self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];
return uploadTask;
}
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
// 安全的经过传入的request建立一个uploadTask
__block NSURLSessionUploadTask *uploadTask = nil;
url_session_manager_create_task_safely(^{
uploadTask = [self.session uploadTaskWithStreamedRequest:request];
});
// 为uploadTask绑定AFURLSessionManagerTaskDelegate对象,以监听uploadTask的处理进度和处理数据
[self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];
return uploadTask;
}
复制代码
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
// 安全的经过传入的request建立一个downloadTask
__block NSURLSessionDownloadTask *downloadTask = nil;
url_session_manager_create_task_safely(^{
downloadTask = [self.session downloadTaskWithRequest:request];
});
// 为downloadTask绑定AFURLSessionManagerTaskDelegate对象,以监听downloadTask的处理进度和处理数据
[self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];
return downloadTask;
}
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
// 安全的经过传入的resumeData重启一个downloadTask
__block NSURLSessionDownloadTask *downloadTask = nil;
url_session_manager_create_task_safely(^{
downloadTask = [self.session downloadTaskWithResumeData:resumeData];
});
// 为downloadTask绑定AFURLSessionManagerTaskDelegate对象,以监听downloadTask的处理进度和处理数据
[self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];
return downloadTask;
}
复制代码
- (NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task {
return [[self delegateForTask:task] uploadProgress];
}
- (NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task {
return [[self delegateForTask:task] downloadProgress];
}
复制代码
这两个方法都是先经过传入的task
参数获取到与之绑定的AFURLSessionManagerTaskDelegate
对象,再经过AFURLSessionManagerTaskDelegate
对象获取其监听的进度数据
- (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block {
self.sessionDidBecomeInvalid = block;
}
- (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block {
self.sessionDidReceiveAuthenticationChallenge = block;
}
复制代码
- (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block {
self.taskNeedNewBodyStream = block;
}
- (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block {
self.taskWillPerformHTTPRedirection = block;
}
- (void)setTaskDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block {
self.taskDidReceiveAuthenticationChallenge = block;
}
- (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block {
self.taskDidSendBodyData = block;
}
- (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block {
self.taskDidComplete = block;
}
复制代码
- (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block {
self.dataTaskDidReceiveResponse = block;
}
- (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block {
self.dataTaskDidBecomeDownloadTask = block;
}
- (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block {
self.dataTaskDidReceiveData = block;
}
- (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block {
self.dataTaskWillCacheResponse = block;
}
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block {
self.didFinishEventsForBackgroundURLSession = block;
}
复制代码
- (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block {
self.downloadTaskDidFinishDownloading = block;
}
- (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block {
self.downloadTaskDidWriteData = block;
}
- (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block {
self.downloadTaskDidResume = block;
}
复制代码
- (NSString *)description {
// 定制打印数据
return [NSString stringWithFormat:@"<%@: %p, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, self.session, self.operationQueue];
}
- (BOOL)respondsToSelector:(SEL)selector {
// 若是没有对相应的block进行赋值,也不会去调用实现相应的代理
if (selector == @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)) {
return self.taskWillPerformHTTPRedirection != nil;
} else if (selector == @selector(URLSession:dataTask:didReceiveResponse:completionHandler:)) {
return self.dataTaskDidReceiveResponse != nil;
} else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) {
return self.dataTaskWillCacheResponse != nil;
} else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
return self.didFinishEventsForBackgroundURLSession != nil;
}
return [[self class] instancesRespondToSelector:selector];
}
复制代码
/**
当session无效时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
didBecomeInvalidWithError:(NSError *)error
{
// 调用block回调数据
if (self.sessionDidBecomeInvalid) {
self.sessionDidBecomeInvalid(session, error);
}
// 发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session];
}
/**
当session接收到验证请求时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
// 设置临时变量保存数据
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
// 若是经过block回调传入了证书处理方式,则直接传参
if (self.sessionDidReceiveAuthenticationChallenge) {
disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential);
// 若是没有传入证书处理方式
} else {
// 若是验证方式为NSURLAuthenticationMethodServerTrust
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
// 若是经过了当前类安全策略的验证
if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
// 生成证书
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
// 若是有证书的话就使用指定证书验证,不然就用默认方式验证
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
// 若是没有经过当前类安全策略的验证
} else {
// 不须要验证证书了
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
// 若是验证方式不是NSURLAuthenticationMethodServerTrust,也使用默认方式验证证书
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
}
// 回调结果
if (completionHandler) {
completionHandler(disposition, credential);
}
}
复制代码
/**
当一个HTTP请求试图执行重定向到一个不一样的URL时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest *))completionHandler
{
NSURLRequest *redirectRequest = request;
// 若是经过block传入重定向的处理方式,就传参调用
if (self.taskWillPerformHTTPRedirection) {
redirectRequest = self.taskWillPerformHTTPRedirection(session, task, response, request);
}
// 回调结果
if (completionHandler) {
completionHandler(redirectRequest);
}
}
/**
当task接收到身份验证时,会调用这个代理方法。这个证书验证的处理方式和上面那个如出一辙,只不过上面那个是session级别的,这个是task级别的
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
// 设置临时变量保存数据
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
// 若是经过block传入了证书处理方式,则直接传参调用
if (self.taskDidReceiveAuthenticationChallenge) {
disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential);
// 若是没有传入证书处理方式
} else {
// 若是验证方式为NSURLAuthenticationMethodServerTrust
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;
}
// 若是验证方式不是NSURLAuthenticationMethodServerTrust,就使用默认方式验证证书
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
}
// 回调结果
if (completionHandler) {
completionHandler(disposition, credential);
}
}
/**
当task须要一个新的输入流时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
{
// 建立临时变量保存数据
NSInputStream *inputStream = nil;
// 若是经过block回调传入获取输入流的方式,就传参调用
if (self.taskNeedNewBodyStream) {
inputStream = self.taskNeedNewBodyStream(session, task);
// 不然若是task中原有输入流,就用原有输入流
} else if (task.originalRequest.HTTPBodyStream && [task.originalRequest.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
inputStream = [task.originalRequest.HTTPBodyStream copy];
}
// 回调结果
if (completionHandler) {
completionHandler(inputStream);
}
}
/**
当task已经发送出数据时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
// 建立临时变量保存数据
int64_t totalUnitCount = totalBytesExpectedToSend;
// 若是数据总大小获取失败
if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
// 经过请求头中的“Content-Length”字段获取大小
NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"];
if(contentLength) {
totalUnitCount = (int64_t) [contentLength longLongValue];
}
}
// 获取与task绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// 调用delegate对象所实现相同的代理方法来监听进度
if (delegate) {
[delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend];
}
// 调用block回调数据
if (self.taskDidSendBodyData) {
self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount);
}
}
/**
当task执行完成时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
// 获取与task绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// 加判断的缘由是,在后台结束这个task时,其delegate可能会被置nil
// delegate may be nil when completing a task in the background
if (delegate) {
// 调用delegate对象所实现相同的代理方法来处理结果
[delegate URLSession:session task:task didCompleteWithError:error];
// 移除对task监听的通知和其绑定的delegate
[self removeDelegateForTask:task];
}
// 调用block回调数据
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
复制代码
/**
当dataTask接收到响应时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
// 建立临时变量保存接收到数据后的处理模式
NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
// 若是经过block传入了处理方式,则传参调用
if (self.dataTaskDidReceiveResponse) {
disposition = self.dataTaskDidReceiveResponse(session, dataTask, response);
}
// 回调结果
if (completionHandler) {
completionHandler(disposition);
}
}
/**
当dataTask变成downloadTask时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
{
// 获取与dataTask绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
if (delegate) {
// 把delegate从dataTask上解绑,而后绑定到downloadTask
[self removeDelegateForTask:dataTask];
[self setDelegate:delegate forTask:downloadTask];
}
// 调用block回调数据
if (self.dataTaskDidBecomeDownloadTask) {
self.dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask);
}
}
/**
当dataTask接收到数据时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data
{
// 获取与dataTask绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
// 调用delegate对象所实现相同的代理方法来处理结果
[delegate URLSession:session dataTask:dataTask didReceiveData:data];
// 调用block回调数据
if (self.dataTaskDidReceiveData) {
self.dataTaskDidReceiveData(session, dataTask, data);
}
}
/**
当dataTask将要对响应进行缓存时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler
{
// 建立临时变量保存要缓存的相应对象
NSCachedURLResponse *cachedResponse = proposedResponse;
// 若是经过block传入了处理方式,则传参调用
if (self.dataTaskWillCacheResponse) {
cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse);
}
// 回调结果
if (completionHandler) {
completionHandler(cachedResponse);
}
}
/**
当session队列中全部的消息都发送出去时,会调用这个代理方法
*/
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
// 主队列异步回调结果
if (self.didFinishEventsForBackgroundURLSession) {
dispatch_async(dispatch_get_main_queue(), ^{
self.didFinishEventsForBackgroundURLSession(session);
});
}
}
复制代码
/**
当downloadTask完成一个下载时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
// 获取与downloadTask绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
// 若是经过block传入了处理方式
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;
}
}
// 调用delegate对象所实现相同的代理方法来处理结果
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
}
}
/**
downloadTask下载时的按期回调代理
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
// 获取与downloadTask绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
// 调用delegate对象所实现相同的代理方法来处理数据
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didWriteData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
}
// 调用block回调数据
if (self.downloadTaskDidWriteData) {
self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}
}
/**
当downloadTask从新开始下载时,会调用这个代理方法
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
// 获取与downloadTask绑定的delegate对象
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
// 调用delegate对象所实现相同的代理方法来处理数据
if (delegate) {
[delegate URLSession:session downloadTask:downloadTask didResumeAtOffset:fileOffset expectedTotalBytes:expectedTotalBytes];
}
// 调用block回调数据
if (self.downloadTaskDidResume) {
self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
}
}
复制代码
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];
self = [self initWithSessionConfiguration:configuration];
if (!self) {
return nil;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"];
}
复制代码
关于NSSecureCoding
代理方法的实如今AFNetworking源码阅读(二)——从AFURLRequestSerialization入手这篇文章中的4.1.2.4.7 NSSecureCoding协议方法的实现段落已经介绍过。
- (instancetype)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithSessionConfiguration:self.session.configuration];
}
复制代码
到这里,AFURLSessionManager
这个类咱们就看完了。能够看出该类是负责管理NSURLSession
对象,建立各类类型的task
,并监听其属性的状态,处理代理和返回的数据。
源码阅读系列: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