AFNetworking 全解析之RechabilityManager

一个关于AFNetworking的系列

AFNetworking框架是一个使用很是普遍的框架,如今几乎已经占据了iOS开发中网络层的主导地位,成为行业标准。究其缘由,其代码自己的质量很是高,设计很是优秀,使用也很是方便。
咱们平时在网上看到的大可能是如何来使用AFNetworking的文章,少有剖析实现原理。虽然咱们没有必要再造一个轮子,可是理解轮子如何制造有助于提升咱们自身的能力,也能够避免在使用过程当中踩坑。
这个系列的文章是鄙人学习AF框架过程当中所做的笔记,分享出来以供你们观摩批评,若有理解不到位的地方,欢迎你们批评指正。编程

AFNetworkReachabilityManager的做用

AFNetworkReachabilityManager是af库中用于临测网络状态,网络状态变化的工具。使用这个工具能够获得当前系统是否可接入网络,使用什么方式接入网络(Wifi or WWAN?),以及在网络发生变化时获得相应的通知。网络

定义的几种网络状态

manager对象的networkReachabilityStatus 属性标记当前的网络状态,有如下几种选项
AFNetworkReachabilityStatusUnknown 未知的网络状态
AFNetworkReachabilityStatusNotReachable 当前处于一个无网的状态,或者被禁用的网络状态
AFNetworkReachabilityStatusReachableViaWWAN 当前网络使用移动
AFNetworkReachabilityStatusReachableViaWiFi 当前使用wifi链接网络框架

使用AF查看当前网络状态

可使用提供的单例,也能够本身建立一个新的实例来检查网络异步

[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    NSString *statusstr = AFStringFromNetworkReachabilityStatus(status);
    NSLog(@"network : %@", statusstr);
}];

注意,若是启动时就去获取,这时得到的状态可能会为Unknownasync

[[AFNetworkReachabilityManager sharedManager] startMonitoring];
NSString *statusstr = AFStringFromNetworkReachabilityStatus(status);
// statusstr = @"unknown...";

RechabilityManager类中所涉及的知识点

这里列举中间所用到的不常见的知识点,诸如单例、静态函数等不在此列函数

SCNetworkReachabilityRef

SCNetworkReachabilityRef 是SystemConfiguration framework中的一个类,专门用于检测和关注网络状态,使用C语言风格进行编程。
主要的函数有如下几个:
SCNetworkRechabilityRef SCNetworkReachabilityCreateWithAddress(CFAllocatorRef allocator, const struct sockaddr *address) 建立该对象的引用,第一个参数可使用NULL或者kCFAllocatorDefault,第二个参数为目标地址,若是传入0.0.0.0则用于查询本机网络状态。
在咱们的AFReachabilityManager中,+manager方法使用了这个函数来建立一个默认的,用于0.0.0.0的链接器。工具

struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
[self managerForAddress:&address];

Boolean SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags *flags) 用于获取网络的链接状态值,若是获取成功,返回TRUE。oop

Boolean SCNetworkReachabilityScheduleWithRunLoop    (
                    SCNetworkReachabilityRef    target,
                    CFRunLoopRef            runLoop,
                    CFStringRef            runLoopMode
                    ) 

Boolean SCNetworkReachabilityUnscheduleFromRunLoop    (
                    SCNetworkReachabilityRef    target,
                    CFRunLoopRef            runLoop,
                    CFStringRef            runLoopMode
                    )
Boolean SCNetworkReachabilitySetCallback        (
                    SCNetworkReachabilityRef            target,
                    SCNetworkReachabilityCallBack    __nullable    callout,
                    SCNetworkReachabilityContext    * __nullable    context
                    )

这三个函数用于将screachability对象加入到runloop中,在网络状态发生变化时触发回调得到相应的通知。
要使用这三个方法,首先必须先配置好回调函数学习

static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
    AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info);
}

而后使用 SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); 函数将callback添加到screachability中。
注意这里还有一个context参数 SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
callback是一个已定义好的block对象,而retainCallback和releaseCallback则决定了以后如何对这个callback对象进行引用。
这个callback将在随后的回调触发中,被传入到AFNetworkReachabilityCallback函数中被使用。spa

KeyValueAffecting

KVO机制咱们在平时的开发中也常常会有使用,不过比较深刻和偏门一些的知识点则不是那么的常见了,在AFReachabilityManager中使用到了一个方法
+(NSSet )keyPathsForValuesAffectingValueForKey:(NSString )key,这个方法决定了哪些key值会影响到其余的key值的observing。
好比

+(NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
    if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) {
        return [NSSet setWithObject:@"networkReachabilityStatus"];
    }

    return [super keyPathsForValuesAffectingValueForKey:key];
}

这个方法指明,若是networkReachabilityStatus属性被改变,那么reachable、reachableViaWWAN、reachableViaWiFi这几个属性的观察者也会收到通知。

UML结构图

图片描述

调用流程图

这个流程图标识了AFReachability使用SCNetworkReachability并产生回调的过程
clipboard.png

AFReachability的缺点

经过上面的流程图,你们能够看到,AFReachability对象建立之后并不会当即去取status,而是在startMonitor方法之后,才会去取得SC中的status,
即便如此,源代码中也是使用异步的方法去取的SCReachability的status,因此咱们在使用startMonitor方法以后,并不能稳定的取得当前的网络状态,而是必需在回调中才能获得。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
            AFPostReachabilityStatusChange(flags, callback);
        }
    });
相关文章
相关标签/搜索