AFNetworking
AFNetWorking基本上是所有iOS项目的标配。现在升级带最新版的3.X了。得益于苹果从NSURLConnection升级到NSURLSession,AFN也实现了api的简化,同时功能却一点没少。我们来看一下AFN3.X的目录结构:
- AFNetWorking 这个文件是一个头文件。啥也没做,就是引入了其他文件方便使用。
- AFURLSessionManager 这个文件是核心类,基本上通过它来实现了大部分核心功能。负责请求的建立、管理、销毁、安全、请求重定向、请求重启等各种功能。他主要实现了NSURLSession和NSRULSessionTask的封装。
- AFHTTPSessionManager 这个文件是AFURLSessionManager的子类。主要实现了对HTTP请求的优化。
- AFURLRequestSerialization 这个主要用于请求头的编码解码、序列化、优化处理、简化请* 求拼接过程等。
- AFURLResponseSerialization 这个主要用于网络返回数据的序列化、编码解码、序列化、数据处理等。
- AFSecurityPolicy 这个主要用于请求的认证功能。比如https的认证模式等。
- AFNetworkReachabilityManager 这个主要用于监听网络请求状态变化功能。
我们在看AFNetworking内部时候,首先我们先搞清什么是NSURLSession,苹果原生的请求是如何运行的。
NSURLSession
Session.png
从图中我们可以看出在NSURLSession中比较重要的几个对象,一个是NSURLSessionTask和NSURLSessionConfiguration,还有的为它请求时执行的代理方法。 NSURLSessionTask.png
从这几个子类的名字就可以大概猜出他们的作用了.接下来我们就从不同类型的任务出发,来使用session.
使用NSURLSession,拢共分两步:
- 通过NSURLSession的实例创建task
- 通过task选择自己所需要的方法,有Delegate方法和Block方法
- 执行task
task一共有4个delegate,只要设置了一个,就代表四个全部设置,有时候一些delegate不会被触发的原因在于这四种delegate是针对不同的URLSession类型和URLSessionTask类型来进行响应的,也就是说不同的类型只会触发这些delegate中的一部分,而不是触发所有的delegate。
通过一个例子来查看下请求一个数据时,数据如何发送和接收到数据。
Block方式接收数据
- (IBAction)orginalDownLoadAction:(UIButton *)sender {
__weak typeof(self) weakself = self;
NSURLSession *session = [self createASession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:[self creatRequest:downURL] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
weakself.showImageView.image = [UIImage imageWithData:data];
});
}];
[dataTask resume];
}
// 创建Session对象
- (NSURLSession *)createASession {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 1;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:operationQueue];
return session;
}
- (NSURLRequest *)creatRequest:(NSString *)url {
NSURLRequest *requset = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
return requset;
}
使用Block很简单,只需要传入请求的Request就可以直接获取到数据。
使用Delegate方式,才可以真正的观测到数据的获取和请求的发送。
- (IBAction)orginalDownLoadAction:(UIButton *)sender {
NSURLSession *session = [self createASession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:downURL]];
[dataTask resume];
}
/**
接收到服务器的响应
*/
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{
_mutableData = [[NSMutableData alloc] init];
// 允许处理服务器的响应,才会继续接收服务器返回的数据
if (completionHandler) {
completionHandler(NSURLSessionResponseAllow);
}
}
/**
接收到服务器的数据(可能调用多次)
*/
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data {
NSLog(@"接收数据返回");
[_mutableData appendData:data];
}
/**
请求成功或者失败(如果失败,error有值)
所有的代理都会执行此代理方法
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error) {
NSLog(@"下载有误 %@",[error localizedDescription]);
}
else {
NSLog(@"完成下载");
__weak typeof(self) weakself = self;
dispatch_async(dispatch_get_main_queue(), ^{
weakself.showImageView.image = [UIImage imageWithData:_mutableData];
});
}
}
如果使用下载downloadTaskWithRequest:
方法会调用别的代理方法
/**
* 写数据
*
* @param session 会话对象
* @param downloadTask 下载任务
* @param bytesWritten 本次写入的数据大小
* @param totalBytesWritten 下载的数据总大小
* @param totalBytesExpectedToWrite 文件的总大小
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
__weak typeof(self) weakself = self;
CGFloat percent = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"执行下载中 %.1lf%%",percent * 100);
dispatch_async(dispatch_get_main_queue(), ^{
[weakself.progressSlider setValue:percent animated:YES];
});
}
/**
下载完成的事件
@param location 数据存放位置,一定要在这个函数返回之前,对数据进行使用,或者保存
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
NSLog(@"完成下载");
}
看完了对于苹果原生的下载流程,接下来我们来看看AFNetworking对于这套流程是做了怎样的处理,如何方便我们使用这套流程。
AFNetworking源码分析
AFNetworking.png
AFNetworking主要模块有个模块:
- AFURLSessionManager
- AFHTTPSessionManager
- AFURLRequestSerialtion
- AFNetworkReachabilityManager
- AFSecurityPolicy
五个模块,其中AFURLSessionManager是核心类,也是AFHTTPSessionManager的父类。这类中控制所有NSURLSession的代理数据回调,AFHTTPSessionManager是对外面做一个接口的显示,对于外部方便调用和请求的数据的处理,还有就是让AFURLSessionManager专门只需要负责数据的回调和处理工作。
首先我们从这个AFURLSessionManager核心类说起
网友评论