AFNetworking(AFURLSessionManager)

AFNetworking2.0和3.0有什么区别?
2.0使用的NSURLConnection,3.0使用的是NSURLSession
那么NSURLSesstion和NSURLConnection有什么区别:

1、下载任务时:
NSURLConnection会先放在内存、最后写入沙盒。可能引起内存暴涨。
NSURLSession会直接写在沙盒和tem文件夹中、最后需要手动转移。
2、请求控制:
NSURLConnection创建好了对象、便开始网络请求。
只能cancel并不能恢复。
NSURLSession则在挂起状态需要手动resume。
可以取消(cancel)、暂停(suspend)、继续(resume)。
3、断点续传:
NSURLConnection通过设置访问请求的HTTPHeaderField的Range属性、继续下载剩余的部分。
NSURLSession通过将任务暂停时候代理返回的resumeData传入downloadTaskWithResumeData:方法进行续传。
4、配置信息:
NSURLConnection只能全局配置。
NSURLSession每一个实例都可以通过NSURLSessionConfiguration进行配置。

AF3.x是基于NSURLSession来封装的,其核心是网络通信模块AFURLSessionManager
AFN经pod导入后的目录为:

  • AFNetworking.h : afn的头文件,外部仅需导入此头文件即可调用afn的相关内容
  • NSURLSession文件: 存放网络通讯模块,包含(AFURLSessionManager、AFHTTPSessionManger)
  • Reachability文件: 存放监听网络状态的模块(AFNetworkReachabilityManager)
  • Security文件: 存放网络通信安全策略模块(AFSecurityPolicy)
  • Serialization文件: 存放对网络通讯信息序列化/反序列化的模块(AFURLRequestSerialization、- - AFURLResponseSerialization)
  • UIKit文件: 存放uikit一些类扩展等。
    在这里插入图片描述
    NSURLSession文件中包含AFURLSessionManager和AFHTTPSessionManager这2个类,
    其中AFHTTPSessionManager是AFURLSessionManager的子类。
    先看下AFURLSessionManager这个类:
    ​ AFURLSessionManager 这个文件是核心类,基本上通过它来实现了大部分核心功能。负责请求的建立、管理、销毁、安全、请求重定向、请求重启等各种功能。他主要实现了NSURLSession和NSRULSessionTask的封装。

在AFURLSessionManager.h文件中,我们发现了它创建了NSURLSession这个对象。
我们基于NSURLSession来写一个简单的网络请求和上传。

- (void)NSURLSessionFuc{
    
    NSString *urlStr = @"http://api.androidhive.info/volley/person_object.json";
    NSURL *url = [NSURL URLWithString:urlStr];
    //1.请求地址url
    //2.缓存策略
    //3.请求超时时间
    //4.请求request.HTTPBody\request.HTTPMethod
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30];

    /*  配置
     1.NSURLSessionConfiguration为NSURLSession配置一些请求所需要的策略。如:
     超时、缓存策略、链接需求的
     2.defaultSessionConfiguration:默认配置使用的是持久化的硬盘缓存,
     存储证书到用户钥匙链。存储cookie到shareCookie。
     3.ephemeralSessionConfiguration:返回一个不适用永久持存cookie、证书、缓存的配置,
     最佳优化数据传输。
     */
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    //创建NSURLSession对象并添加配置
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    
    //创建会话任务
    /*
     创建会话任务后,根据请求url和配置的一些策略,开启任务,服务器返回data数据
     */
    NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"data=%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    //开启会话任务,创建后的NSURLSessionTask需要调用resume才会执行
    [task resume];
}

//打印结果为:
data={
	"name" : "Ravi Tamada", 
	"email" : "ravi8x@gmail.com",
	"phone" : {
		"home" : "08947 000000",
		"mobile" : "9999999999"
	}
}

可以看出,创建一个网络请求,我们的NSRULSession 网络请求系统包括一个session、一个configuration、一个Task已经Task附带的delegate。

一个NSURLSession,总共只有一个类,也是最核心的类,他有一个对应的代理NSURLSessionDelegate。
一个NSURLSessionConfiguration,总共有三种模式。
一个NSURLSessionTask。NSURLSessionTask是抽象类,对应的代理NSURLSessionTaskDelegate。我们具体使用的时候,会使用他的三种子类,而且每个子类都有对应的delegate

我们可以看看NSRULSession.h这个类关于NSURLSession的部分,可以把这个类分为初始化部分、属性部分、dataTask部分、uploadTask部分、downloadTask部分。也就是说其他很多类都是围绕着下面这几个api衍生的

整体api

//初始化部分
@property (class, readonly, strong) NSURLSession *sharedSession;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;

//属性部分
@property (readonly, retain) NSOperationQueue *delegateQueue;
@property (nullable, readonly, retain) id <NSURLSessionDelegate> delegate;
@property (readonly, copy) NSURLSessionConfiguration *configuration;

//dataTask部分
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;

//uploadTask部分
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;

//downloadTask部分
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;

我们都知道,NSRULConnection除了一套使用代理的API,还有一套对应的使用Block的api。NSURLSession也不列外。使用这一套api就不用实现代理方法。和delegate一样,Block也有dataTask系列、downloadTask系列、uploadTask系列。具体看下面:

//dataTask系列
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}
//unloadTast系列
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}
//downloadTask系列
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
	
}

Block的NSURLSession使用
用dataTask下载一张图片,然后用imageView显示。

-(IBAction)requestBlockTaskTest:(id)sender{
    [self clear];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:bigPic]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        UIImage *image = [[UIImage alloc]initWithData:data];
        self.imageView.image = image;
    }];
    [dataTask resume];
}
NSURLSessionConfiguration

首先看一下NSURLSessionConfiguration部分。这个是与session的配置相关的,共有三种类型的configuratin,另外还有很多属性,比如配置缓存策略的requestCachePolicy,请求超时的timeoutIntervalForRequest,添加额外请求头的HTTPAdditionalHeaders,其他还有很多属性这里就不一一说了,具体看源码:

//默认的配置会将缓存存储在磁盘上
@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
//第二种瞬时会话模式不会创建持久性存储的缓存.
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;
//第三种后台会话模式允许程序在后台进行上传下载工作
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;
//各种属性
@property NSURLRequestCachePolicy requestCachePolicy;
@property NSTimeInterval timeoutIntervalForRequest;
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;

NSURLSessionTask
从上面NSURLSession初始化一个请求的时候,我们发现NSURLSessionTask并不能直接使用,只能使用他的子类。具体如下:

NSURLSessionTask抽象类。有对应的代理NSURLSessionTaskDelegate,而且这个代理继承了NSURLSessionDelegate代理。
NSURLSessionDataTask是NSURLSessionTask的子类。有对应的代理NSURLSessionTaskDelegate,而且这个代理继承了NSURLSessionTaskDelegate代理。我们一般网络请求,就用这个类。
NSURLSessionDownloadTask是NSURLSessionTask的子类。有对应的代理NSURLSessionDownloadDelegate,而且这个代理继承了NSURLSessionTaskDelegate代理。这个主要用于下载大文件等。
NSURLSessionUploadTask是NSURLSessionDataTask的子类。有对应的代理及时父类代理NSURLSessionDownloadDelegate。这个主要用于处理上传请求如上传图片。
从上面我们发现Task和delegate有一套对应的继承关系:
在这里插入图片描述
从继承关系上,我们就可以理解在初始化的时候,只通过设置NSURLSession对象的delegate就可以了。因为根据不同的task,其实就是设置了不同的delegate。这个设计避免了多次设置delegate的情况,同时也根据不同的task实现不同的delegate方法。真是一个很绝妙的设计。
代理说明 (NSURLSessionDelegate)
接下来我们看看NSURLSession的delegate对象NSURLSessionDelegate的方法,当一个session遇到错误、或者需要认证、应用进入后台都会调用下面的代理方法:

//当一个session遇到系统错误或者未检测到的错误的时候,就会调用这个方法。
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error{

}
//当请求需要认证、或者https证书认证的时候,我们就需要在这个方法里面处理。
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
    
}
//如果应用进入后台、这个方法会被调用。我们在这里可以对session发起的请求做各种操作比如请求完成的回调等。
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {

}

NSURLSessionTaskDelegate

/*
 当请求重定向的时候调用这个方法。我们必须设置一个新的`NSURLRequest`对象传入completionHandler来重定向新的请求,但是当`session`是background模式的时候,这个方法不会被调用。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request
 completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler{

}
/*
 当请求需要认证的时候调用这个方法。如果没有实现这个代理,那么请求认证这个过程不会被调用。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{

}
/*
    如果请求需要一个新的请求体时,这个方法就会被调用。比如认证失败的时候,我们可以通过这个机会从新认证。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
 needNewBodyStream:(void (^)(NSInputStream * _Nullable bodyStream))completionHandler{

}
/*
 当我们上传数据的时候,我们可以通过这个代理方法获取上传进度。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{

}
/*
 当task的统计信息收集好了以后,调用这个方法。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {

}
/*
 当一个task出错的时候,会调用这个方法。如果error是nil,也会调用这个方法,表示task完成。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error{
	NSLog(@"数据返回以后,不管有错没错都回调用,如果没错,error及时nil");
}

NSURLSessionDataDelegate

/*
 当一个task接收到返回信息。当所有信息都接收完毕以后,completionHandler会被调用。我们可以在这里取消一个网络请求或者把一个datatask转换为downloadtask。如果没有实现这个代理方法,我们也可以通过task的response属性获取到对应的数据。background模式的uploadtask不会调用这个方法。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{

}
/*
 当一个datatask转换为一个downloadtask以后会调用。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask{
	// 允许处理服务器的响应,才会继续接收服务器返回的数据
    completionHandler(NSURLSessionResponseAllow);
}
/*
 暂时忽略,这个是和数据流相关的。不管了
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask{

}
/*
 当data可以使用的时候,调用这个方法。我们可以在这里获取data。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data{

}
/*
 允许我们在这里调用completionHandler缓存data,或者传入nil来禁止缓存
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
 willCacheResponse:(NSCachedURLResponse *)proposedResponse
 completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler{

}

NSURLSessionDownloadDelegate

/*
    当一个下载task任务完成以后,这个方法会被调用。我们可以在这里移动或者复制download的数据
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{

}
/*
 获取下载进度
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{

}
/*
 重启一个下载任务(比如下载一半后停止然后过一点时间继续)。如果下载出错,`NSURLSessionDownloadTaskResumeData`里面包含重新开始下载的数据。
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{

}

AFURLSessionManager类
现在继续看AFURLSessionManager这个类,先看.h文件

//为NSURLSession 绑定一个队列。并且设置这个队列的最大并发数maxConcurrentOperationCount为1.
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;
//这是序列化响应数据的对象,默认的模式是AFJSONResponseSerializer,而且不能为空。
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
//安全策略,默认是defaultPolicy。
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;
//监听网络状态
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
//当前被管理的包括data upload download 任务的集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;
//当前被管理的data任务集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;
//当前被管理的upload任务集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;
//当前被管理的download任务集合
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;
//用于处理任务回调的GCD对象,默认是dispatch_main_queue。
@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;
//用于处理任务回调的GCD的group对象,如果不初始化、则一个默认的Group被使用。
@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;
//创建一个NSURLSessionDataTask
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler DEPRECATED_ATTRIBUTE;
//创建一个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;
//创建一个上传Task,并且指定上传文件的路径。
- (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;
//创建一个上传Task,并且指定上传的数据。
- (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;
//创建一个uploadTask,然后上传数据
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
                                                 progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
                                        completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
//新建一个download任务,destination表示的下载文件的缓存路径
- (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;
//继续恢复一个download任务。resumeData参数表示的是恢复下载的时候初始化数据,比如前面已经下载好的部分数据。
- (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;

AFURLSessionManager的实现分析
AFURLSessionManager.m文件里面除了有AFURLSessionManager.h定义的各种接口的实现意外,还有处理不同iOS版本下NSRULSession不同的部分,以及多个全局dispatch_queue_t的定义、以及处理NSURLSeesionTash的各种代理方法的实现和处理。具体划分如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值