请选择 进入手机版 | 继续访问电脑版

AFNetworking拆解分析

AFNetworking拆解分析

代理11:
[Objective-C] 纯文本查看 复制代码
//当我们获取到数据就会调用,会被反复调用,请求到的数据就在这被拼装完整
- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data
{
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
    [delegate URLSession:session dataTask:dataTask didReceiveData:data];
    if (self.dataTaskDidReceiveData) {
        self.dataTaskDidReceiveData(session, dataTask, data);
    }
}

  • 这个方法和上面didCompleteWithError算是NSUrlSession的代理中最重要的两个方法了。
  • 我们转发了这个方法到AF的代理中去,所以数据的拼接都是在AF的代理中进行的。这也是情理中的,毕竟每个响应数据都是对应各个task,各个AF代理的。在AFURLSessionManager都只是做一些公共的处理。
代理12:
[Objective-C] 纯文本查看 复制代码
/*当task接收到所有期望的数据后,session会调用此代理方法。
*/
- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
 willCacheResponse:(NSCachedURLResponse *)proposedResponse
 completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler
{
    NSCachedURLResponse *cachedResponse = proposedResponse;

    if (self.dataTaskWillCacheResponse) {
        cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse);
    }
    if (completionHandler) {
        completionHandler(cachedResponse);
    }
}
官方文档翻译如下:
函数作用:
询问data task或上传任务(upload task)是否缓存response。
函数讨论:
当task接收到所有期望的数据后,session会调用此代理方法。如果你没有实现该方法,那么就会使用创建session时使用的configuration对象决定缓存策略。这个代理方法最初的目的是为了阻止缓存特定的URLs或者修改NSCacheURLResponse对象相关的userInfo字典。
该方法只会当request决定缓存response时候调用。作为准则,responses只会当以下条件都成立的时候返回缓存:
该request是HTTP或HTTPS URL的请求(或者你自定义的网络协议,并且确保该协议支持缓存)
确保request请求是成功的(返回的status code为200-299)
返回的response是来自服务器端的,而非缓存中本身就有的
提供的NSURLRequest对象的缓存策略要允许进行缓存
服务器返回的response中与缓存相关的header要允许缓存
该response的大小不能比提供的缓存空间大太多(比如你提供了一个磁盘缓存,那么response大小一定不能比磁盘缓存空间还要大5%)
  • 总结一下就是一个用来缓存response的方法,方法中调用了我们自定义的Block,自定义一个response用来缓存。
NSURLSessionDownloadDelegate代理13:
[Objective-C] 纯文本查看 复制代码
//下载完成的时候调用

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
    //这个是session的,也就是全局的,后面的个人代理也会做同样的这件事
    if (self.downloadTaskDidFinishDownloading) {

        //调用自定义的block拿到文件存储的地址
        NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
        if (fileURL) {
            delegate.downloadFileURL = fileURL;
            NSError *error = nil;
            //从临时的下载路径移动至我们需要的路径
            [[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error];
            //如果移动出错
            if (error) {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
            }
            return;
        }
    }
    //转发代理
    if (delegate) {
        [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
    }
}
这个方法和之前的两个方法:
[Objective-C] 纯文本查看 复制代码
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)error;
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
  • 总共就这3个方法,被转调到AF自定义delegate中。
  • 方法做了什么看注释应该很简单,就不赘述了。
代理14:
[Objective-C] 纯文本查看 复制代码
//周期性地通知下载进度调用
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    if (self.downloadTaskDidWriteData) {
        self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
    }
}
简单说一下这几个参数:
bytesWritten 表示自上次调用该方法后,接收到的数据字节数
totalBytesWritten表示目前已经接收到的数据字节数
totalBytesExpectedToWrite 表示期望收到的文件总字节数,是由Content-Length header提供。如果没有提供,默认是NSURLSessionTransferSizeUnknown。
代理15:
[Objective-C] 纯文本查看 复制代码
//当下载被取消或者失败后重新恢复下载时调用
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
    //交给自定义的Block去调用
    if (self.downloadTaskDidResume) {
        self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
    }
}
官方文档翻译:
函数作用:
告诉代理,下载任务重新开始下载了。
函数讨论:
如果一个正在下载任务被取消或者失败了,你可以请求一个resumeData对象(比如在userInfo字典中通过NSURLSessionDownloadTaskResumeData这个键来获取到resumeData)并使用它来提供足够的信息以重新开始下载任务。
随后,你可以使用resumeData作为downloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:的参数。当你调用这些方法时,你将开始一个新的下载任务。一旦你继续下载任务,session会调用它的代理方法URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:其中的downloadTask参数表示的就是新的下载任务,这也意味着下载重新开始了。
总结一下:
  • 其实这个就是用来做断点续传的代理方法。可以在下载失败的时候,拿到我们失败的拼接的部分resumeData,然后用去调用downloadTaskWithResumeData:就会调用到这个代理方法来了。
  • 其中注意:fileOffset这个参数,如果文件缓存策略或者最后文件更新日期阻止重用已经存在的文件内容,那么该值为0。否则,该值表示当前已经下载data的偏移量。
  • 方法中仅仅调用了downloadTaskDidResume自定义Block。
至此NSUrlSesssion的delegate讲完了。大概总结下:
  • 每个代理方法对应一个我们自定义的Block,如果Block被赋值了,那么就调用它。
  • 在这些代理方法里,我们做的处理都是相对于这个sessionManager所有的request的。是公用的处理。
  • 转发了3个代理方法到AF的deleagate中去了,AF中的deleagate是需要对应每个task去私有化处理的。
文 /涂耀辉(简书作者)
原文链接:http://www.jianshu.com/p/f32bd79233da





举报 使用道具
| 回复

共 0 个关于本帖的回复 最后回复于 2017-1-12 22:10

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

本文内容不够精彩,我要自己发布

发布新帖

推荐阅读

    拥有的,不仅是技术!还有...
    联系 Email: support.36ji@qq.com

    • 关注酷站官方微博
      了解最新动态

    • 关注酷站微信公众号
      这里有好玩的讯息

    • 加入酷站交流群
      不断在这里成长

    © 2014-2017 36ji网络科技有限公司 . All rights reserved.
    京ICP备14001609号

    Archiver|    
    Powered by Discuz! X3.2 © 2001-2013 Comsenz Inc.
    快速回复 返回顶部 返回列表