AFNetworkReachabilityManager 閱讀筆記(項目問題總結(jié))

AFNetworkReachabilityManager 閱讀筆記

AFNetworkReachabilityManager 是 AFNetworking 中用來監(jiān)聽網(wǎng)絡(luò)可達(dá)性的組件,(有沒有網(wǎng)絡(luò),什么網(wǎng)絡(luò))之類的奕坟。

ps:不能根據(jù)這個狀態(tài)來阻止用戶發(fā)送網(wǎng)絡(luò)請求泳桦。

我們項目中碱璃,對網(wǎng)絡(luò)狀態(tài)變化做了一層封裝菩鲜,如下:

@interface PTVNetworkStatus()
@property(strong,nonatomic)AFHTTPSessionManager* session;
@end


@implementation PTVNetworkStatus


-(id)init
{
    if (self = [super init]) {
        _session = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.m.panda.tv"]];
        _session.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        
        [_session.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            switch (status) {
                case AFNetworkReachabilityStatusReachableViaWWAN:
                    NSLog(@"-------AFNetworkReachabilityStatusReachableViaWWAN------");
                    break;
                    
                case AFNetworkReachabilityStatusReachableViaWiFi:
                    NSLog(@"-------AFNetworkReachabilityStatusReachableViaWiFi------");
                    break;
                case AFNetworkReachabilityStatusNotReachable:
                    NSLog(@"-------AFNetworkReachabilityStatusNotReachable------");
                    break;
                default:
                    break;
            }
            if (_status != status) {
                _status = status;
                [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil];
            }
        }];
        [_session.reachabilityManager startMonitoring];
        
    }
    return self;
}

我覺得這個包裝有問題览徒。所以決定深入看一下代碼事哭,

_session = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"https://xxxxx.xxxxx"]];
        _session.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        

這里initWithBaseUrl 的參數(shù) https://xxxxx.xxxxx 對網(wǎng)絡(luò)狀態(tài)監(jiān)聽并沒有影響漫雷。

糾錯

我們看看 AFHTTPSessionManager 的初始化函數(shù):

在 AFURLSessionManager 的 init 函數(shù)中有默認(rèn)的 reachabilityManager 實(shí)現(xiàn)。

self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];

默認(rèn)的實(shí)現(xiàn)是不會用到剛才傳入的參數(shù)的鳍咱。

+ (instancetype)sharedManager {
    static AFNetworkReachabilityManager *_sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_len = sizeof(address);
        address.sin_family = AF_INET;

        _sharedManager = [self managerForAddress:&address];
    });

    return _sharedManager;
}

所以項目中的正確用法應(yīng)該是使用 managerForDomain 函數(shù)進(jìn)行初始化 AFNetworkReachabilityManager 對象降盹。然后使用 setReachabilityStatusChangeBlock 監(jiān)聽網(wǎng)絡(luò)狀態(tài)。谤辜。蓄坏。

比如:

AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager managerForDomain:@"www.google.com"];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){
    switch (status) {
        case AFNetworkReachabilityStatusReachableViaWWAN:
        case AFNetworkReachabilityStatusReachableViaWiFi:
        case AFNetworkReachabilityStatusNotReachable:
            NSLog(@"Never called");
            break;
        default:
            NSLog(@"Never called");
        break;
    }
}];
[manager startMonitoring];

如果項目要包裝 AFNetworkReachabilityManager 也不建議在 block 中直接發(fā)送通知价捧,因?yàn)槎荚谕粋€類,如果通知忘記清空涡戳,倒是還有可能導(dǎo)致崩潰结蟋。

建議使用target/action 的方式,包裝渔彰!一個列表嵌屎,足以維護(hù)某個類需要的網(wǎng)絡(luò)請求。

AFNetworkReachabilityManager 實(shí)現(xiàn)原理恍涂。

主要是基于 SCNetworkReachabilityRef 對網(wǎng)絡(luò)狀態(tài)進(jìn)行監(jiān)聽的宝惰,系統(tǒng)本身已經(jīng)支持監(jiān)聽網(wǎng)絡(luò)狀態(tài),只是C 語言的形式再沧,加上函數(shù)指針等等欧芽,對iOS 開發(fā)者族铆,并不是很友好使用起來。

所以弄懂 AFNetworkReachabilityManager 只要點(diǎn)擊看看 SCNetworkReachabilityRef 的相關(guān)函數(shù)以及文檔就好。抚垃。

+ (instancetype)managerForDomain:(NSString *)domain {
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);

    AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
    manager.networkReachabilityAssociation = AFNetworkReachabilityForName;

    return manager;
}

上面的函數(shù)式依據(jù)domain 創(chuàng)建一個 監(jiān)聽網(wǎng)絡(luò)的對象紫岩。首先先創(chuàng)建一個 SCNetworkReachabilityRef 引用火邓。

SCNetworkReachabilityRef的官方說明如下:

    The SCNetworkReachability API allows an application to
        determine the status of a system's current network
        configuration and the reachability of a target host.
        In addition, reachability can be monitored with notifications
        that are sent when the status has changed.

重點(diǎn)在于 函數(shù) startMonitoring

- (void)startMonitoring {
    //先停止當(dāng)前的監(jiān)聽
    [self stopMonitoring];
    ///如果沒有 SCNetworkReachabilityRef 不能監(jiān)聽
    if (!self.networkReachability) {
        return;
    }
///創(chuàng)建網(wǎng)絡(luò)變化回調(diào)的block
    __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }

    };

    id networkReachability = self.networkReachability;
    ///創(chuàng)建 SCNetworkReachabilityContext 結(jié)構(gòu)袖订,結(jié)構(gòu)包含了用戶指定的信息,和回調(diào)函數(shù)
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
    ///設(shè)置網(wǎng)絡(luò)變化的回調(diào)
    SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context);
    ///指定網(wǎng)絡(luò)監(jiān)聽的runloop
    SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);

    switch (self.networkReachabilityAssociation) {
        case AFNetworkReachabilityForName:
            break;
        case AFNetworkReachabilityForAddress:
        case AFNetworkReachabilityForAddressPair:
        default: {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
                SCNetworkReachabilityFlags flags;
                SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags);
                AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
                dispatch_async(dispatch_get_main_queue(), ^{
                    callback(status);

                    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
                    [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }];


                });
            });
        }
            break;
    }
}

開始監(jiān)聽函數(shù)的實(shí)現(xiàn)過程屎即。

停止監(jiān)聽的過程如下:

- (void)stopMonitoring {
    if (!self.networkReachability) {
        return;
    }

    SCNetworkReachabilityUnscheduleFromRunLoop((__bridge SCNetworkReachabilityRef)self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}

直接從runloop中移除當(dāng)前的網(wǎng)絡(luò)監(jiān)聽對象庙睡、

小結(jié)

使用第三方功能的時候,一定要對源碼有足夠的了解才行技俐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乘陪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子雕擂,更是在濱河造成了極大的恐慌啡邑,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件井赌,死亡現(xiàn)場離奇詭異谤逼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)仇穗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門流部,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纹坐,你說我怎么就攤上這事枝冀。” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵果漾,是天一觀的道長球切。 經(jīng)常有香客問我,道長绒障,這世上最難降的妖魔是什么吨凑? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮户辱,結(jié)果婚禮上鸵钝,老公的妹妹穿的比我還像新娘。我一直安慰自己焕妙,他們只是感情好蒋伦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著焚鹊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪韧献。 梳的紋絲不亂的頭發(fā)上末患,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音锤窑,去河邊找鬼璧针。 笑死,一個胖子當(dāng)著我的面吹牛渊啰,可吹牛的內(nèi)容都是我干的探橱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼绘证,長吁一口氣:“原來是場噩夢啊……” “哼隧膏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嚷那,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤胞枕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后魏宽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腐泻,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年队询,在試婚紗的時候發(fā)現(xiàn)自己被綠了派桩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚌斩,死狀恐怖铆惑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤鸭津,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布彤侍,位于F島的核電站,受9級特大地震影響逆趋,放射性物質(zhì)發(fā)生泄漏盏阶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一闻书、第九天 我趴在偏房一處隱蔽的房頂上張望名斟。 院中可真熱鬧,春花似錦魄眉、人聲如沸砰盐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岩梳。三九已至,卻和暖如春晃择,著一層夾襖步出監(jiān)牢的瞬間冀值,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工宫屠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留列疗,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓浪蹂,卻偏偏與公主長得像抵栈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坤次,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評論 25 707
  • 前言 人生苦多古劲,快來 Kotlin ,快速學(xué)習(xí)Kotlin浙踢! 什么是Kotlin绢慢? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,146評論 9 118
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法洛波,內(nèi)部類的語法胰舆,繼承相關(guān)的語法,異常的語法蹬挤,線程的語...
    子非魚_t_閱讀 31,581評論 18 399
  • 科拉梁閱讀 114評論 0 0
  • 利維坦按:盡管我們看了無數(shù)的科幻作品焰扳,幻想著時間穿梭倦零,但從古典力學(xué)的角度卻無法解釋時間的不可逆——你養(yǎng)的貓咪從小長...
    若風(fēng)的若boom閱讀 364評論 0 0