当前位置:   article > 正文

AFNetworking网路请求源码精讲(四) — Download下载任务_afnetworking downloadtaskwithrequest

afnetworking downloadtaskwithrequest

NSURLSessionDownloadTask

前面三篇,分析了关于AFNetworking的GET和POST请求方法,以及AFNetworking将系统的协议封装成为了一个AFNetworking自己的DataTaskDelegate的方法。通过本篇AFNetworking,我们将分析AFNetworking下载任务操作。

NSURLSessionDownloadTask
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
                                             progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                                          destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                                    completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
    __block NSURLSessionDownloadTask *downloadTask = nil;
    url_session_manager_create_task_safely(^{
        downloadTask = [self.session downloadTaskWithRequest:request];
    });

    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];

    return downloadTask;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

通过系统提供的NSURLSession实力化对象创建一个下载任务,传入的是一个下载路径的请求request。

这里面,我们稍微关心一下url_session_manager_create_task_safely是做了什么操作???

static void url_session_manager_create_task_safely(dispatch_block_t _Nonnull block) {
    if (block != NULL) {
        if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
            // Fix of bug
            // Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
            // Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
            dispatch_sync(url_session_manager_creation_queue(), block);
        } else {
            block();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在创建下载任务的时候,block块不为空,因此,通过创建了同步线程阻塞线程来创建一个下载任务作业,我们不难看出,在GET和POST到现在的下载任务,凡事关于到下载数据请求的AFNetworking多做了线程安全处理,这是一个很好的操作。

思考:为什么不直接在下载任务中使用dispatch_sync()而要疯转一个AFURLSessionManager???
个人认为,其实直接使用是没用问题的,只是无疑的,但是面对AFNetworking,多个需要考虑线程安全问题的框架,使用一个SessionManager来管理线程安全显得尤为重要,这样可以提高代码的重用性。

最后,在返回下载任务之前,添加下载协议。

- (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
                          progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                       destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                 completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:downloadTask];
    delegate.manager = self;
    delegate.completionHandler = completionHandler;

    if (destination) {
        delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
            return destination(location, task.response);
        };
    }

    downloadTask.taskDescription = self.taskDescriptionForSessionTasks;

    [self setDelegate:delegate forTask:downloadTask];

    delegate.downloadProgressBlock = downloadProgressBlock;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在协议中,我们进行了数据的保存,包括管理者身份,完成的回调,任务的描述等。
这样就基本实现了下载功能。

上传操作和下载操作大同小异,就不再这里赘述了。

回顾AFNetworking

如果是从第一篇坚持看到这里,那么AFNetworking的基本网络请求过程就会有大概的印象。在AFNetworking中,小编觉得有以下部分是值得我们去学习和借鉴的:

  1. 首当其冲的就是线程安全。
    我们知道,Objective-C不像Swift let一样具有线程安全,因此,在网络请求时候,如果不加同步锁会产生严重的问题。AFNetworking通过GCD来实现线程安全问题。
  2. 对协议的封装,通常,我们使用到协议的地方有UITextView,UITableView,UICollectionView,网络请求,蓝牙请求等都会用到协议,如果,我们需要封装这些功能,面对协议我们就可以效仿AFNetworking,将协议利用一个自定义类进行封装,通过协议来赋值给自定义中的属性。然后,在外部就可以直接调用成员属性来实现代理的效果。这样的好处无疑是使得代码更加高效紧凑。
  3. 大量的错误判断处理,AFNetworking作为网络请求的框架,在网络请求的同时会面对多种错误问题,AFNetworking通过大量的判断来进行错误处理,这个在对于开发中的错误处理给予了方向。
  4. Block块使用,从开始写RAC,到Masonry,再到AFNetworking,我们无处不用到Block,对于Block,我相信大家已经不具有恐惧心里,相反会喜欢上Block的使用,AFNetworking在使用Block调用时候,会先判断是否Block有值,如果有则调用,否则,不调用,这个设计思路也是我们可以借鉴的。
预告篇

下一篇,我们将介绍AFNetworking判断设备的联网状态源码分析,并且,会分析AFNetworking缓存图片进行介绍。尽可能理解缓存机制的做法。

中文源码下载

AFNetworking中文源码:GitHub.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/629981
推荐阅读
  

闽ICP备14008679号