你要知道的NSURLSession都在这里
转载请注明出处 http://blog.youkuaiyun.com/u014205968/article/details/78481498
本系列文章主要讲解iOS中网络请求类NSURLSession的使用方法进行详解,同时也会以此为扩展,讲解SDWebImage中图片下载功能的源码分析,讲解AFNetworking相关源码分析。本系列文章主要分为以下几篇进行讲解,读者可按需查阅。
- iOS网络——NSURLSession详解及SDWebImage源码解析
- iOS网络——SDWebImage SDImageDownloader源码解析
- iOS网络——AFNetworking AFURLSessionManager源码解析
- iOS网络——AFNetworking AFHttpSessionManager源码解析
AFNetworking AFURLSessionManager源码解析
前面几篇文章讲解了NSURLSession
的基础使用方法以及SDWebImage
在下载图片时是如何使用NSURLSession
,来完成下载任务的,本篇文章将阅读AFNetworking
是如何封装NSURLSession
来提供便捷的网络请求功能。
AFNetworking
的使用方法就不赘述了,我们经常使用AFHttpSessionManager
来发起一个GET
或是POST
请求,该类是继承自AFURLSessionManager
并在其上进行了一个封装,提供了更加便捷的接口来发起网络请求,所以本篇将详细讲解AFURLSessionManager
是如何封装NSURLSession
的,建议读者对照源码阅读。
首先看一下头文件的声明:
//AFURLSessionManager类实现了NSURLSession相关的众多协议,用于帮助我们进行数据的处理
@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>
//猪脚,NSURLSession 作为一个实例变量,AFN发起的网络请求都是通过该session创建的task实现的
@property (readonly, nonatomic, strong) NSURLSession *session;
//NSURLSession delegate方法执行队列
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;
//响应序列化,不是本系列文章的关注点,有兴趣的读者可以自行阅读源码
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
///-------------------------------
/// @name Managing Security Policy
///-------------------------------
//安全策略,用于https等需要验证的地方
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;
#if !TARGET_OS_WATCH
///--------------------------------------
/// @name Monitoring Network Reachability
///--------------------------------------
//监测网络连通性,使用AFNetworkReachabilityManager,读者可自行阅读相关源码
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
#endif
///----------------------------
/// @name Getting Session Tasks
///----------------------------
//前面那个session管理的data upload download task的集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;
//前面那个session管理的data task的集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;
//前面那个session管理的upload task的集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;
//前面那个session管理的download task的集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;
///-------------------------------
/// @name Managing Callback Queues
///-------------------------------
//完成网络请求后执行回调块的队列,如果为nil则使用主队列
@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;
//完成网络请求后回调块的
@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;
///---------------------------------
/// @name Working Around System Bugs
///---------------------------------
//background类型的session是否尝试重新创建上传任务
@property (nonatomic, assign) BOOL attemptsToRecreateUploadTasksForBackgroundSessions;
///---------------------
/// @name Initialization
///---------------------
//初始化函数,根据指定NSURLSessionConfiguration创建session
- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
//设置session无效,cancelPendingTasks标识是否取消session中正在执行的任务
//内部还是调用NSURLSession的invalidate方法
- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks;
///-------------------------
/// @name Running Data Tasks
///-------------------------
//根据指定的request等信息创建一个NSURLSessionDataTask任务
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler DEPRECATED_ATTRIBUTE;
//根据指定的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;
///---------------------------
/// @name Running Upload Tasks
///---------------------------
//根据指定request fileURL等参数构造一个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;
//根据指定request和data等参数构造一个上传任务
- (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;
//根据指定的request构造一个上传任务
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
///-----------------------------
/// @name Running Download Tasks
///-----------------------------
//构造下载任务
- (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 *)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;
///---------------------------------
/// @name Getting Progress for Tasks
///---------------------------------
//根据NSURLSessionTask获取对应的任务完成进度NSProgress
- (nullable NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task;
//根据NSURLSessionTask获取对应下载任务的进度NSProgress
- (nullable NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task;
///-----------------------------------------
/// @name Setting Session Delegate Callbacks
///-----------------------------------------
//设置session无效时执行的回调块
- (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block;
//设置session收到challenge时执行的回调块
- (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
///--------------------------------------
/// @name Setting Task Delegate Callbacks
///--------------------------------------
//设置session需要新的流时执行的回调块
- (void)setTaskNeedNewBodyStreamBlock:(nullable NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block;
//设置session的任务需要执行重定向时执行的回调块
- (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * _Nullable (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block;
//又是代理方法执行时需要执行的回调块
- (void)setTaskDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
//同上
- (void)setTaskDidSendBodyDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block;
//同上
- (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * _Nullable error))block;
///-------------------------------------------
/// @name Setting Data Task Delegate Callbacks
///-------------------------------------------
/**
Sets a block to be executed when a data task has received a response, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveResponse:completionHandler:`.
@param block A block object to be executed when a data task has received a response. The block returns the disposition of the session response, and takes three arguments: the session, the data task, and the received response.
*/
- (void)setDataTaskDidReceiveResponseBlock:(nullable NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block;
//同上
- (void)setDataTaskDidBecomeDownloadTaskBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block;
//同上
- (void)setDataTaskDidReceiveDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block;
//同上
- (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block;
//同上
- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block;
///-----------------------------------------------
/// @name Setting Download Task Delegate Callbacks
///-----------------------------------------------
//同上
- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * _Nullable (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block;
//同上
- (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block;
//同上
- (void)setDownloadTaskDidResumeBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block;
@end
///--------------------
/// @name Notifications
///--------------------
//一些通知的名称,使用FOUNDATION_EXPORT标识
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteNotification;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidSuspendNotification;
FOUNDATION_EXPORT NSString * const AFURLSessionDidInvalidateNotification;
FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseDataKey;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey;
FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey;
NS_ASSUME_NONNULL_END
通过头文件可以发现,AFURLSessionManager
是封装了NSURLSession
并实现了其相关的所有协议,提供了一系列方法用于构造各种网络请求任务,并提供回调块进行处理,还提供了一系列设置代理方法执行时的执行回调块的方法,这样,我们也可以监听整个网络请求的过程,当然也可以忽略这些代理方法执行情况,提供了各种通知,通过头文件可以看出,主要目的还是为了封装NSURLSession
从而提供更加便捷的方法来实现网络请求。
接下来看一下实现的文件:
//C静态函数,GCD只执行一次,用于创建一个串行队列来执行各种网络请求任务的创建工作
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.creat