AFNetworking 是对 Foundation 中 URL Loading System 框架的进一步抽象封装。它在 URL Loading System 的基础上,做了许多工作,从而简化了网络请求类的使用。
基本结构
NSURLSession
AFURLSessionManager
AFHTTPSessionManager
Serialization
-
AFHTTPRequestSerializer
AFJSONRequestSerializer
AFPropertyListRequestSerializer
-
AFHTTPResponseSerializer
AFJSONResponseSerializer
AFXMLParserResponseSerializer
-
AFXMLDocumentResponseSerializer
(Mac OS X) AFPropertyListResponseSerializer
AFImageResponseSerializer
AFCompoundResponseSerializer
Additional Functionality
AFSecurityPolicy
AFNetworkReachabilityManager
AFURLSessionManager
AFURLSessionManager
是对NSURLSession
的封装,通过一个NSURLSessionConfiguration
实例创建。它创建并维护着一个NSURLSession
实例,并作为这个NSURLSession
实例的代理。所以AFURLSessionManager
实现了NSURLSession
相关的代理协议:
、
、
和
。通过实现这些代理协议,AFURLSessionManager
对 data、upload 和 download 三类 task 都提供了直接传入响应完成回调 block 的创建接口。注意,创建时必须传入NSURLRequest
对象。
– dataTaskWithRequest:completionHandler:
- dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
– uploadTaskWithRequest:fromFile:progress:completionHandler:
– uploadTaskWithRequest:fromData:progress:completionHandler:
– uploadTaskWithStreamedRequest:progress:completionHandler:
– downloadTaskWithRequest:progress:destination:completionHandler:
– downloadTaskWithResumeData:progress:destination:completionHandler:
虽然AFURLSessionManager
为了实现功能已经作为了所管理的NSURLSession
实例的代理。但其对外依然提供了代理中对 session 实例的进一步控制的接口,原理就是提供设置 session 相关代理触发时的回调 block 的方法,这样在AFURLSessionManager
所实现的代理方法中,就会执行设置的对应的回调 block。
– setSessionDidBecomeInvalidBlock:
– setSessionDidReceiveAuthenticationChallengeBlock:
– setTaskNeedNewBodyStreamBlock:
– setTaskWillPerformHTTPRedirectionBlock:
– setTaskDidReceiveAuthenticationChallengeBlock:
– setTaskDidSendBodyDataBlock:
– setTaskDidCompleteBlock:
– setDataTaskDidReceiveResponseBlock:
– setDataTaskDidBecomeDownloadTaskBlock:
– setDataTaskDidReceiveDataBlock:
– setDataTaskWillCacheResponseBlock:
– setDidFinishEventsForBackgroundURLSessionBlock:
– setDownloadTaskDidFinishDownloadingBlock:
– setDownloadTaskDidWriteDataBlock:
– setDownloadTaskDidResumeBlock:
AFHTTPSessionManager
AFHTTPSessionManager
是AFURLSessionManager
的子类,它增加了针对 HTTP 协议的功能方法。这些便捷方法用于创建并执行NSURLSessionDataTask
,它们是对AFURLSessionManager
中的方法-dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
的封装。这些方法根据请求类型,传入的 URL,parameters 创建NSMutableURLRequest
实例,包括设置相应的请求头,encode URL,设置请求体等操作。另外,这些方法将请求成功和失败的情况拆分成两个不同的回调参数,需要注意的是,HTTP 状态码不为 2xx 时,会走请求失败的回调。
– GET:parameters:success:failure:
– GET:parameters:progress:success:failure:
– HEAD:parameters:success:failure:
– POST:parameters:success:failure:
– POST:parameters:progress:success:failure:
– POST:parameters:constructingBodyWithBlock:success:failure:
– POST:parameters:constructingBodyWithBlock:progress:success:failure:
– PUT:parameters:success:failure:
– PATCH:parameters:success:failure:
– DELETE:parameters:success:failure:
其中第一个参数 URLString,需要传入一个字符串类型的 URL,这个参数会和
AFHTTPSessionManager
的属性baseURL
配合使用,通过NSURL
的方法
+ URLWithString:relativeToURL:
创建用于最终请求的NSURL
实例。所以当 session 中的请求都在同一域名下或者版本相同,可以设置baseURL
,如
[NSURL URLWithString:@"http://example.com/v1/"]
,这样之后的请求方法中,URLString 参数可以只传入后面不同的 path 部分。即使有其他域名的请求,也可以直接在 URLString 参数中传入完整的 URL 字符串,因为这时+ URLWithString:relativeToURL:
方法会忽略掉 baseURL 部分,详见 NSURL。另外,还可以在创建实例时传入baseURL
,创建实例的方法包括:
+ manager
– initWithBaseURL:
– initWithBaseURL:sessionConfiguration:
协议只定义了一个方法,这个方法的作用是将需要加入请求的参数 parameters 序列化处理后和已有的请求 request 生成一个新的完整的
NSURLRequest
实例。实现的类可能要把参数作为请求的 query string,也有可能放入请求体,另外可能还要设置请求头的Content-Type
字段。
– requestBySerializingRequest:withParameters:error:
AFHTTPRequestSerializer
是实现该协议的一个具体类,可将参数作为 query string 或 URL form-encoded 的形式加入到请求中,并加入了更多的用于创建请求的属性和方法。AFHTTPRequestSerializer
类可通过方法+ serializer
创建一个新的实例,这个方法其实就是返回了[[self alloc] init]
,而真正执行的内容则是在重写过的- init
方法中。在初始化方法中,AFHTTPRequestSerializer
设置了一些用于创建请求的属性的默认值以及默认的请求头字段。AFHTTPRequestSerializer
中的很多属性其实是跟
NSURLRequest
类对应的,最终创建NSMutableURLRequest
的实例时,会根据相应的属性来设置:
allowsCellularAccess
cachePolicy
HTTPShouldHandleCookies
HTTPShouldUsePipelining
networkServiceType
timeoutInterval
另外,属性stringEncoding
是用来设置序列化后的参数的编码格式,默认值为
NSUTF8StringEncoding
。当然,还有重要的请求头的相关属性和设置方法:
HTTPRequestHeaders
– setValue:forHTTPHeaderField:
– valueForHTTPHeaderField:
– setAuthorizationHeaderFieldWithUsername:password:
– clearAuthorizationHeader
对于请求参数的序列化,即对协议方法
– requestBySerializingRequest:withParameters:error:
的实现。AFHTTPRequestSerializer
的处理是,如果请求方法为GET
、HEAD
或DELETE
,那么参数将作为 query string 添加到 URL 的后面。如果为其他,例如POST
,那么参数将放入请求体,Content-Type
为
application/x-www-form-urlencoded
。关于 query string,AFHTTPRequestSerializer
也提供了相关的属性和方法:
// 使用 query string 方式的请求方法的集合,默认值是 GET、HEAD 和 DELETE
HTTPMethodsEncodingParametersInURI
// 设置 query string 序列化使用默认行为
– setQueryStringSerializationWithStyle:
// 设置 query string 序列化使用自定义行为
– setQueryStringSerializationWithBlock:
最后,AFHTTPRequestSerializer
提供了创建NSMutableURLRequest
实例的便捷方法:
// 内部实现是通过接收的请求方法和 URL 创建请求实例,接着调用协议方法序列化参数到请求中
– requestWithMethod:URLString:parameters:error:
// 返回 Content-Type 为 multipart/form-data 的请求实例
– multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:
AFHTTPRequestSerializer
的使用方式是,在AFHTTPSessionManager
中有一个
AFHTTPRequestSerializer
类型的属性requestSerializer
,session manager 通过请求方法、URL 以及参数来创建 data task 时,则会先使用requestSerializer
来创建请求实例,之后再调用父类AFURLSessionManager
中接收请求实例参数创建 data task 的方法。
除了AFHTTPRequestSerializer
,AFNetworking 还提供了它的子类,如
AFJSONRequestSerializer
,它重写了
协议定义的方法,通过NSJSONSerialization
将参数编码为 JSON 格式,并设置请求头的Content-Type
为application/json
。当然,我们也可以自己定义AFHTTPRequestSerializer
的子类,通过重写协议方法来自定义序列化请求参数的行为。
定义了一个方法,其根据服务端的响应将返回的数据转换成更有意义的数据类型:
– responseObjectForResponse:data:error:
同 request serializer 类似,AFNetworking 提供了AFHTTPResponseSerializer
类实现了上述协议,它对协议方法的实现很简单,只是将 data 部分直接返回。但它提供了额外的方法和属性用于校验 HTTP 协议响应的状态码和Content-Type
:
// 可接受的状态码,默认值是 2xx
acceptableStatusCodes
// 可接受的数据类型,默认为空
acceptableContentTypes
// 在实现的协议方法中会调用,默认实现是如果 acceptableStatusCodes 和 acceptableContentTypes 在不为空的情况下,响应相关值不在范围内,则返回 NO,并赋值 error 对象说明原因。
– validateResponse:data:error:
AFHTTPResponseSerializer
同样是通过方法+ serializer
来创建,然后在重写的- init
方法中设置默认值。属性stringEncoding
指明当响应头未指明内容编码格式的情况下,用于编码 data 的格式,默认值是NSUTF8StringEncoding
。
AFNetworking 针对不同的响应类型,提供了多个AFHTTPResponseSerializer
子类,当然也可以自己创建子类实现自定义行为。例如AFJSONResponseSerializer
,它的
acceptableContentTypes
属性的值为application/json
、text/json
和text/javascript
,协议方法的实现中,通过NSJSONSerialization
来解析并返回数据。其他的 response serializer 还包括:
- AFImageResponseSerializer
- AFPropertyListResponseSerializer
- AFXMLParserResponseSerializer
- AFXMLDocumentResponseSerializer
- AFCompoundResponseSerializer
的使用是通过 session manager 中的属性
responseSerializer
,在AFURLSessionManager
中的类型为
id
,在AFHTTPSessionManager
则为
AFHTTPResponseSerializer
,默认值都是AFJSONResponseSerializer
实例。
AFNetworkReachabilityManager
AFNetworking 还提供了用于监听设备网络状态的工具类
AFNetworkReachabilityManager
,比如在线视频播放,下载等功能需要在网络状态从 WiFi 切换到移动流量时提醒用户,或者在网络请求失败时提醒用户网络未连接,注意,因为网络状态的判断是不可靠的,不能以此为依据来拒绝发起请求,永远都要尝试去发起请求。另外,当设备断网时,返回的 error 对象的 domain 为NSURLErrorDomain
,code 为
NSURLErrorNotConnectedToInternet
,其实也可以此作为提示没有网络连接的依据,毕竟 Foundation 框架更可靠一些。AFNetworkReachabilityManager
提供的可能的状态包括:
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1,
AFNetworkReachabilityStatusNotReachable = 0,
AFNetworkReachabilityStatusReachableViaWWAN = 1,
AFNetworkReachabilityStatusReachableViaWiFi = 2,
};
有多种可以获取 manager 实例的方法:
+ sharedManager
+ manager
+ managerForDomain:
+ managerForAddress:
– initWithReachability:
之后可以通过方法- setReachabilityStatusChangeBlock:
设置监听状态变化的回调,通过方法- startMonitoring
和- stopMonitoring
,开启和停止监听。此外,manager 还提供了一组属性用于查询当前状态:
networkReachabilityStatus
reachable
reachableViaWWAN
reachableViaWiFi
Other
对于 request serializer 和 response serializer 的设计,可以理解为策略模式的应用,在 session manager 中面向父类AFHTTPRequestSerializer
和AFHTTPResponseSerializer
编程,使用时可以灵活切换不同的具体 serializer 实现子类,即切换策略。
TODO:Category