AFNetworking源码学习
AFNetworking源码学习
简介
AFNetWorking是使用Objective-c开发iOS程序主流的网络请求开源库。
AFNetworking组织结构
AFNetWorking主要分为5个部分。NSURLSession、Reachability、security、Serialization、UIKit。其中NSURLSession是整个网络请求开源库的灵魂,对外提供了丰富的网络请求接口。包括GET
、POST
、HEAD
、PUT
、DELETE
,与及文件上传的接口。
整个AFNetWorking组织结构如下:
源码解读
1.NSURLSession
NSURLSession包括AFURLSessionManager和AFHTTPSessionManager,AFHTTPSessionManager继承了AFURLSessionManager,对外提供了网络请求的接口。我们最常使用的GET
、POST
接口,底层都调用了
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(id)parametersuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgresssuccess:(void (^)(NSURLSessionDataTask *, id))successfailure:(void (^)(NSURLSessionDataTask *, NSError *))failure
整个方法的实现如下:
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(id)parametersuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgresssuccess:(void (^)(NSURLSessionDataTask *, id))successfailure:(void (^)(NSURLSessionDataTask *, NSError *))failure
{NSError *serializationError = nil;NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];if (serializationError) {if (failure) {dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{failure(nil, serializationError);});}return nil;}__block NSURLSessionDataTask *dataTask = nil;dataTask = [self dataTaskWithRequest:requestuploadProgress:uploadProgressdownloadProgress:downloadProgresscompletionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {if (error) {if (failure) {failure(dataTask, error);}} else {if (success) {success(dataTask, responseObject);}}}];return dataTask;
}
文件上传的接口例外,文件上传涉及到数据分片的问题,使用的是一个叫
- (NSURLSessionDataTask *)POST:(NSString *)URLStringparameters:(id)parametersconstructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))blockprogress:(nullable void (^)(NSProgress * _Nonnull))uploadProgresssuccess:(void (^)(NSURLSessionDataTask *task, id responseObject))successfailure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
接口,这个接口的全部实现如下:
- (NSURLSessionDataTask *)POST:(NSString *)URLStringparameters:(id)parametersconstructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))blockprogress:(nullable void (^)(NSProgress * _Nonnull))uploadProgresssuccess:(void (^)(NSURLSessionDataTask *task, id responseObject))successfailure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{NSError *serializationError = nil;NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];if (serializationError) {if (failure) {dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{failure(nil, serializationError);});}return nil;}__block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {if (error) {if (failure) {failure(task, error);}} else {if (success) {success(task, responseObject);}}}];[task resume];return task;
}
AFURLSessionManager
AFURLSessionManager是整个网络请求框架的核心。
创建了url_session_manager_creation_queue、url_session_manager_processing_queue、
url_session_manager_completion_group,这三个都是单例的形式。
AFURLSessionManager是以串行队列的方式进行session管理的。安全策略使用的是默认策略。
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)requestuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler
以安全的方式,创建了一个dataTask,最后加入到mutableTask的NSMutableDictionary中。
AFURLSessionManager是AFHTTPSessionManager的基础,对AFHTTPSessionManager提供了downloadTask、uploadTask、dataTask等等的封装。
2.AFNetworkReachabilityManager
AFNetworkReachabilityManager监测网络状态。方法如下:
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) {BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0));BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0);BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction));AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown;if (isNetworkReachable == NO) {status = AFNetworkReachabilityStatusNotReachable;}
#if TARGET_OS_IPHONEelse if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {status = AFNetworkReachabilityStatusReachableViaWWAN;}
#endifelse {status = AFNetworkReachabilityStatusReachableViaWiFi;}return status;
}
根据传入的SCNetworkReachabilityFlags
标志进行判断,返回对应的网络状态。
3.AFSecurityPolicy
AFSecurityPolicy,网络请求的安全策略。该类提供了三种安全策略:
typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {AFSSLPinningModeNone,AFSSLPinningModePublicKey,AFSSLPinningModeCertificate,
};
默认的安全策略是AFSSLPinningModeNone
,我们可以根据需要设置对应的安全策略。
开发中实际的设置栗子如下:
- (void)setupSecurityPolicy {AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];[securityPolicy setAllowInvalidCertificates:YES];[securityPolicy setValidatesDomainName:YES];self.sessionManager.securityPolicy = securityPolicy;
}
我们当时使用的是SSL对传输的数据进行加密,来达到数据的安全传输。
4.AFURLRequestSerialization
里面是对客户端发起的请求的序列化。
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)requestwithParameters:(id)parameterserror:(NSError *__autoreleasing *)error
{NSParameterAssert(request);NSMutableURLRequest *mutableRequest = [request mutableCopy];[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {if (![request valueForHTTPHeaderField:field]) {[mutableRequest setValue:value forHTTPHeaderField:field];}}];NSString *query = nil;if (parameters) {if (self.queryStringSerialization) {NSError *serializationError;query = self.queryStringSerialization(request, parameters, &serializationError);if (serializationError) {if (error) {*error = serializationError;}return nil;}} else {switch (self.queryStringSerializationStyle) {case AFHTTPRequestQueryStringDefaultStyle:query = AFQueryStringFromParameters(parameters);break;}}}if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {if (query && query.length > 0) {mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];}} else {// #2864: an empty string is a valid x-www-form-urlencoded payloadif (!query) {query = @"";}if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];}[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];}return mutableRequest;
}
对请求参数进行拼接,序列化,设置request的Content-Type,然后把序列化后的参数设置到HTTPBody中。
还有对应的序列化类AFJSONRequestSerializer & AFPropertyListRequestSerializer,可以把请求参数根据Content-Type序列化成application/json或者application/x-plist格式。
5.AFURLResponseSerialization
response序列化就是把响应数据使用数据解析器解析成对应的格式。AFURLResponseSerialization提供的解析器有:
- AFJSONResponseSerializer -> application/json/text/json/text/javascript
- AFXMLParserResponseSerializer -> application/xml/text/xml
- AFPropertyListResponseSerializer -> application/x-plist
- AFImageResponseSerializer -> image/jpeg/image/gif/image/png,这三种是常用的,还有其他好几种,可以到源码中查看。
- AFCompoundResponseSerializer 合成解析器,是上面几种的集合。
AFNetworking源码学习相关推荐
- AFNetworking源码学习 1
简介: AFNetworking是iOS.macOS.watchOS和tvOS的一个令人愉快的网络库.它建立在基础URL加载系统之上,扩展了构建到Cocoa中的强大的网络高级抽象.它有一个模块化的体系 ...
- [iOS开发]AFNetworking源码学习
目录 简介 开始解读 核心类 AFURLSessionManger 作用 属性和接口方法 代理 AFURLSessionManagerTaskDelegate _AFURLSessionTaskSwi ...
- iOS AFNetWorking源码详解(一)
来源:Yuzeyang 链接:http://zeeyang.com/2016/02/21/AFNetWorking-one/ 首先来介绍下AFNetWorking,官方介绍如下: AFNetworki ...
- Shiro源码学习之二
接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...
- Shiro源码学习之一
一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...
- mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...
前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...
- vue实例没有挂载到html上,vue 源码学习 - 实例挂载
前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...
- 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制
Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...
- jQuery源码学习之Callbacks
jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...
最新文章
- yudian温控表a1温度怎么补偿_冰箱冷藏温度多少合适 冰箱冷藏温度怎么调节 看完这篇你就有答案 冰箱...
- 领域驱动设计门槛很高,没有深厚的面向对象编码能力很难实践成功
- IT技术人生路之我的大学--我技术方向的转变
- ExecuteNonQuery返回值问题
- ansible-playbook之条件判断
- android gridview显示本地图片大小,在Android上的GridView中调整图像大小
- Mac技巧之查看苹果电脑 Mac OS X 系统是否开启 64 位运算,以及设置 32/64 位模式的方法
- Java中加二怎么打_Java(一)(二)
- Bootstrap3 栅格系统之自定义mixin和变量
- 【英语学习】【Level 08】U03 My Choice L5 The star that shines the brightest
- java可以做网页吗_如果我用java 只会做网页,那么我会不会被淘汰?
- echarts3与echarts2区别
- 计算机硬盘搜索记录,怎么清除Win7搜索记录 Win7搜索历史记录删除教程
- zigbee终端向多个协调器发起请求的思路(终端入网流程分析)
- java用springboot开发的美食菜谱网(有美食达人)附论文
- linux设置用户的执行权限,Linux下ACL权限控制以及用sudo设置用户对命令的执行权限...
- 顺丰同城赴港IPO,即时配送烽火再起
- 玫琳凯首席创新官Lucy Gildea在2022年妇女和女童参与科学国际日的声明
- 互联网创业人士具备的5大素质
- 倩女幽魂2服务器维护怎么抢先进,玉玉倩女幽魂新区攻略-经验篇
热门文章
- aaynctask控制多个下载进度_做进度计划一路关卡困难重重?通关攻略了解一下!...
- 字节跳动高工面试:mysql索引视频教程
- 6阶群的非平凡子群_抽代杂谈(9): Fratinni子群和幂零群(上)
- java的write无法写入,Java加载ImageIO.write的文件在.jar中不起作用
- 锐龙r54600虚拟linux,锐龙r5 4600u相当于i几 游戏设备问题解决分享!
- java窗口添加标签页_在新标签页中打开新窗口
- Web 浏览器相关的一些概念
- 如何面试一位前端工程师
- transformer 解码_碎碎念:Transformer的解码加速
- 质性研究工具_MAXQDA在质性数据分析中的使用——免费的中文在线研讨会!