AFNetworking研读

由于公司的网络库使用的是AFNetworking旧版本,所以最近研究了这版的AFNetworking的源码,下面我们就简单介绍一下AFNetworking的核心类:
AFNetworkActivityIndicatorManager : NSObject,用来根据当前是否有网络请求,来设置状态栏菊花是否显示。

AFHTTPClient : NSObject,作为请求的入口,封装了请求的get、post等方法,以及对http的header操作的方法

AFURLConnectionOperation : NSOperation ,继承自NSOperation,是所有网络请求operation的基类,实现了NSURLConnection的代理方法,管理connection的start方法以及响应数据的处理

AFHTTPRequestOperation : AFURLConnectionOperation,对AFURLConnectionOperation进行封装,request请求使用的协议为HTTP和HTTPS,它对决定request请求是否成功的状态码和内容类型进行了封装,并且可以设置请求成功或者失败的回调;其他具体的requestOperation可以直接继承AFHTTPRequestOperation,实现简单的父类方法即可

//一个布尔值,它对应于响应的状态码是否在指定的一组可接受的状态码之内。 如果acceptableStatusCodes`为nil,则返回YES。
@property (readonly) BOOL hasAcceptableStatusCode;
//一个布尔值,它对应于响应的MIME类型是否在指定的一组可接受的内容类型之中。 如果acceptableContentTypes为nil,则返回YES。
@property (readonly) BOOL hasAcceptableContentType;

+ (NSIndexSet *)acceptableStatusCodes;
+ (void)addAcceptableStatusCodes:(NSIndexSet *)statusCodes;

+ (NSSet *)acceptableContentTypes;
+ (void)addAcceptableContentTypes:(NSSet *)contentTypes;
//决定一个请求能否被处理
+ (BOOL)canProcessRequest:(NSURLRequest *)urlRequest;
//设置请求成功/失败的回调
- (void)setCompletionBlockWithSuccess:(void (^)(WBTDAFHTTPRequestOperation *operation, id responseObject))success  failure:(void (^)(WBTDAFHTTPRequestOperation *operation, NSError *error))failure;

  • AFDownloadRequestOperation:AFHTTPRequestOperation,创建一个下载的operation,并且返回下载进度
  • AFImageRequestOperation : AFHTTPRequestOperation,封装了下载图片的请求operation,之后operation执行后,请求成功返回图片,请求失败返回错误原因;缺点没有使用缓存机制。
@property (readonly, nonatomic, retain) UIImage *responseImage;
+ (AFImageRequestOperation *)imageRequestOperationWithRequest: success:
+ (AFImageRequestOperation *)imageRequestOperationWithRequest:imageProcessingBlock:success:failure
  • AFJSONRequestOperation : AFHTTPRequestOperation,用于下载和处理返回数据格式是json的数据
//根据响应数据构造的JSON对象。 如果解析时发生错误,则将返回nil,并且将error属性设置为错误。
@property (readonly, nonatomic, retain) id responseJSON;
//创建返回AFJSONRequestOperation对象的请求,并且可以设置成功or失败的回调
+ (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest   success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success  failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON))failure;
  • AFPropertyListRequestOperation : AFHTTPRequestOperation,用于下载和处理返回数据格式是property list的数据
@property (readonly, nonatomic, retain) id responsePropertyList;
@property (nonatomic, assign) NSPropertyListReadOptions propertyListReadOptions;
+(AFPropertyListRequestOperation *)propertyListRequestOperationWithRequest:success:failure:
  • AFXMLRequestOperation : AFHTTPRequestOperation,用于下载和处理返回数据格式是xml的数据
//根据响应数据构造的“ NSXMLParser”对象。
@property (readonly, nonatomic, retain) NSXMLParser *responseXMLParser;
//根据响应数据构造的“ NSXMLDocument”对象。 如果解析时发生错误,则将返回nil,并且将error属性设置为错误。
@property (readonly, nonatomic, retain) NSXMLParser *responseXMLDocument;
@property (readonly, nonatomic, retain) id responseJSON;
//创建返回AFXMLRequestOperation对象的请求,并且可以设置成功or失败的回调
+ (AFXMLRequestOperation *)XMLParserRequestOperationWithRequest:success:failure:
+ (AFXMLRequestOperation *)XMLDocumentRequestOperationWithRequest:success:failure:

主要的逻辑在AFNetworking和AFURLConnectionOperation类中,下面我们详细介绍一下 AFURLConnectionOperation和AFHTTPClient
(1)AFURLConnectionOperation是对NSURLConnection的封装,实现网络请求的建立,并且实现NSURLConnection的代理方法获取请求的response或者请求错误等
(2)AFHTTPClient:
AFHTTPClient :封装了网络状态监听、请求编码、请求地址、请求参数以及对请求队列的管理。

(1)AFHTTPClient文件给出的使用建议包含:

  • 可以实现获取期望的解析完成的resopnse数据。

    AFHTTPClient的实例可以通过注册用于自动解析的HTTP操作类来指定期望的类型和应该处理的请求类型,例如AFJSONRequestOperation来获取解析为json数据的response、使用AFImageRequestOperation获取图片,然后在“ enqueueHTTPRequestOperationWithRequest:success:failure”中相应地构造一个请求操作。

  • 子类化

    使用的时候,为app和服务器交互的每个网络请求创建一个AFHTTPClient子类,在子类中返回一个http client的共享单例,便于在整个应用程序中保留身份验证凭据和相关网络请求配置。

  • 方法的继承

    • 重写requestWithMethod:path:parameters方法,可以改变所有AFHTTPClient子类的url请求的构建;

    • 重写HTTPRequestOperationWithRequest:success:failure方法,可以改变所有AFHTTPClient子类的request请求

  • 默认的header

    “ AFHTTPClient”设置关于HTTP header设置了一些默认值:

    -Accept-Encoding:gzip
    -Accept-Language:(逗号分隔的首选语言),en-us; q = 0.8
    -User-Agent :(生成的用户代理)

    在使用时,可以覆盖这些HTTP header或使用setDefaultHeader:value:定义新的请求header。

  • 使用相对路径构造URL

    -requestWithMethod:path:parameters:-multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:都使用NSURL 的+ URLWithString:relativeToURL:从-baseURL的请求路径中构造URL。

  • NSCoding / NSCopying一致性

    AFHTTPClient遵守NSCoding和NSCopying协议,允许将operations归档到磁盘、复制到内存中,但是注意下面几项:

    -HTTP客户端的archives和copies使用的是空操作队列进行初始化。
    -NSCoding无法序列化/反序列化block属性,因此HTTP客户端的archives不包含block。

下面我们来研究一下AFHTTPClient中网路状态的监控逻辑,AFNetworking中的网络检测主要逻辑如下:

- (void)startMonitoringNetworkReachability {
    [self stopMonitoringNetworkReachability];
    
    if (!self.baseURL) {
        return;
    }
    
  //1、获取该域名的网络连接的引用
    self.networkReachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [[self.baseURL host] UTF8String]);
    
    WBTDAFNetworkReachabilityStatusBlock callback = ^(WBTDAFNetworkReachabilityStatus status){
        self.networkReachabilityStatus = status;
        if (self.networkReachabilityStatusBlock) {
            self.networkReachabilityStatusBlock(status);
        }
    };
    
  //2、创建网络引用的context容器
    SCNetworkReachabilityContext context = {0, callback, WBTDAFNetworkReachabilityRetainCallback, WBTDAFNetworkReachabilityReleaseCallback, NULL};
  
  //3、网络变化时将client分配给一个target
    SCNetworkReachabilitySetCallback(self.networkReachability, WBTDAFNetworkReachabilityCallback, &context);
  //4、将target安排到对应的runloop和model中
    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
    
    /* Network reachability monitoring does not establish a baseline for IP addresses as it does for hostnames, so if the base URL host is an IP address, the initial reachability callback is manually triggered.
     */
    if (WBTDAFURLHostIsIPAddress(self.baseURL)) {
      //5、获取当前网络连接的标志
        SCNetworkReachabilityFlags flags;
        SCNetworkReachabilityGetFlags(self.networkReachability, &flags);
      //6、网络发生变化后更新状态并且执行相应的回调
        dispatch_async(dispatch_get_main_queue(), ^{
            WBTDAFNetworkReachabilityStatus status = WBTDAFNetworkReachabilityStatusForFlags(flags);
            callback(status);
        });
    }
}

AFNetworking中网络状态的监听实现大概流程如下:
​ 使用SCNetworkReachabilityCreateWithName()初始化函数,获取一个SCNetReachabilityRef的引用,然后使用SCNetworkReachabilityCallBack定义是一个网络监听的回调blcok,网络状态发生变化之后执行,然后初始化一个SCNetworkingReachabilityContext上下文信息,初始化SCNetworkingReachabilitySetCallback()函数传入上述 ref、callback、context 3个参数,设置Ref引用在网络变化时执行的回调blcok,通过调用SCNetworkReachabilityScheduleWithRunLoop()函数并传入Ref,在 Current Runloop 中开始或取消监听网络连接状态变化;最后调用SCNetworkReachabilityGetFlags()函数并传入Ref,可获得当前网络连接状态的 flags 枚举值,设置网络状态并且发送网络变化的通知。

注意:当 DNS 服务器无法连接或在弱网环境下,SCNetworkingReabilityGetFlags()函数将会很耗时,所以苹果建议在子线程里异步调用此函数,然后根据不同的 SCNetworkReachabilityFlags枚举值,判断当前网络连接状态和连接类型。

网络监听使用的API介绍
1、SCNetworkReachabilityRef SCNetworkReachabilityCreateWithName(CFAllocatorRef allocator, const char *nodename);根据传入的网址获得网络连接的引用,其中SCNetworkReachabilityRef表示创建的网络连接的引用,SCNetworkReachabilityCreateWithName函数参数介绍如下

  • CFAllocatorRef allocator, //可以为NULL或kCFAllocatorDefault
  • const char *nodename //比如为"www.baidu.com",此参数为域名

2、SCNetworkReachabilityContext 包含了用户数据和SCNetworkReachability的callback

typedef struct 
{
	CFIndex		version;
	void *		__nullable info;
	const void	* __nonnull (* __nullable retain)(const void *info);
	void		(* __nullable release)(const void *info);
	CFStringRef	__nonnull (* __nullable copyDescription)(const void *info);
} SCNetworkReachabilityContext;

4、SCNetworkReachabilityScheduleWithRunLoop

SCNetworkReachabilityScheduleWithRunLoop	(
					SCNetworkReachabilityRef	target,
					CFRunLoopRef			runLoop,
   				CFStringRef			runLoopMode
)	

5、SCNetworkReachabilityFlags枚举类型,定义正常测试的网络的可达性的类型,常用的类型有以下几种

  • kSCNetworkReachabilityFlagsReachable:能够连接网络
  • kSCNetworkReachabilityFlagsConnectionRequired:能够连接网络,但是首先得建立连接过程
  • kSCNetworkReachabilityFlagsIsWWAN:判断是否通过蜂窝网覆盖的连接,比如EDGE,GPRS或者目前的3G.主要是区别通过WiFi的连接。

(1)AFNetworking目前检测的网络类型

  • AFNetworkReachabilityStatusUnknown = -1,

  • AFNetworkReachabilityStatusNotReachable = 0,//网络不可用

  • AFNetworkReachabilityStatusReachableViaWWAN = 1,//移动网络连接

  • AFNetworkReachabilityStatusReachableViaWiFi = 2,//wifi连接

(2)如果要获取当前正在检测的网络可达性类型,可以通过下面函数来获取相应的类型
SCNetworkReachabilityGetFlags (
SCNetworkReachabilityRef target, //正在检测的网络连接的引用
SCNetworkReachabilityFlags *flags //用来保存获得的状态
);

知识点
OC中与网络设置、检测相关的API由SystemConfiguration静态库提供,AFNetworking、Reachability都是借助SystemConfiguration框架来完成的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员的修养

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值