该文章阅读的AFNetworking的版本为3.2.0。

这个分类提供了对请求周期进行控制的方法,包括进度监控、成功和失败的回调。

1.接口文件

1.1.属性

/**网络会话管理者对象*/
@property (nonatomic, strong) AFHTTPSessionManager *sessionManager;
复制代码

1.2.方法

/**异步加载指定请求*/
- (void)loadRequest:(NSURLRequest *)requestprogress:(NSProgress * _Nullable __autoreleasing * _Nullable)progresssuccess:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))successfailure:(nullable void (^)(NSError *error))failure;/**以指定MIME类型和指定文本编码格式异步加载指定请求*/
- (void)loadRequest:(NSURLRequest *)requestMIMEType:(nullable NSString *)MIMETypetextEncodingName:(nullable NSString *)textEncodingNameprogress:(NSProgress * _Nullable __autoreleasing * _Nullable)progresssuccess:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))successfailure:(nullable void (^)(NSError *error))failure;
复制代码

2.UIWebView+_AFNetworking私有分类

2.1.接口

/**保存任务对象*/
@property (readwrite, nonatomic, strong, setter = af_setURLSessionTask:) NSURLSessionDataTask *af_URLSessionTask;
复制代码

2.2.实现

这两个方法就是通过Runtime的关联对象为分类添加属性保存任务对象

- (NSURLSessionDataTask *)af_URLSessionTask {return (NSURLSessionDataTask *)objc_getAssociatedObject(self, @selector(af_URLSessionTask));
}- (void)af_setURLSessionTask:(NSURLSessionDataTask *)af_URLSessionTask {objc_setAssociatedObject(self, @selector(af_URLSessionTask), af_URLSessionTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
复制代码

3.方法实现

  • 属性的访问方法

下面的这四个方法同样是通过关联对象为分类添加属,分别是保存网络会话管理者对象和响应序列化对象

- (AFHTTPSessionManager  *)sessionManager {static AFHTTPSessionManager *_af_defaultHTTPSessionManager = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_af_defaultHTTPSessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];_af_defaultHTTPSessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];_af_defaultHTTPSessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];});return objc_getAssociatedObject(self, @selector(sessionManager)) ?: _af_defaultHTTPSessionManager;
}- (void)setSessionManager:(AFHTTPSessionManager *)sessionManager {objc_setAssociatedObject(self, @selector(sessionManager), sessionManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (AFHTTPResponseSerializer <AFURLResponseSerialization> *)responseSerializer {static AFHTTPResponseSerializer <AFURLResponseSerialization> *_af_defaultResponseSerializer = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_af_defaultResponseSerializer = [AFHTTPResponseSerializer serializer];});return objc_getAssociatedObject(self, @selector(responseSerializer)) ?: _af_defaultResponseSerializer;
}- (void)setResponseSerializer:(AFHTTPResponseSerializer<AFURLResponseSerialization> *)responseSerializer {objc_setAssociatedObject(self, @selector(responseSerializer), responseSerializer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
复制代码
  • 接口方法实现
- (void)loadRequest:(NSURLRequest *)requestprogress:(NSProgress * _Nullable __autoreleasing * _Nullable)progresssuccess:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))successfailure:(void (^)(NSError *error))failure
{// 调用下面的方法[self loadRequest:request MIMEType:nil textEncodingName:nil progress:progress success:^NSData *(NSHTTPURLResponse *response, NSData *data) {// 设置字符编码方式为UTF8NSStringEncoding stringEncoding = NSUTF8StringEncoding;// 如果响应对象有文本编码方式,就将字符编码方式设置为响应的文本编码方式if (response.textEncodingName) {CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);if (encoding != kCFStringEncodingInvalidId) {stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding);}}// 将返回的数据进行编码NSString *string = [[NSString alloc] initWithData:data encoding:stringEncoding];// 如果设置了成功回调就调用block传递数据if (success) {string = success(response, string);}// 将字符串编码成二进制数据后返回return [string dataUsingEncoding:stringEncoding];} failure:failure];
}- (void)loadRequest:(NSURLRequest *)requestMIMEType:(NSString *)MIMETypetextEncodingName:(NSString *)textEncodingNameprogress:(NSProgress * _Nullable __autoreleasing * _Nullable)progresssuccess:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))successfailure:(void (^)(NSError *error))failure
{// 在debug模式下缺少参数就crashNSParameterAssert(request);// 如果当前已经有任务正在进行或者已经暂停,就取消掉这个任务,并将保存它的属性置空if (self.af_URLSessionTask.state == NSURLSessionTaskStateRunning || self.af_URLSessionTask.state == NSURLSessionTaskStateSuspended) {[self.af_URLSessionTask cancel];}self.af_URLSessionTask = nil;// 生成任务__weak __typeof(self)weakSelf = self;__block NSURLSessionDataTask *dataTask;dataTask = [self.sessionManagerdataTaskWithRequest:requestuploadProgress:nildownloadProgress:nilcompletionHandler:^(NSURLResponse * _Nonnull response, id  _Nonnull responseObject, NSError * _Nullable error) {__strong __typeof(weakSelf) strongSelf = weakSelf;// 如果出错就调用失败回调blockif (error) {if (failure) {failure(error);}// 如果成功} else {// 先调用成功回调blockif (success) {success((NSHTTPURLResponse *)response, responseObject);}// 调用UIWebView加载本地数据的方式进行加载页面[strongSelf loadData:responseObject MIMEType:MIMEType textEncodingName:textEncodingName baseURL:[dataTask.currentRequest URL]];// 调用UIWebView代理中的完成加载方法if ([strongSelf.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {[strongSelf.delegate webViewDidFinishLoad:strongSelf];}}}];// 用属性保存任务对象self.af_URLSessionTask = dataTask;// 如果设置了进度对象,就获取到网络会话管理者的下载进程对象if (progress != nil) {*progress = [self.sessionManager downloadProgressForTask:dataTask];}// 启动任务[self.af_URLSessionTask resume];// 调用UIWebView代理中的开始加载方法if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {[self.delegate webViewDidStartLoad:self];}复制代码

4.总结

看完这个分类的源码,我们可以看到这个分类做的事就是,手动实现了UIWebView加载网络数据的过程,从而可以监听进度和通过block回调处理成功与失败的结果。

通常,我们会使用loadRequest:方法加载指定页面,然后通过UIWebViewDelegate中的方法监听网页加载的开始、结束与失败。

而这个分类,通过AFHTTPSessionManager类手动生成NSURLSessionDataTask对象下载网页的二进制数据,然后通过loadData: MIMEType: textEncodingName: baseURL:方法加载已经下载到本地的网页的二进制数据。在这个过程中通过AFHTTPSessionManager类中已经实现的方法实现进度的监控、成功和失败的回调。

源码阅读系列:AFNetworking

源码阅读:AFNetworking(一)——从使用入手

源码阅读:AFNetworking(二)——AFURLRequestSerialization

源码阅读:AFNetworking(三)——AFURLResponseSerialization

源码阅读:AFNetworking(四)——AFSecurityPolicy

源码阅读:AFNetworking(五)——AFNetworkReachabilityManager

源码阅读:AFNetworking(六)——AFURLSessionManager

源码阅读:AFNetworking(七)——AFHTTPSessionManager

源码阅读:AFNetworking(八)——AFAutoPurgingImageCache

源码阅读:AFNetworking(九)——AFImageDownloader

源码阅读:AFNetworking(十)——AFNetworkActivityIndicatorManager

源码阅读:AFNetworking(十一)——UIActivityIndicatorView+AFNetworking

源码阅读:AFNetworking(十二)——UIButton+AFNetworking

源码阅读:AFNetworking(十三)——UIImageView+AFNetworking

源码阅读:AFNetworking(十四)——UIProgressView+AFNetworking

源码阅读:AFNetworking(十五)——UIRefreshControl+AFNetworking

源码阅读:AFNetworking(十六)——UIWebView+AFNetworking

源码阅读:AFNetworking(十六)——UIWebView+AFNetworking相关推荐

  1. Soul网关源码阅读(十)自定义简单插件编写

    Soul网关源码阅读(十)自定义简单插件编写 简介     综合前面所分析的插件处理流程相关知识,此次我们来编写自定义的插件:统计请求在插件链中的经历时长 编写准备     首先我们先探究一下,一个P ...

  2. Go-Excelize API源码阅读(十九)——SetHeaderFooter

    Go-Excelize API源码阅读(十九)--SetHeaderFooter 开源摘星计划(WeOpen Star) 是由腾源会 2022 年推出的全新项目,旨在为开源人提供成长激励,为开源项目提 ...

  3. php网页游戏学习之xnova(ogame)源码解读,PHP网页游戏学习之Xnova(ogame)源码解读(十六)...

    PHP网页游戏学习之Xnova(ogame)源码解读(十六) 作者:bea 十九.攻击任务(MissionCaseAttack.php) 按照舰队任务的编号,排在第一个的就是攻击任务.这个代码很长,看 ...

  4. Spark修炼之道(高级篇)——Spark源码阅读:第六节 Task提交

    Task提交 在上一节中的 Stage提交中我们提到,最终stage被封装成TaskSet,使用taskScheduler.submitTasks提交,具体代码如下: taskScheduler.su ...

  5. 【转】ABP源码分析四十六:ABP ZERO中的Ldap模块

    通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供Defaut ...

  6. 【转】ABP源码分析三十六:ABP.Web.Api

    这里的内容和ABP 动态webapi没有关系.除了动态webapi,ABP必然是支持使用传统的webApi.ABP.Web.Api模块中实现了一些同意的基础功能,以方便我们创建和使用asp.net w ...

  7. 【转】ABP源码分析二十六:核心框架中的一些其他功能

    本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSess ...

  8. ABP源码分析三十六:ABP.Web.Api

    这里的内容和ABP 动态webapi没有关系.除了动态webapi,ABP必然是支持使用传统的webApi.ABP.Web.Api模块中实现了一些同意的基础功能,以方便我们创建和使用asp.net w ...

  9. 第二人生的源码分析(二十六)底层网络协议

    为了理解第二人生的客户端与服务器的沟通,那么下面就来分析一下第二人生采用的网络协议.在目前的网络里,主要有两个协议:TCP和UDP,而第二人生里是采用UDP协议.TCP协议与UDP协议的主要区别,就是 ...

  10. skywalking源码分析第十六篇一agent端JVMService之度量上报

    文章目录 原理图 原理图一基于MXBean进行Metrics数据收集 源码分析一JVMService 总结 原理图 通过prepare构建Metrics存储缓冲队列 初始化grpc客户端 通过boot ...

最新文章

  1. Linux中ifreq 结构体分析和使用
  2. VScode Python插件
  3. 主页面功能的java_6-04-项目实战-主页面显示当前用户退出功能实现
  4. java堆和客栈_JAVA中堆、栈,静态方法和非静态方法的速度问题
  5. ROS Nodelet使用
  6. fisco bcos应用开发(一) springboot报错 Error reading resource
  7. 不学点《近世代数》怎么学好现代密码学
  8. Multisim卸载后重新安装不上解决方案
  9. ApacheCN 活动汇总 2019.8.23
  10. 一键下载QQ空间相册
  11. SaaS已死。下一个。
  12. linux恢复误删除文件
  13. 按钮样式动态切换js
  14. 使用ETE包让系统发育树(进化树)和多重序列比对(MSA)“同框”
  15. luffy-(12)
  16. 5G/NR 随机接入过程之PRACH时域资源
  17. 第 16 章 string类和标准模板库
  18. Google全系列产品不再信任赛门铁克某款根证书
  19. php仿u8系统模板_中文分词源码_7urpu8 采用php的源码实现 - 下载 - 搜珍网
  20. vue IE下验证码无法显示解决方法

热门文章

  1. C++实现tar包解析
  2. 【Qt】Qt源码中涉及到的设计模式
  3. 【Qt】调用Python函数:无参数、单个参数、多个参数、数组参数
  4. 【imx6】Unable to find the ncurses libraries的解决办法
  5. webkit内核 css,纯CSS改变webkit内核浏览器的滚动条样式
  6. uniapp 鸿蒙,关于前端:uniapp项目安装运行操作手册
  7. alexnet训练多久收敛_如何将深度学习训练速度提升一百倍?PAISoar 来了
  8. 正向最大匹配算法 python代码_中文分词算法之最大正向匹配算法(Python版)
  9. Mybatis入门:4(多表查询操作)
  10. Java学习总结:24