iOS下的實際網(wǎng)絡連接狀態(tài)檢測:RealReachability

網(wǎng)絡連接狀態(tài)檢測對于我們的iOS app開發(fā)來說是一個非常通用的需求。為了更好的用戶體驗,我們會在無網(wǎng)絡時展現(xiàn)本地或者緩存的內(nèi)容,并對用戶進行合適的提示。對絕大部分iOS開發(fā)者來說,從蘋果示例代碼改變而來的各種Reachablity框架是實現(xiàn)這個需求的普遍選擇,比如這個庫。但事實上,基于此方案的所有實現(xiàn),都無法幫助我們檢測真正的網(wǎng)絡連接狀態(tài),它們能檢測的只是本地連接狀態(tài);這種情況包括但不限于如下場景: 1.現(xiàn)在很流行的公用wifi,需要網(wǎng)頁鑒權,鑒權之前無法上網(wǎng),但本地連接已經(jīng)建立; 2.存在了本地網(wǎng)絡連接,但信號很差,實際無法連接到服務器; 3.iOS連接的路由設備本身沒有連接外網(wǎng)。 cocoachina上已有很多網(wǎng)友對此進行提問和吐槽,比如: 如何判斷設備是否真正連上互聯(lián)網(wǎng)?而不是只有網(wǎng)絡連接 [Reachability reachabilityWithHostName:]完全沒用!
蘋果的Reachability示例中有如下說明,告訴我們其能力受限于此:

“Reachability cannot tell your application if you can connect to a particular host, only that an interface is available that might allow a connection, and whether that interface is the WWAN.”

蘋果的SCNetworkReachability API則告訴了我們更多: “Reachability does not guarantee that the data packet will actually be received by the host. ” 而Reachability相關的所有框架在底層實現(xiàn)都是通過SCNetworkReachability進行檢測,所以無法檢測實際網(wǎng)絡連接情況。 有鑒于此,筆者希望打造一個通用、簡單、可靠的實際網(wǎng)絡連接狀態(tài)檢測框架,于是RealReachability誕生了。

RealReachability簡單介紹

RealReachability是筆者幾個月前發(fā)布到github的開源庫,目前有1000多個star,200多個fork,幾經(jīng)修改完善后,當前pod版本為1.1.5。 項目地址如下: https://github.com/dustturtle/RealReachability。 此框架開發(fā)的初衷來源于項目實際需求,離線模式對網(wǎng)絡連接狀態(tài)的要求比較苛刻,且實際場景經(jīng)常會遇到“偽連接”的情況,Reachability面對此場景力不從心。多方研究后引入了ping能力(此方案流量開銷最小,也最簡單),實現(xiàn)了簡單的實際網(wǎng)絡連接監(jiān)測;后面經(jīng)過提煉和優(yōu)化,就有了這個框架。可以告訴大家的是,這個框架在appstore上架應用中已經(jīng)經(jīng)受了考驗,目前也不斷完善中,追求穩(wěn)定的朋友可以使用最新的pod版本(修復了已知的絕大部分問題,參考demo的使用方式即可)。

集成和使用介紹

集成
  • 最簡便的集成方法當屬pod: pod ‘RealReachability’。
  • 手動集成:將RealReachability文件夾加入到工程即可。
    • 依賴:Xcode5.0+,支持ARC, iOS6+.項目需要引入SystemConfiguration.framework.
使用介紹

其接口的設計和調(diào)用方法和Reachability非常相似,大家可以無縫上手,非常方便。 開啟網(wǎng)絡監(jiān)聽(建議在didFinishLaunchingWithOptions中進行監(jiān)聽):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

[GLobalRealReachability startNotifier]; 
return YES;
}
  • 監(jiān)聽網(wǎng)絡變化通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChanged:) name:kRealReachabilityChangedNotification object:nil];
  • 通知回調(diào)代碼示例:
- (void)networkChanged:(NSNotification *)notification{ 
RealReachability *reachability = (RealReachability *)notification.object; 
ReachabilityStatus status = [reachability currentReachabilityStatus]; 
NSLog(@"currentStatus:%@",@(status));}
  • 觸發(fā)實時網(wǎng)絡狀態(tài)查詢代碼示例:
[GLobalRealReachability reachabilityWithBlock:^(ReachabilityStatus status) {
    switch (status) { 
        case NotReachable: {
   //   case NotReachable handler 
        break; 
    } 

        case ReachableViaWiFi: { 
          // case ReachableViaWiFi handler 
              break; 
        } 

        case ReachableViaWWAN: { 
          // case ReachableViaWWAN handler 
             break; 
        } 
        default: break; 
    } 
}];
  • 查詢當前實際網(wǎng)絡連接狀態(tài):
ReachabilityStatus status = [reachability currentReachabilityStatus];
  • 設置ping檢測用的host服務器地址(可選):
注意:
  • 這里你需要確保該服務器支持ping操作。不設置的情況下我們默認使用www.apple.com作為ping服務器。 可以使用自己的服務器,或者使用穩(wěn)定、可靠的網(wǎng)絡地址(比如百度、qq等)。設置示例如下:
GLobalRealReachability.hostForPing = @"www.apple.com";
  • 獲取當前的數(shù)據(jù)網(wǎng)絡連接類型(高級功能):
WWANAccessType accessType = [GLobalRealReachability currentWWANtype];
Demo:

我們在github的repository中已經(jīng)包含了簡單的Demo工程,直接下載運行即可。相關的Api調(diào)用也可以參考demo中的實現(xiàn)。 demo截圖:
這里寫圖片描述
RealReachability的實現(xiàn)原理
RealReachability架構圖:

</br>


realReachability架構概要圖

RealReachability主要包含3大模塊:connection、ping、FSM;
其中Ping模塊通過對同樣是蘋果提供的ping樣例代碼進行了封裝,connection模塊實現(xiàn)了基于SCNetworkReachability的本地狀態(tài)檢測,F(xiàn)SM模塊是有限狀態(tài)機。通過FSM的狀態(tài)管理控制connection模塊和Ping模塊協(xié)同工作,并通過可配置的定時策略等業(yè)務邏輯優(yōu)化,最終得到了我們的實現(xiàn)。

PS:其中connection模塊和ping模塊也可獨立使用,分別提供本地網(wǎng)絡檢測和ping的能力,感興趣的讀者也可以嘗試(調(diào)用方式請參考RealReachability開源代碼)。

更新:github上的master版本已經(jīng)支持IPV6,請開發(fā)者盡快升級。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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