iOS网络——AFNetworking AFURLSessionManager源码解析

Posted 这个名字到底好不好

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS网络——AFNetworking AFURLSessionManager源码解析相关的知识,希望对你有一定的参考价值。

你要知道的NSURLSession都在这里

转载请注明出处 http://blog.csdn.net/u014205968/article/details/78481498

本系列文章主要讲解ios中网络请求类NSURLSession的使用方法进行详解,同时也会以此为扩展,讲解SDWebImage中图片下载功能的源码分析,讲解AFNetworking相关源码分析。本系列文章主要分为以下几篇进行讲解,读者可按需查阅。

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.creation", DISPATCH_QUEUE_SERIAL);
    );

    return af_url_session_manager_creation_queue;


/*
C静态函数,用于执行创建网络请求任务的block
主要目的是为了解决ios8以下存在的一个block和task不匹配的bug
上面那个队列也是为了解决这个bug才创建的
具体可查看
Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
*/
static void url_session_manager_create_task_safely(dispatch_block_t block) 
    if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) 
        dispatch_sync(url_session_manager_creation_queue(), block);
     else 
        block();
    


//C静态函数,创建一个并发队列,用于在网络请求任务完成后处理数据的,并发队列实现多线程处理多个请求完成后的数据处理
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;

//C静态函数创建一个dispatch的组
//但在接下来的源码中并没有使用这个组来实现notify等功能,仅仅是将block和组关联了,不太清楚具体用意
//有明白的读者还请不吝赐教
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";

//需要使用的NSLock锁的名称
static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";

//background session重试创建上传任务次数
static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3;

上面的代码定义了一系列GCD队列,根据需求有串行队列和并行队列,串行队列可以解决多线程情况下竞争条件的产生,并发队列可以提高性能,每个队列都有自己的功能,接下来会讲到,接下来定义了各种通知的名称。

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);

上面是一系列回调块的定义,在阅读下面源码的时候可以来找找看具体回调块的参数。

//定义了一个类AFURLSessionManagerTaskDelegate并实现了NSURLSessionTask的相关协议
//通过名称可以猜测,这个类是用于处理NSURLSessionTask相关代理方法的
@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>

//初始化构造函数,需要传入一个关联的task
- (instancetype)initWithTask:(NSURLSessionTask *)task;

//weak修饰的manager
@property (nonatomic, weak) AFURLSessionManager *manager;
//可变data用于存储获取到的网络数据
@property (nonatomic, strong) NSMutableData *mutableData;
//上传进度NSProgress
@property (nonatomic, strong) NSProgress *uploadProgress;
//下载进度NSProgress
@property (nonatomic, strong) NSProgress *downloadProgress;
//下载文件的NSURL
@property (nonatomic, copy) NSURL *downloadFileURL;
//下载完成的回调块
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
//上传进度的回调块
@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
//下载进度的回调块
@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
//网络请求完成的回调块
@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
@end

@implementation AFURLSessionManagerTaskDelegate

//初始化构造函数
- (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];

    //遍历两个上传和下载NSProgress设置一些属性
    __weak __typeof__(task) weakTask = task;
    for (NSProgress *progress in @[ _uploadProgress, _downloadProgress ])
    
        //初始化progress
        progress.totalUnitCount = NSURLSessionTransferSizeUnknown;
        progress.cancellable = YES;
        //设置取消进度的回调块,执行task的cancel方法
        progress.cancellationHandler = ^
            [weakTask cancel];
        ;
        progress.pausable = YES;
        //设置暂停进度的回调块,执行task的suspend方法
        progress.pausingHandler = ^
            [weakTask suspend];
        ;
        //设置重新开始的回调块,执行task的resume方法
        if ([progress respondsToSelector:@selector(setResumingHandler:)]) 
            progress.resumingHandler = ^
                [weakTask resume];
            ;
        
        //progress添加kvo,监听progress的进度fractionCompleted
        [progress addObserver:self
                   forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
                      options:NSKeyValueObservingOptionNew
                      context:NULL]; 
    
    return self;


//析构函数
- (void)dealloc 
    //删除KVO
    [self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
    [self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];


#pragma mark - NSProgress Tracking
//KVO回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context 
    //上次或下载进度有改变时,执行上传或下载进度回调块
   if ([object isEqual:self.downloadProgress]) 
        if (self.downloadProgressBlock) 
            self.downloadProgressBlock(object);
        
    
    else if ([object isEqual:self.uploadProgress]) 
        if (self.uploadProgressBlock) 
            self.uploadProgressBlock(object);
        
    


#pragma mark - NSURLSessionTaskDelegate
//代理方法,网络请求完成或出错
- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error

    //manager用weak修饰,这里strong一下防止manager被释放
    __strong AFURLSessionManager *manager = self.manager;

    __block id responseObject = nil;

    __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    //为userInfo字典设置响应序列化
    userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;

    //Performance Improvement from #2672
    //赋值mutableData到data中,并释放mutableData
    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;
    
    //如果downloadFileURL存在,即是下载任务就设置下载完成后的文件存储url到字典中
    if (self.downloadFileURL) 
        userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
     else if (data) 
    //否则就设置对应的NSData数据到字典中
        userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
    
    //如果网络请求有错误
    if (error) 
        //设置error信息到字典中
        userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
        /*
        这个三目运算符需要解释一下,在其他语言中这么写很可能就是语法错误
        这里的意思就是如果manager.completionGroup存在就使用它
        不存在就使用url_session_manager_completion_group函数返回的group
        后面的三目运算符同理
        所以如果自己不设置manager的completionGroup或completionQueue就会使用默认提供的
        */
        //执行对应的completionHandler回调块
        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];
            //如果是下载任务设置响应数据为文件的url
            if (self.downloadFileURL) 
                responseObject = self.downloadFileURL;
            
            //如果响应对象序列化成功或是文件url就设置相关字典key-value
            if (responseObject) 
                userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
            
            //如果序列化出错,设置相关字典值
            if (serializationError) 
                userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
            
            //同理,在dispatch组中和特定队列执行回调块
            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];
                );
            );
        );
    


#pragma mark - NSURLSessionDataDelegate
//回调方法,收到数据
- (void)URLSession:(__unused NSURLSession *)session
          dataTask:(__unused NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data

    //设置下载进度的相关属性
    self.downloadProgress.totalUnitCount = dataTask.countOfBytesExpectedToReceive;
    self.downloadProgress.completedUnitCount = dataTask.countOfBytesReceived;
    //添加数据到mutableData
    [self.mutableData appendData:data];


//上传任务的回调方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
    //设置上传进度的相关属性
    self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
    self.uploadProgress.completedUnitCount = task.countOfBytesSent;


#pragma mark - NSURLSessionDownloadDelegate

//下载任务的回调方法
//由于NSURLSession的downloadTask直接将文件下载到磁盘沙盒中,所以不需要mutableData自行接收数据
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    //设置下载进度的相关属性
    self.downloadProgress.totalUnitCount = totalBytesExpectedToWrite;
    self.downloadProgress.completedUnitCount = totalBytesWritten;


//恢复下载任务的回调方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
    //设置下载进度的相关属性
    self.downloadProgress.totalUnitCount = expectedTotalBytes;
    self.downloadProgress.completedUnitCount = fileOffset;


//下载任务下载文件完成后的回调方法
//location就是文件下载到磁盘沙盒目录的NSURL
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location

    //设置downloadFileURL为nil
    self.downloadFileURL = nil;
    //如果有下载完成的回调块
    if (self.downloadTaskDidFinishDownloading) 
        //执行该回调块,这个回调块返回一个下载的文件保存的路径URL
        //默认保存在沙盒tmp文件中,可能会被删除,需要持久化时要自己设置一个目录存储
        self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
        //如果需要移动文件的路径使用NSFileManaegr移动
        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];
            
        
    


@end

上面这个类AFURLSessionManagerTaskDelegate具体的源码很简单,主要就是关联一个NSURLSessionTask并实现了相关任务的代理方法用于数据的获取、上传文件和下载文件。需要注意的是NSURLSessionTaskdelegate属性是只读的,只能在使用session创建task的函数中传入代理对象,而且通过源码也没有发现相关代理的设置,所以AFURLSessionManagerTaskDelegate类实现相关代理是为了其他类手动调用相关方法,AFURLSessionManager也实现了这些代理,所以具体的调用是由AFURLSessionManger手动触发的。

接下来的源码中有一部分关于method-swizzling的技术,这一部分由于篇幅问题不打算展开讲解,_AFURLSessionTaskSwizzling类存在的目的就是为了交换NSURLSessionTaskresumesuspend方法的实现,因为iOS7iOS8NSURLSessionTask的父类不同,需要做一些处理,关于method-swizzling技术有兴趣的读者可以阅读iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling

接下来看一下AFURLSessionManager类的实现部分。

@interface AFURLSessionManager ()
//管理的session运行模式,默认情况下使用默认运行模式,defaultConfiguration
@property (readwrite, nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
/*
NSOperation队列,代理方法执行的队列
.h文件里是readonly,所以这里定义一个readwrite用于赋值
*/
@property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue;
//管理的session,readwrite
@property (readwrite, nonatomic, strong) NSURLSession *session;
//可变字典,key是NSURLSessionTask的唯一NSUInteger类型标识,value是对应的AFURLSessionManagerTaskDelgate对象
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;
//只读属性,通过getter返回数据
@property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks;
//NSLock锁
@property (readwrite, nonatomic, strong) NSLock *lock;
//下面是一系列回调块
@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
@property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
@property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
@property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData;
@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume;
@end

上面就是定义了一系列的回调块和一些属性。

@implementation AFURLSessionManager
//构造函数
- (instancetype)init 
    return [self initWithSessionConfiguration:nil];

//构造函数
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration 
    self = [super init];
    if (!self) 
        return nil;
    
    //如果没有指定session运行模式就使用默认的
    if (!configuration) 
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    

    self.sessionConfiguration = configuration;
    //创建代理方法执行的队列,最大并发数为1,即串行队列
    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;
    //创建session,注意代理对象是self
    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
    //创建响应序列化器
    self.responseSerializer = [AFJSONResponseSerializer serializer];
    //设置默认安全策略
    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    //获取网络可达性manager
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
    //创建锁
    self.lock = [[NSLock alloc] init];
    self.lockiOS开发网络数据之AFNetworking使用

iOS开发网络数据之AFNetworking使用

iOS开发篇-AFNetworking网络封装(下载)

iOS开发——Reachability和AFNetworking判断网络连接状态

iOS 网络资源汇总之网络

iOS 网络资源汇总之网络