AFNetworking 实现下载请求的原理过程

news2024/12/27 0:17:07

实现下载的流程

  • 一 生成一个 NSMutableURLRequest
  • 二 创建 NSURLSessionTask
  • 创建 URLSessionTask过程解析
  • 代理方法调用过程
  • 这样设计的原因

一 生成一个 NSMutableURLRequest

   NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:requestUrl parameters:nil error:nil];
        [request setAllHTTPHeaderFields:[self requestHeader]];
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer.timeoutInterval = 15;

二 创建 NSURLSessionTask

        NSURLSessionTask *task = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
            
        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
            NSURL *pathURL = [NSURL URLWithString:[@"file://" stringByAppendingString:filePath]];
            return pathURL;
        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
            if (!error) {
                [self performSelector:@selector(downloadFinish:) withObject:userInfo];
            } else {
                [self handleFailtureResponse:response error:error userInfo:userInfo];
                [self performSelector:@selector(requestFailed:) withObject:userInfo];
            }
        }] ;
        [task resume];

创建 URLSessionTask过程解析

生成 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
{
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
    
    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];

    return downloadTask;
}

由于 NSURLSession的代理是AFURLSessionManager,所以系统的
网络请求相关的代理方法都是由 AFURLSessionManager 实现的,如图
请添加图片描述

@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>

addDelegateForDownloadTask 方法的实现

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

有上面代码可以看出,是创建了一个 AFURLSessionManagerTaskDelegate对象,把请求的完成回调,过程
回调,以及下载完成回调 downloadTaskDidFinishDownloading都传给了该AFURLSessionManagerTaskDelegate对象

又通过下面代码

- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    [self.lock lock];
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}

可以看出,创建的AFURLSessionManagerTaskDelegate对象被放在了 self.mutableTaskDelegatesKeyedByTaskIdentifier这个字典中,并且以
task.taskIdentifier作为key

代理方法调用过程

我们以 - (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location 代理方法为例子

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
    if ([location.pathExtension containsString:@"gif"]) {
        
    }
    
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
    if (self.downloadTaskDidFinishDownloading) {
        NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
        if (fileURL) {
            delegate.downloadFileURL = fileURL;
            NSError *error = nil;
            
            if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error]) {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidMoveFileSuccessfullyNotification object:downloadTask userInfo:nil];
            }

            return;
        }
    }

    if (delegate) {
        [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
    }
}

由以上代码可以看出,在该代理方法中,先获取AFURLSessionManagerTaskDelegate对象,然后让AFURLSessionManagerTaskDelegate 对象执行和代理方法名相同的方法

获取AFURLSessionManagerTaskDelegate对象

- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
    NSParameterAssert(task);

    AFURLSessionManagerTaskDelegate *delegate = nil;
    [self.lock lock];
    delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];
    [self.lock unlock];

    return delegate;
}

请添加图片描述

这样设计的原因

AFNetworking这样设计,就可以是同一个AFURLSessionManager 对象
可以创建多个task,方便管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/974916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【三相太阳能光伏系统控制】在线性和非线性负载条件下模拟额定功率为33kW的三相并网光伏系统,提高电能质量研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

C#,《小白学程序》第十三课:阶乘(Factorial)的计算方法与代码

1 文本格式 /// <summary> /// 阶乘的非递归算法 /// </summary> /// <param name"a"></param> /// <returns></returns> private int Factorial_Original(int a) { int r 1; for (int i a; i > 1; i--) { …

java八股文面试[数据库]——最左匹配原则

最佳左前缀法则 最佳左前缀法则: 如果创建的是联合索引,就要遵循该法则. 使用索引时&#xff0c;where后面的条件需要从索引的最左前列开始使用,并且不能跳过索引中的列使用。 最左匹配原则是什么&#xff1f; 简单来讲&#xff1a;在联合索引中&#xff0c;只有左边的字段被…

线上展厅可以用在哪些行业,线上展厅如何获取访客

引言&#xff1a; 随着数字化时代的到来&#xff0c;线上展厅成为了一种重要的营销工具&#xff0c;适用于多个行业&#xff0c;帮助他们吸引来自不同领域的潜在用户。 一&#xff0e;线上展厅在哪些行业有应用 1.零售行业 线上展厅为零售商提供了一个虚拟展示产品的平台&am…

ERROR 之 SpringMVC开发注解版之版本问题

如果你也和我一样&#xff0c;完全是按照狂神老师的代码来敲的&#xff0c;不用注解版的情况下是不会出错的&#xff0c;但是一用注解版&#xff0c;就出现了404&#xff0c;500的类型的错误。那我真诚的建议你换个jdk版本,再来试试。我试了3遍&#xff0c;事实证明用jdk1.8&am…

Springboot - 13.spring-boot-starter-security集成

&#x1f440;Spring Boot Starter Security 中文文档 Spring Security中文文档 &#x1f440;Spring Boot Starter Security 运行流程 当然可以。首先&#xff0c;我们会将用户存储和认证的流程融入整个Spring Boot Starter Security的使用流程中。以下是当你使用Spring Bo…

30岁成为项目经理有多难?

大家好&#xff0c;我是老原。 “30岁危机”真的是个土到掉渣的话题&#xff0c;但身边奔三的朋友&#xff0c;包括曾经奔三、现在奔四的自己&#xff0c;确实感受到了30岁焦虑。 或许&#xff0c;年龄无罪&#xff0c;30岁和危机真是被大家等的30岁焦虑绑架了。 中国古话说…

JavaScript必须掌握的三大器件:基础语法、BOM和DOM

目录 一、什么是 JavaScript 二、JavaScript 的基础语法 三、什么是JavaScript的BOM 四、什么是JavaScript的DOM 一、什么是 JavaScript JavaScript是一种广泛用于网页上实现交互功能的编程语言。它是一种脚本语言&#xff0c;可以嵌入到HTML页面中&#xff0c;并在浏览器…

食品化妆品核辐射检测

GB 14883.3-2016 GB 14883.3-2016 这次核污水时间&#xff0c;对我们的生活影响是比较大&#xff0c;尤其是未来几十年几百年的伤害最深&#xff0c;因为这是不可磨灭的伤害&#xff0c;无法去除&#xff01; 所以我要抵制日本任何的食物&#xff0c;尤其是海鲜食品&#xff…

Keil Flash的下载算法

更进一步的了解Keil Flash的下载算法 前面提到了通用算法的选择&#xff0c;那么问题来了&#xff0c;这个算法文件如何来的呢&#xff1f;如果你所用的MCU不是默认支持的品牌&#xff0c;如何编写属于自己的算法呢&#xff1f; 工具/原料 Keil uVision ULINK2仿真器 方法/…

连接云-边-端,构建火山引擎边缘云网技术体系

近日&#xff0c;火山引擎边缘云网络产品研发负责人韩伟在LiveVideoStack Con 2023上海站围绕边缘云海量分布式节点和上百T的网络规模&#xff0c;结合边缘云快速发展期间遇到的各种问题和挑战&#xff0c;分享了火山引擎边缘云网的全球基础设施&#xff0c;融合开放的云网技术…

69、配置AWS服务,接收来自RTSP流的推送

基本思想:在上一篇的基础和视频教程之后,进行简单的aws服务,进行RTSP流的接收 第一步: 第二步:配置video_stream,记得选择香港节点 同时记录这个信息,后面的策略需要填充 第三步:进行策略设置 第四步:策略设置,选中右上角的创建策略 第五步、进行json填充 第六步:填…

程序产生自我意识,创造人工生命

偶然发现一个大佬研究了一个很有意思的项目&#xff0c;研究了好几年&#xff0c;让程序产生自我意识诞生人工生命&#xff0c;感觉10年后肯定是继Chart GPT之后的又一个风口&#xff0c;在这里记录一下分享给大家&#xff0c;这个项目在git上有开源&#xff0c;开源地址&#…

CC-TDOB01 CC-TDIL01 有效地监控和管理热工设备

CC-TDOB01 CC-TDIL01 有效地监控和管理热工设备 新兴的互联工厂技术是霍尼韦尔启动其43的亮点注册营养师霍尼韦尔用户组(HUG)美洲研讨会&#xff0c;重点是向制造商展示数字化转型如何帮助他们实现更高水平的高性能。 来自石油和天然气、化工、纸浆和造纸以及金属和采矿行业的…

亚马逊重大更新,底层卖家的机会来了(干货)

最近&#xff0c;亚马逊对产品详细页面进行了又一次的改版。在这次改版中&#xff0c;亚马逊调整了产品详细页面的五点描述显示&#xff0c;无论是在电脑端还是移动端&#xff0c;大部分产品的五点描述都被折叠。 亚马逊的这一举动可能会改变传统的流量分配方式&#xff0c;进一…

Wasm软件生态系统安全分析

本文转载自 OpenHarmony TSC 官方微信公众号《峰会回顾第12期 | Wasm软件生态系统安全分析》 演讲嘉宾 | 王浩宇 回顾整理 | 廖 涛 排版校对 | 李萍萍 嘉宾简介 王浩宇&#xff0c;华中科技大学教授&#xff0c;博士生导师&#xff0c;华中科技大学OpenHarmony技术俱乐部主任…

vmware设置桥接模式后ip设置

网络连接方式设置 找到虚拟机里机器的网络设置 左边是宿主机&#xff0c;右边是虚拟机&#xff0c;按照这个设置就可以上网了(IP指定一个没有占用的值&#xff0c;子网掩码和网关设置成一样的)就可以联网了。 over~~

leetcode1288. 删除被覆盖区间(java)

删除被覆盖区间 题目描述贪心法代码演示 题目描述 难度 - 中等 leetcode1288. 删除被覆盖区间 给你一个区间列表&#xff0c;请你删除列表中被其他区间所覆盖的区间。 只有当 c < a 且 b < d 时&#xff0c;我们才认为区间 [a,b) 被区间 [c,d) 覆盖。 在完成所有删除操作…

Error: Cannot find module ‘timers/promises‘

这个错误很要命 他会导致你本机所有的npm 命令全部报错 首先 这个错误是因为 npm 与 node版本不匹配导致的 最简单的办法就是 查一下你安装的这个npm 的版本适配那个版本的 node 然后将本地的node删除 控制面板写在node 然后去官方文档现在与本地npm 匹配的node.js 这样 你执行…

健康舒适的超满意照明体验!SUKER书客SKY护眼台灯测评

健康舒适的超满意照明体验&#xff01;SUKER书客SKY护眼台灯测评 2022年全国儿童青少年总体近视率为53.6%&#xff0c;其中6岁儿童为14.5%&#xff0c;小学生为36%&#xff0c;初中生为71.6%&#xff0c;高中生为81%&#xff0c;近视已成为当下人们遇到的比较普遍的眼健康问题…