[iOS-Vendor] AFNetworking

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

AFHTTPSessionManagerAFURLSessionManager的子类,它增加了针对 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的处理是,如果请求方法为GETHEADDELETE,那么参数将作为 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-Typeapplication/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/jsontext/jsontext/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 中面向父类AFHTTPRequestSerializerAFHTTPResponseSerializer编程,使用时可以灵活切换不同的具体 serializer 实现子类,即切换策略。

TODO:Category

你可能感兴趣的:([iOS-Vendor] AFNetworking)