1. 程式人生 > >iOS下的實際網路連線狀態檢測:RealReachability

iOS下的實際網路連線狀態檢測:RealReachability

序言

網路連線狀態檢測對於我們的iOS app開發來說是一個非常通用的需求。為了更好的使用者體驗,我們會在無網路時展現本地或者快取的內容,並對使用者進行合適的提示。對絕大部分iOS開發者來說,從蘋果示例程式碼改變而來的各種Reachablity框架是實現這個需求的普遍選擇,比如這個庫。但事實上,基於此方案的所有實現,都無法幫助我們檢測真正的網路連線狀態,它們能檢測的只是本地連線狀態;這種情況包括但不限於如下場景:
1.現在很流行的公用wifi,需要網頁鑑權,鑑權之前無法上網,但本地連線已經建立;
2.存在了本地網路連線,但訊號很差,實際無法連線到伺服器;
3.iOS連線的路由裝置本身沒有連線外網。
cocoachina上已有很多網友對此進行提問和吐槽,比如:

如何判斷裝置是否真正連上網際網路?而不是隻有網路連線
[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相關的所有框架在底層實現都是通過SCNetworkReachability進行檢測,所以無法檢測實際網路連線情況。
有鑑於此,筆者希望打造一個通用、簡單、可靠的實際網路連線狀態檢測框架,於是RealReachability誕生了。

RealReachability簡單介紹

RealReachability是筆者幾個月前釋出到github的開源庫,目前有1000多個star,200多個fork,幾經修改完善後,當前pod版本為1.1.5。
專案地址如下:

https://github.com/dustturtle/RealReachability
此框架開發的初衷來源於專案實際需求,離線模式對網路連線狀態的要求比較苛刻,且實際場景經常會遇到“偽連線”的情況,Reachability面對此場景力不從心。多方研究後引入了ping能力(此方案流量開銷最小,也最簡單),實現了簡單的實際網路連線監測;後面經過提煉和優化,就有了這個框架。可以告訴大家的是,這個框架在appstore上架應用中已經經受了考驗,目前也不斷完善中,追求穩定的朋友可以使用最新的pod版本(修復了已知的絕大部分問題,參考demo的使用方式即可)。

整合和使用介紹

整合

  • 最簡便的整合方法當屬pod: pod ‘RealReachability’。
  • 手動整合:將RealReachability資料夾加入到工程即可。
  • 依賴:Xcode5.0+,支援ARC, iOS6+.專案需要引入SystemConfiguration.framework.

使用介紹

其介面的設計和呼叫方法和Reachability非常相似,大家可以無縫上手,非常方便。
開啟網路監聽(建議在didFinishLaunchingWithOptions中進行監聽):


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [GLobalRealReachability startNotifier];
    return YES;
}

監聽網路變化通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(networkChanged:)
                                                 name:kRealReachabilityChangedNotification
                                               object:nil];

通知回撥程式碼示例:

- (void)networkChanged:(NSNotification *)notification
{
    RealReachability *reachability = (RealReachability *)notification.object;
    ReachabilityStatus status = [reachability currentReachabilityStatus];
    NSLog(@"currentStatus:%@",@(status));
}

觸發實時網路狀態查詢程式碼示例:

[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;
        }
    }];

查詢當前實際網路連線狀態:

ReachabilityStatus status = [reachability currentReachabilityStatus];

設定ping檢測用的host伺服器地址(可選):

注意:這裡你需要確保該伺服器支援ping操作。不設定的情況下我們預設使用www.apple.com作為ping伺服器。
可以使用自己的伺服器,或者使用穩定、可靠的網路地址(比如百度、qq等)。設定示例如下:

GLobalRealReachability.hostForPing = @"www.apple.com";

獲取當前的資料網路連線型別(高階功能):

 WWANAccessType accessType = [GLobalRealReachability currentWWANtype];

Demo:

我們在github的repository中已經包含了簡單的Demo工程,直接下載執行即可。相關的Api呼叫也可以參考demo中的實現。
demo截圖:
這裡寫圖片描述

RealReachability的實現原理

RealReachability架構圖:

realReachability架構概要圖
RealReachability主要包含3大模組:connection、ping、FSM;
其中Ping模組通過對同樣是蘋果提供的ping樣例程式碼進行了封裝,connection模組實現了基於SCNetworkReachability的本地狀態檢測,FSM模組是有限狀態機。通過FSM的狀態管理控制connection模組和Ping模組協同工作,並通過可配置的定時策略等業務邏輯優化,最終得到了我們的實現。
PS:其中connection模組和ping模組也可獨立使用,分別提供本地網路檢測和ping的能力,感興趣的讀者也可以嘗試(呼叫方式請參考RealReachability開原始碼)。

結束語

希望這個框架能夠幫助到大家的iOS開發! 遇到任何疑問或者使用上的問題,都可以聯絡我,期待與您交流iOS開發技術(可以直接在我的部落格提問或者email給我).

更新:github上的master版本已經支援IPV6,請開發者儘快升級。