日常文章学习

AFNetworking-数据流程

2017-08-15  本文已影响34人  烧烤有点辣

AFNetworking


AFNetWorking基本上是所有iOS项目的标配。现在升级带最新版的3.X了。得益于苹果从NSURLConnection升级到NSURLSession,AFN也实现了api的简化,同时功能却一点没少。我们来看一下AFN3.X的目录结构:

我们在看AFNetworking内部时候,首先我们先搞清什么是NSURLSession,苹果原生的请求是如何运行的。

NSURLSession


Session.png
从图中我们可以看出在NSURLSession中比较重要的几个对象,一个是NSURLSessionTaskNSURLSessionConfiguration,还有的为它请求时执行的代理方法。 NSURLSessionTask.png

从这几个子类的名字就可以大概猜出他们的作用了.接下来我们就从不同类型的任务出发,来使用session.
使用NSURLSession,拢共分两步:

  1. 通过NSURLSession的实例创建task
  2. 通过task选择自己所需要的方法,有Delegate方法Block方法
  3. 执行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的父类。这类中控制所有NSURLSession的代理数据回调AFHTTPSessionManager是对外面做一个接口的显示,对于外部方便调用和请求的数据的处理,还有就是让AFURLSessionManager专门只需要负责数据的回调和处理工作。
首先我们从这个AFURLSessionManager核心类说起

D0832F85-DF51-47BD-999E-764B13E56E39.png
上一篇 下一篇

猜你喜欢

热点阅读