AFNetworking网络请求详解
一、AFURLSessionManager
网络请求的核心类,主要作用有以下几点:
1、线程安全的创建NSURLSession,并实现NSURLSessionDelegate
2、设置responseSerializer(用于返回数据的解析,默认AFJSONResponseSerializer)
设置securityPolicy(用于SSL证书,HTTPS访问安全管理)
设置completionQueue(请求完成返回数据时的队列,不设置默认回到主线程队列)
设置completionGroup(请求完成返回数据时的队列组,不设置会使用默认值)
设置reachabilityManager(用于网络状况的监控)
3、生成各类NSURLSessionTask,以及设置各类Task的回调Block。
NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask
4、管理AFURLSessionManagerTaskDelegate,根据Task标识,把NSURLSessionDelegate
回调分发到具体的AFURLSessionManagerTaskDelegate对象中
二、AFHTTPSessionManager
是AFURLSessionManager子类,除了父类功能外,还有以下作用:
1、设置requestSerializer
2、根据不同请求方式生成NSURLSessionDataTask
三、AFURLRequestSerialization
是生成NSURLRequest的协议,主要针对AFHTTPSessionManager的requestSerializer
AFURLRequestSerialization协议实现类为:AFHTTPRequestSerializer,除了帮我们生成
NSURLRequest外,还可以设置stringEncoding、allowsCellularAccess、cachePolicy、
HTTPRequestHeaders等一些请求相关的参数。
AFHTTPRequestSerializer有2个子类(主要用于不同的`Content-Type`):
AFJSONRequestSerializer(application/json)
AFPropertyListRequestSerializer(application/x-plist)
在处理multipart/form-data方式时,提供了方法:
- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(nullable NSDictionary <NSString *, id> *)parametersconstructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))blockerror:(NSError * _Nullable __autoreleasing *)error;
在constructingBodyWithBlock中提供了实现AFMultipartFormData协议的类用于添加参数
AFMultipartFormData真正的实现类是AFStreamingMultipartFormData
四、AFURLResponseSerialization
是解析Response的协议,实现类为:AFHTTPResponseSerializer
AFHTTPResponseSerializer有以下几个子类(用于解析不同的MIMEType):
AFJSONResponseSerializer(json解析)
AFXMLParserResponseSerializer(xml解析,返回NSXMLParser)
AFXMLDocumentResponseSerializer(xml解析,返回NSXMLDocument)
AFPropertyListResponseSerializer(plist解析)
AFImageResponseSerializer(图片解析)
AFCompoundResponseSerializer(组合解析,可以添加多个上面类,根据顺序解析)
五、AFURLSessionManagerTaskDelegate
真正的NSURLSessionDelegate实现类,用于管理Task的上传下载进度,完成回调等
六、完整的网络请求流程
1、准备工作。初始化AFHTTPSessionManager,并根据业务设置requestSerializer、
responseSerializer、baseUrl等
2、创建Task,以自定义NSURLSessionDataTask为例:
- (nullable NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(nullable id)parametersheaders:(nullable NSDictionary <NSString *, NSString *> *)headersuploadProgress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressdownloadProgress:(nullable void (^)(NSProgress *downloadProgress))downloadProgresssuccess:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))successfailure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
首页会根据我们设置的requestSerializer生成NSMutableURLRequest:
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
设置请求头:
for (NSString *headerField in headers.keyEnumerator) {[request setValue:headers[headerField] forHTTPHeaderField:headerField];
}
如果requestSerializer报错,就结束流程,从completionQueue回调出去,
如果requestSerializer成功,开始生成NSURLSessionDataTask:
__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);}}}];
我们跟着生成的方法点进去看到,通过AFHTTPSessionManager.session生成Task,并且
创建Task的AFURLSessionManagerTaskDelegate和回调参数,同时根据Task的标识存储
Delegate到mutableTaskDelegatesKeyedByTaskIdentifier字典中
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTaskuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];delegate.manager = self;delegate.completionHandler = completionHandler;dataTask.taskDescription = self.taskDescriptionForSessionTasks;[self setDelegate:delegate forTask:dataTask];delegate.uploadProgressBlock = uploadProgressBlock;delegate.downloadProgressBlock = downloadProgressBlock;
}
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegateforTask:(NSURLSessionTask *)task
{NSParameterAssert(task);NSParameterAssert(delegate);[self.lock lock];self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;[self addNotificationObserverForTask:task];[self.lock unlock];
}
3、启动Task,使用resume方法。而后通过NSURLSessionDelegate监听网络请求过程。我们
可以看到AFURLSessionManager实现的NSURLSessionDelegate方法中,首先根据task
标识获取对应的AFURLSessionManagerTaskDelegate,然后分发事件至具体的Delegate
类中。我们以didCompleteWithError回调看:
- (void)URLSession:(NSURLSession *)sessiontask:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];// delegate may be nil when completing a task in the backgroundif (delegate) {[delegate URLSession:session task:task didCompleteWithError:error];[self removeDelegateForTask:task];}if (self.taskDidComplete) {self.taskDidComplete(session, task, error);}
}
4、请求完成回调处理,实际是在AFURLSessionManagerTaskDelegate中实现的,通过阅读
代码实现可以看出如果请求出现错误,就回调到completionHandler,如果未出现错误,
首先获取manager的responseSerializer去解析返回内容,然后再回调出去
- (void)URLSession:(__unused NSURLSession *)sessiontask:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{error = objc_getAssociatedObject(task, AuthenticationChallengeErrorKey) ?: error;__strong AFURLSessionManager *manager = self.manager;__block id responseObject = nil;NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;//Performance Improvement from #2672NSData *data = nil;if (self.mutableData) {data = [self.mutableData copy];//We no longer need the reference, so nil it out to gain back some memory.self.mutableData = nil;}#if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICSif (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {if (self.sessionTaskMetrics) {userInfo[AFNetworkingTaskDidCompleteSessionTaskMetrics] = self.sessionTaskMetrics;}}
#endifif (self.downloadFileURL) {userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;} else if (data) {userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;}if (error) {userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{if (self.completionHandler) {self.completionHandler(task.response, responseObject, error);}dispatch_async(dispatch_get_main_queue(), ^{[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];});});} else {dispatch_async(url_session_manager_processing_queue(), ^{NSError *serializationError = nil;responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];if (self.downloadFileURL) {responseObject = self.downloadFileURL;}if (responseObject) {userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;}if (serializationError) {userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;}dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{if (self.completionHandler) {self.completionHandler(task.response, responseObject, serializationError);}dispatch_async(dispatch_get_main_queue(), ^{[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];});});});}
}
AFNetworking网络请求详解相关推荐
- afn访问本地html,Swift利用AFN实现封装网络请求详解
前言 相信大家都知道,我们一般在一个项目中,网络请求都封装成一个单例,以确保整个项目的网络请求 Session 是同一个. 单例模式定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供,下面话不 ...
- Android 网络请求详解
我们知道大多数的 Android 应用程序都是通过和服务器进行交互来获取数据的.如果使用 HTTP 协议来发送和接收网络数据,就免不了使用 HttpURLConnection 和 HttpClient ...
- afn原理 ios_iOS AFNetworking网络框架详解
导语: 众所周知,AFNetworking是目前IOS开发中非常受欢迎的第三方网络通信类库,同时AFNetworking对苹果官方NSURLConnection和NSURLSession进行了封装,使 ...
- 用netstat查看网络状态详解
--用netstat查看网络状态详解 -----------------------------2014/06/11 一.Linux服务器上11种网络连接状态: ...
- nbns协议_网络协议详解1 - NBNS
NetBIOS 简介 NetBIOS,Network Basic Input/Output System的缩写,一般指用于局域网通信的一套API,相关RFC文档包括 RFC 1001, RFC 100 ...
- Linux网络编程---详解TCP
Linux网络编程---详解TCP的三次握手和四次挥手_shanghx_123的博客-CSDN博客_tcp的协议数据单元被称为 TCP协议详解(TCP报文.三次握手.四次挥手.TIME_WAIT状态. ...
- JavaEE基础(03):Http请求详解,握手挥手流程简介
本文源码:GitHub·点这里 || GitEE·点这里 一.Http协议简介 1.概念说明 HTTP超文本传输协议,是用于从万维网服务器传输超文本到本地浏览器的传送协议,基于TCP/IP通信协议来传 ...
- 网络知识详解之:网络攻击与安全防护
网络知识详解之:网络攻击与安全防护 计算机网络相关知识体系详解 网络知识详解之:TCP连接原理详解 网络知识详解之:HTTP协议基础 网络知识详解之:HTTPS通信原理剖析(对称.非对称加密.数字签名 ...
- 趣谈网络协议-第二模块-底层网络知识详解:4陌生的数据中心2CDN和数据中心
趣谈网络协议-第二模块-底层网络知识详解:4陌生的数据中心2CDN和数据中心 1:CDN:你去小卖部取过快递么? 使用"中间仓库"来优化 网络中的"就近配送" ...
最新文章
- 软件架构设计 温昱著 - 读书笔记
- 误用.Net Redis客户端工具CSRedisCore,自己挖坑自己填
- 现代交换技术学习笔记001
- java里面的 |运算符_Java 中 | ^ 运算符的简单使用
- map类的erase方法的在Linux与Windows中的差异
- 推荐系统(3)-协同过滤2-矩阵分解算法
- 【Python】Python3编码规范
- Linux创建软连接
- Mac OS X10.11下CocoaPods的安装过程
- 中值滤波器的matlab实现
- c语言炒股软件公式,股票软件怎么使用指标选股公式
- 聊一聊,android程序员前景如何
- MySql 操作时间
- 研究生毕业论文如何选题
- 猜数字(Bulls and Cows)游戏
- excel标题行列浮动显示/冻结窗口
- 小高不太行之前端--JSON
- 参加《前沿科学国际研讨会》的世界著名学者简介
- 长续航高性价比,轻松畅享好音质 ——索尼长续航颈挂式无线耳机WI-C100活力发布
- CF专题(长安大学)
热门文章
- 【算法】局部敏感哈希 LSH 的 Python 实现
- 想成为真正的网游研发员吗,从这开始吧
- python实现手机通讯录_Python实现命令行通讯录
- html计算数学表达式,如何使用MathCalc在JavaScript中实现基本的数学表达式计算器...
- iOS开发-支付宝手势解锁实现展示
- CH395: TCP/IP网络协议栈芯片,让单片机轻松联网
- Traceroute
- 一点排位就安全异常退出_腾讯游戏信用 影响CF排位赛
- websocket java详解_WebSocket详解
- java生成与解析二维码 支持插入图片与文字