AFNetworking <一> AFNetworkReachabilityManager

AFNetworkReachabilityManager 是用來實(shí)時(shí)監(jiān)聽網(wǎng)絡(luò)狀態(tài)的。具體來說,是監(jiān)聽手機(jī)(主機(jī))是否能夠向外發(fā)出數(shù)據(jù)包。注意咆瘟,AFNetworkReachabilityManager 只是監(jiān)聽手機(jī)(主機(jī))能不能把數(shù)據(jù)包發(fā)出去,而不管目標(biāo)主機(jī)是否接受诽里。簡(jiǎn)而言之袒餐,就是確認(rèn)箭能不能射出去,但是不保證射的中谤狡。
AFNetworkReachabilityManager 在一般情況下的調(diào)用是 [[AFNetworkReachabilityManager sharedManager]startMonitoring]灸眼。由于對(duì)網(wǎng)絡(luò)狀態(tài)的監(jiān)聽,貫徹整個(gè)app的運(yùn)行豌汇,所以,一般情況下應(yīng)用開發(fā)中開發(fā)者不會(huì)手動(dòng)調(diào)用 stopMonitoring 方法泄隔。
這里需要注意的是拒贱,AFNetworkReachabilityManager 提供了多個(gè)獲取其實(shí)例的方法。sharedManager是獲取單例,而 manager 是獲取一個(gè)新初始化的實(shí)例逻澳,不是單例闸天。還有幾個(gè)別的獲取實(shí)例的方法如下:

  • (instancetype)managerForDomain:(NSString *)domain; —— 根據(jù)域名來獲取一個(gè) ReachabilityManager 的實(shí)例;
  • (instancetype)managerForAddress:(const void *)address; —— 根據(jù) socket 地址(sockaddr_in6斜做,ipv6) 來獲取一個(gè) ReachabilityManager 的實(shí)例苞氮。
    一般程序中,是用的都是 sharedManager瓤逼,而其他獲取實(shí)例的方法笼吟,可以讓開發(fā)者根據(jù)實(shí)際業(yè)務(wù)需求,對(duì)有需要的網(wǎng)絡(luò)進(jìn)行監(jiān)聽霸旗。
    sharedManager中實(shí)際上是使用 dispatch_once 創(chuàng)建一個(gè)單例贷帮。


    sharedManager

    再來看下 manager 這個(gè)方法:


    manager

    可以看到,這個(gè)方法里面诱告,先是創(chuàng)建了一個(gè) sockaddr 結(jié)構(gòu)體撵枢。這里,做了下版本控制精居,分別對(duì)應(yīng) ipv6 和 ipv4兩種 sockaddr 結(jié)構(gòu)體锄禽。然后調(diào)用 managerForAddress 方法:
    managerForAddress

    managerForAddress中,調(diào)用 SCNetwork中的方法靴姿,創(chuàng)建一個(gè)用于監(jiān)聽網(wǎng)絡(luò)狀態(tài)的網(wǎng)絡(luò)狀態(tài)句柄(SCNetworkReachabilityRef)沃但。這里,SC 是 system configuration 的縮寫空猜,這是一個(gè) Apple 底層的庫绽慈。
    最后看下 initWithReachability 這個(gè)初始化方法:
    initWithReachability

    忙了這么一大圈,其實(shí)就是為了得到一個(gè) SCNetworkReachabilityRef辈毯,他在監(jiān)聽網(wǎng)絡(luò)狀態(tài)時(shí)很關(guān)鍵坝疼。SCNetworkReachabilityRef是一個(gè)結(jié)構(gòu)體,我們來看看 Apple 的代碼注釋:


    SCNetworkReachabilityRef

    文檔中說谆沃,SCNetworkReachabilityRef 的 api 使得一個(gè)應(yīng)用可以獲知系統(tǒng)當(dāng)前的網(wǎng)絡(luò)配置狀態(tài)钝凶,以及判斷網(wǎng)絡(luò)是否能夠連接目標(biāo)主機(jī)。此外唁影,當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生改變時(shí)耕陷,可以通過通知監(jiān)聽網(wǎng)絡(luò)是否能夠連接【萆颍“Reachability”反映出哟沫,一個(gè)應(yīng)用向網(wǎng)絡(luò)堆棧發(fā)出的數(shù)據(jù)包,是否能夠從本機(jī)發(fā)出锌介。需要注意的是嗜诀,“Reachability”只是表征數(shù)據(jù)包能夠發(fā)出猾警,并不保證數(shù)據(jù)能夠切實(shí)的被主機(jī)收到。
    可以看到隆敢,SCNetworkReachabilityRef 其實(shí)是一個(gè)網(wǎng)絡(luò)地址或者說名稱的句柄发皿,Apple把所有相關(guān)的一些列信息都用著一個(gè)句柄在操作。同時(shí)拂蝎,在Apple的代碼注釋中可以看到穴墅,要讓 SCNetworkReachabilityRef 正常工作的話,需要將 SCNetworkReachabilityRef 加入到 運(yùn)行循環(huán) 或者是 調(diào)度隊(duì)列中温自。
    簡(jiǎn)單來說玄货,所謂的網(wǎng)絡(luò)監(jiān)聽,就是觀察 SCNetworkReachabilityRef 中的參數(shù)狀態(tài)捣作,所有的一切其實(shí)都是圍繞著他的誉结。在 SCNetworkReachabilityRef 中有 target host ,整個(gè)監(jiān)聽的過程券躁,其實(shí)就是監(jiān)聽能不能對(duì)這個(gè)目標(biāo)主機(jī)發(fā)出數(shù)據(jù)包惩坑。
    簡(jiǎn)單的看下 startMonitoring 方法。startMonitoring 中也拜,主要是是對(duì) SCNetwork 這一Apple底層的網(wǎng)絡(luò)框架的使用以舒。SCNetwork 存在于 systemConfiguration庫中,顧名思義是對(duì)系統(tǒng)的配置慢哈。AFNetworking 中的 startMonitoring 方法實(shí)現(xiàn):
    startMonitoring

    讓我們一步一步來看蔓钟。方法一開始會(huì)將上次的監(jiān)聽任務(wù)停止。隨后卵贱,判斷 self 的 networkReachability 是否為空滥沫。然后創(chuàng)建了一個(gè)閉包(block)這個(gè) block 是使用于 SCNetworkReachabilityRef 的回調(diào)中的。使用 __weak 目的是為了不讓 self 的引用計(jì)數(shù) +1键俱,使用 __strong 是為了讓實(shí)例在 block 運(yùn)行完之前不被釋放兰绣。當(dāng)然,如果你使用的是 shareManager 的話编振,那么其實(shí)這里的 __weak 和 __strong 都沒有存在的必要缀辩,因?yàn)?shareManager 是一個(gè)單例。
    block顯然是在網(wǎng)絡(luò)狀態(tài)發(fā)生變化時(shí)被調(diào)用的踪央,很簡(jiǎn)單臀玄,不多說了。之后是創(chuàng)建了一個(gè) SCNetworkReachabilityContext 的結(jié)構(gòu)體畅蹂。來看下 SCNetworkReachabilityContext 的定義:
    SCNetworkReachabilityContext

    SCNetworkReachabilityContext 包含了用戶指定的健无,相對(duì)于 SCNetworkReachability 的數(shù)據(jù)和回調(diào)函數(shù)。
    version —— 版本號(hào)液斜,是傳遞給 SCDynamicStore (系統(tǒng)配置動(dòng)態(tài)存儲(chǔ)庫)來創(chuàng)建函數(shù)用的累贤。這個(gè)結(jié)構(gòu)體的版本號(hào)是 0
    info —— 一個(gè) C 指針募胃,指向一個(gè)用戶指定的數(shù)據(jù)塊。(也就是前一步中創(chuàng)建的那個(gè)block)
    retain —— 用在回調(diào) info 的時(shí)候畦浓,為其引用加1

    release —— 用來對(duì)之前引用 +1 的 info,引用減1
    retain 和 release 這里主要注意的是函數(shù)定義要正確检疫,不然會(huì)有不可知的結(jié)果讶请。這里有個(gè)疑問就是這兩個(gè) retain 和 release 究竟是干什么使的?先往下看屎媳。
    copyDescription —— 回調(diào)時(shí)夺溢,為 info 提供描述。這個(gè)直接傳 NULL 就行烛谊,基本沒什么用风响。
    然后,是 SCNetworkReachabilitySetCallback :


    SCNetworkReachabilitySetCallback

    就是為 SCNetworkReachability添加回調(diào)函數(shù)丹禀,target 就是之前設(shè)定的 網(wǎng)絡(luò)句柄状勤。簡(jiǎn)單點(diǎn)說,他就是一個(gè)目標(biāo)双泪,監(jiān)聽本機(jī)能不能像他發(fā)出數(shù)據(jù)包(僅僅是監(jiān)聽能不能發(fā)出持搜,不保證是不是接受)。這個(gè)方法中還要穿入一個(gè)回調(diào)函數(shù)焙矛,和一個(gè) SCNetworkReachabilityContext 葫盼。回調(diào)函數(shù)用來當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生變化時(shí)村斟,讓系統(tǒng)進(jìn)行回調(diào)贫导。最后一個(gè) context 是和 回調(diào)函數(shù)相關(guān)聯(lián)的 SCNetworkReachabilityContext (網(wǎng)絡(luò)可連接上下文)。這兒說的有點(diǎn)繞蟆盹,但繼續(xù)往下看孩灯。
    這里要看下 SCNetworkReachabilityCallBack :
    SCNetworkReachabilityCallBack

    回調(diào)函數(shù)需要包含三個(gè)參數(shù),一個(gè)是監(jiān)聽的目標(biāo)日缨,一個(gè)是flag表示新的網(wǎng)絡(luò)狀態(tài)钱反,還有一個(gè)是一個(gè)C指針,指向用戶設(shè)定的閉包(也就是 SCNetworkReachabilityContext 中的 info)
    到了這里應(yīng)該明白匣距,其實(shí) SCNetworkReachabilityContext 保存的是回調(diào)函數(shù)以及相關(guān)的一些數(shù)據(jù)操作面哥,SCNetworkReachabilityCallBack是回調(diào)函數(shù),其中的 info 來自于 SCNetworkReachabilityContext毅待。
    我覺得 SCNetworkReachabilityContext 讓開發(fā)者能在設(shè)定回調(diào)函數(shù)時(shí)尚卫,有更多的自由,在 retain 和 release 的時(shí)候可以做更多的事兒尸红。(可能有更多的作用吱涉,但是我暫時(shí)沒有看出來刹泄,請(qǐng)知道的朋友不吝賜教)
    到了這里,應(yīng)該對(duì)整個(gè)回調(diào)的結(jié)構(gòu)有一些認(rèn)識(shí)了怎爵。簡(jiǎn)而言之特石,先創(chuàng)建一個(gè)要監(jiān)聽的目標(biāo),然后把回調(diào)函數(shù)用 SCNetworkReachabilityContext 結(jié)構(gòu)體包裹鳖链。然后姆蘸,為這個(gè)監(jiān)聽目標(biāo)設(shè)置回調(diào)方法。當(dāng)然芙委,看到這里逞敷,你可能會(huì)覺得為什么這么麻煩?直接把前面創(chuàng)建的 callback作為回調(diào)不就得了灌侣?
    callback

    這里有幾點(diǎn)推捐,第一 SCNetworkReachabilitySetCallback 中,對(duì)回調(diào)函數(shù)的參數(shù)類型是有要求的侧啼,需要回調(diào)函數(shù)接收三個(gè)參數(shù) —— target牛柒,callout,info痊乾。而 callback 只接受一個(gè)改變后的網(wǎng)絡(luò)狀態(tài)作為參數(shù)焰络。二者實(shí)際上是不同的函數(shù),直接傳符喝,或者強(qiáng)轉(zhuǎn)的話會(huì)出錯(cuò)闪彼。事實(shí)上,AFN在這里set的回調(diào)函數(shù) —— AFNetworkReachabilityCallback 仍然不是不是最終的真正的回調(diào)所在协饲∥吠螅看一下 AFNetworkReachabilityCallback:
    AFNetworkReachabilityCallback

    處理網(wǎng)絡(luò)狀態(tài)變化的入口有兩個(gè),一個(gè)是設(shè)置回調(diào) block 茉稠,另一個(gè)是 接受通知描馅。AFPostReachabilityStatusChange 就是調(diào)用一次用戶設(shè)置的 回調(diào) block ,然后發(fā)一個(gè)通知而线。
    可以看到铭污,AFNetworkReachabilityCallback 實(shí)際上還要調(diào)用 AFPostReachabilityStatusChange 。而在 AFPostReachabilityStatusChange 中并沒有用到 target 這個(gè)參數(shù)膀篮。這么寫嘹狞,看上去是比較繁瑣的,但是有一個(gè)巨大的好處 —— 一個(gè)方法對(duì)應(yīng)一個(gè)功能誓竿。
    對(duì)于 AFNetworkReachabilityCallback 和 AFPostReachabilityStatusChange 確實(shí)只要對(duì) AFPostReachabilityStatusChange 做一下修改磅网,在其參數(shù)列表中,添加一個(gè) target 然后這個(gè) target 參數(shù)不去使用筷屡,就直接可以將其作為回調(diào)函數(shù)傳給 SCNetworkReachabilitySetCallback 了涧偷。這樣做在功能上是沒有問題的簸喂,但是如此一來這么設(shè)計(jì) 函數(shù)的 api 是不優(yōu)雅的 —— 函數(shù)中多了一個(gè)不需要的參數(shù)。而且燎潮,AFPostReachabilityStatusChange 本身是可以直接調(diào)用的喻鳄,而不僅僅是作為 SCNetworkReachabilitySetCallback 的參數(shù)。所以确封,AFN 的作者在這里使用了一個(gè)獨(dú)立的 AFNetworkReachabilityCallback 作為一個(gè)二傳手诽表,最終調(diào)用 AFPostReachabilityStatusChange。這也是給我們?cè)谌粘>幊虝r(shí)的一個(gè)啟發(fā) —— 盡量做到一個(gè)函數(shù)就是一個(gè)功能隅肥;設(shè)計(jì)函數(shù) api 時(shí)不要出現(xiàn)多余的入?yún)ⅰ?br> 在設(shè)置完了回調(diào)函數(shù)后,將 networkReachability 加入到 runloop中袄简,達(dá)到實(shí)時(shí)?監(jiān)聽的目的 —— SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    這個(gè) SCNetworkReachabilityScheduleWithRunLoop 方法比較簡(jiǎn)單腥放,就是將 networkReachability 添加到 某個(gè)運(yùn)行循環(huán)上(這里是主循環(huán)),然后設(shè)定一個(gè)模式绿语,在這個(gè)模式下都會(huì)觸發(fā)監(jiān)聽秃症。
    這里選的是 kCFRunLoopCommonModes 這樣當(dāng)用戶操作UI的時(shí)候,?也會(huì)繼續(xù)監(jiān)聽吕粹。
    最后种柑,直接在最低優(yōu)先級(jí)的的隊(duì)列上,調(diào)用一次 AFPostReachabilityStatusChange 函數(shù)匹耕,發(fā)送目前的網(wǎng)絡(luò)可連接狀態(tài)聚请。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市稳其,隨后出現(xiàn)的幾起案子驶赏,更是在濱河造成了極大的恐慌,老刑警劉巖既鞠,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煤傍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嘱蛋,警方通過查閱死者的電腦和手機(jī)蚯姆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洒敏,“玉大人龄恋,你說我怎么就攤上這事⌒谆铮” “怎么了篙挽?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)镊靴。 經(jīng)常有香客問我铣卡,道長(zhǎng)链韭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任煮落,我火速辦了婚禮敞峭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝉仇。我一直安慰自己旋讹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布轿衔。 她就那樣靜靜地躺著沉迹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪害驹。 梳的紋絲不亂的頭發(fā)上鞭呕,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音宛官,去河邊找鬼葫松。 笑死,一個(gè)胖子當(dāng)著我的面吹牛底洗,可吹牛的內(nèi)容都是我干的腋么。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼亥揖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼珊擂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起费变,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤未玻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胡控,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扳剿,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年昼激,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了庇绽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡橙困,死狀恐怖瞧掺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凡傅,我是刑警寧澤辟狈,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響哼转,放射性物質(zhì)發(fā)生泄漏明未。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一壹蔓、第九天 我趴在偏房一處隱蔽的房頂上張望趟妥。 院中可真熱鬧,春花似錦佣蓉、人聲如沸披摄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疚膊。三九已至,卻和暖如春虾标,著一層夾襖步出監(jiān)牢的瞬間寓盗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工夺巩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人周崭。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓柳譬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親续镇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子美澳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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

  • 概述 在AFN框架中,AFURLSessionManager對(duì)象的初始化方法中創(chuàng)建了AFNetworkReacha...
    egoCogito_panf閱讀 2,378評(píng)論 0 1
  • 41.+load和+initialize區(qū)別是什么摸航? Apple的文檔很清楚地說明了initialize和load...
    Lessin閱讀 949評(píng)論 0 4
  • AFN什么是AFN全稱是AFNetworking制跟,是對(duì)NSURLConnection、NSURLSession的一...
    醉葉惜秋閱讀 1,182評(píng)論 0 0
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,671評(píng)論 0 15
  • 小小的酱虎,精致的雨膨,顏色亮麗的一把兒雨傘,給我?guī)砗芏啾Wo(hù)和快樂读串。下雨天聊记,它輕輕的呵護(hù)我,給我遮風(fēng)擋雨恢暖;有陽光...
    快樂靈芝閱讀 483評(píng)論 6 8