当前位置: 首页 > news >正文

AFNetworking 源码阅读

AFNetworking 3.1.0

AFNetworking 主要的几个类或协议:

  • AFURLSessionManager
  • AFHTTPSessionManager
  • AFNetworkReachabilityManager
  • AFSecurityPolicy
  • <AFURLRequestSerialization>
  • <AFURLResponseSerialization>

AFHTTPSessionManager

AFHTTPSessionManager 是我们使用 AFNetworking 框架最外层或者是可以直接使用的类,它对于框架核心类 AFURLSessionManager 进行了常用的封装。比如设置 BaseURL 和请求序列化,AFHTTPSessionManager 重要的两个属性:

@property (readonly, nonatomic, strong, nullable) NSURL *baseURL;
@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer
复制代码

当发送一个 GET 请求时,框架会依次调用以下三个方法:

[AFHTTPSessionManager GET:parameters:progress:success:failure:] [AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:] [AFURLSessionManager dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:]

第一个方法是 AFHTTPSessionManagerGETPOSTPUTPATCHDELETE 等请求做的一个封装,它们的区别就是请求方法的不同,不同的请求会传入不同的参数给第二个方法,在第二个方法中会对传入的参数进行序列化。具体的序列化方法可以查看 AFHTTPRequestSerializer。然后会把序列化之后的 NSMutableURLRequest 作为参数调用第三方方法,这时就进入了框架的核心类: AFURLSessionManager

AFURLSessionManager

AFURLSessionManager 持有一个 NSURLSession 类型的 session 属性,并作为该属性的 delegate,遵守实现了 NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate 四个代理方法,如果任何子类继承重写这些方法,都必须先调用父类的实现。

initWithSessionConfiguration:AFURLSessionManager 的指定初始化方法,并且在session 初始化指定为其的代理:

self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
复制代码

这样的话当一个网络请求的数据有返回或者状态被更改的时候,可以在代理方法中及时获知。AFURLSessionManagersession 属性可能会实例化多个 NSURLSessionDataTask 对象,但是 AFURLSessionManager 并不会直接维护它们,而是通过一个可变字典以 task.taskIdentifier 为 key 保存一个私有类 AFURLSessionManagerTaskDelegate 的实例,这个实例会保存这次网络请求的回调、响应数据和进度,两者是一对一的关系。当 AFURLSessionManager 所实现的协议方法被调用时,会及时更新 AFURLSessionManagerTaskDelegate 实例的数据。

在实现文件中,框架还对 NSURLSessionDataTaskresumesuspend 方法进行了 Hook,在方法执行的时候发送通知。

除此之外,AFURLSessionManager 还管理者 AFSecurityPolicyAFNetworkReachabilityManager,来保证请求的安全和查看网络连接情况,它有一个 AFJSONResponseSerializer 的实例来序列化 HTTP 响应。

AFURLRequestSerialization 和 AFURLResponseSerialization

<AFURLRequestSerialization><AFURLResponseSerialization> 只是两个协议,并且分别只有一个方法。

@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>
- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(nullable id)parameters
                                        error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
@end

@protocol AFURLResponseSerialization <NSObject, NSSecureCoding, NSCopying>
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
                           data:(nullable NSData *)data
                          error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
@end
复制代码

实现 <AFURLRequestSerialization> 协议的有 AFHTTPRequestSerializer 及其两个子类: AFJSONRequestSerializerAFPropertyListRequestSerializerAFHTTPRequestSerializer除了实现协议之外还封装了对 TTPHeader 和 HTTPBody 操作。

实现 <AFURLResponseSerialization> 协议的有 AFHTTPResponseSerializerAFJSONResponseSerializer 等数个子类。

AFHTTPResponseSerializer 有两个属性分来判断接受的 StatusCode 和 ContentType:

@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes;
@property (nonatomic, copy, nullable) NSSet <NSString *> *acceptableContentTypes
复制代码

AFJSONResponseSerializerAFHTTPSessionManager 类默认的响应序列化类型。

AFNetworkReachabilityManager

AFNetworkReachabilityManager 作用是监听网络,是一个比较独立的模块,可以拿出来单独使用。

指定构造方法: initWithReachability:AFNetworkReachabilityManager 会持有这个 SCNetworkReachabilityRef 属性。

调用 startMonitoring 开始监听:

- (void)startMonitoring {
    // 先停止监听
    [self stopMonitoring];
    // 不符合条件,直接返回
    if (!self.networkReachability) {
        return;
    }
    // 创建一个block作为 SCNetworkReachabilityContext 初始化的第二个参数,参数名:info 参数类型:无类型指针
    __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }

    };
    // 创建监听上下文
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
    // 设置监听回调,回调的是 AFNetworkReachabilityCallback 函数,并且callback会被作为参数一起回调
    SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
    // 开始监听
    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    // 获取当前的网络状态并回调
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
            AFPostReachabilityStatusChange(flags, callback);
        }
    });
}
复制代码

我的博客:iosgg.cn/

相关文章:

  • 利用JQuery制作自定义Alert Box
  • Windows Server 2003域环境搭建
  • 简单学习Less基础用法
  • 让Eclipse使用jQuery的插件-spket/ jQueryWTP/ Aptana
  • 简单的Slony-I设置实例 II
  • Ubuntu环境搭建svn服务器
  • centos7.4源码安装mysql5.6.38
  • C语言中字符串的处理方式
  • 第六章 MVC之 FileResult和JS请求二进制流文件
  • AutoMapper在MVC中的运用04-string映射各种类型、一个属性映射多个属性等
  • linux 上做mysql备份数据的还原
  • ArcGIS帮助文档VS帮助文档不能复制图片的解决方法
  • 聊聊directory traversal attack
  • 如何使用C#关键字const,readonly,static
  • 零元学Expression Blend 4 - Chapter 10 用实例了解布局容器系列-「StackPanel」
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • android图片蒙层
  • Computed property XXX was assigned to but it has no setter
  • create-react-app项目添加less配置
  • Docker: 容器互访的三种方式
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • leetcode388. Longest Absolute File Path
  • markdown编辑器简评
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • React系列之 Redux 架构模式
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • vuex 学习笔记 01
  • 读懂package.json -- 依赖管理
  • 每天10道Java面试题,跟我走,offer有!
  • 鱼骨图 - 如何绘制?
  • C# - 为值类型重定义相等性
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • (3)(3.5) 遥测无线电区域条例
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (原)本想说脏话,奈何已放下
  • .bat批处理(六):替换字符串中匹配的子串
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET Core跨平台微服务学习资源
  • .NET Core中的去虚
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET MVC 验证码
  • .Net MVC4 上传大文件,并保存表单
  • .NET委托:一个关于C#的睡前故事
  • .Net中ListT 泛型转成DataTable、DataSet
  • .NET中的十进制浮点类型,徐汇区网站设计
  • @拔赤:Web前端开发十日谈
  • [ solr入门 ] - 利用solrJ进行检索
  • [AIGC] MySQL存储引擎详解
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [BT]BUUCTF刷题第9天(3.27)