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);
        }
    });
相關文章
相關標籤/搜索