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

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

通过系统提供的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();
        }
    }
}

在创建下载任务的时候,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;
}

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

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

回顾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.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值