2012年5月15日 星期二

[iOS Dev] iOS 上偵測網路連線狀態的做法


在撰寫 iOS App 的時候,如果是要做跟網路有關的,一定都會遇到一個問題,就是偵測網路狀態。

這東西,說難不難,說簡單也得費點工,既然我已經找到解法,想說就順手寫下來,給自己留個記錄,順便造福需要的人。

在開始之前,需要先瞭解,手機上跟 iPad 上網路的來源,主要分成兩大類,一種是 3G 網路,另一種是 WiFi。


在 iOS 中,網路狀態對於這兩種上網通道的通知訊息是不同的,也可以用這樣的思考角度去辨別出現在 Device 是透過 3G 還是 WiFi 上網。

有鑑於這個問題的重要,Apple 在自家的網站上就有提供參考的程式碼,讓大家可以自行取用。

程式碼的連結在此

大體上來說,你需要完成下面幾個步驟。

1. 準備一個 Notifier
2. 準備一個 Notifier 回傳時的接受窗口
3. 找地方安插啟動 Notifier 的 Code
4. 根據 Notification 的狀態,解出目前上網的狀態
5. 做出對應的處理

整個流程在網路上有很多討論,不過大抵上就是這樣。

主要的架構是,iOS 會透過 Reachability 這個 Class 來通知網路狀態變動的訊息,如果有需要收到這個訊息,那 Ap 可以透過註冊的方式,跟 iOS 說要收到變動的訊息,接著把一些環境準備好。當網路狀態有變動的時候,就會透過 Callback 的方式來通知 App。

因此,主要的 Effort 就會花在 Implement 相關的設施,好讓這個 Callback 通知的動作可以順利進行,並且拿到 Ap 所需要的資訊。

不囉唆,底下就一個步驟一個步驟把程式碼貼出來。

Step 1. 準備一個 Notifier


這個 Notifier 事實上就是 Apple 幫我們處理好的那個 Reachability Class 的一個 Object。

你可以宣告在 AppDelegate.h 裡面,把它納入你的 App 中。
#import "Reachability.h"

@interface MyProjAppDelegate : UIResponder 
{
    Reachability *inetReach;
}

當然,在這之前,你要先去上面提供的那個網址下載 Reachability.h Reachability.m 兩個檔案,並且把它們加入你的專案裡面,才可以使用到他們。

Step 2. 準備 Notifier 回傳時的接受窗口


Notifier 會在事件發生的時候,透過 Callback Function 回傳相關資料,因此我們要準備一個 Call back function 給他。

 
// Called by Reachability whenever status changes.
- (void) reachabilityChanged: (NSNotification* )note
{
 Reachability* curReach = [note object];
 NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
 [self updateInterfaceWithReachability: curReach];
}

updateInterfaceWithReachability 這個 Method 是另外撰寫的,目的是為了要在事件發生時解出我們需要的資料,例如是從哪一種管道連出去,還有連線狀態如何之類的資訊。

Step 3. 找地方安插啟動 Notifier 的 Code


Call back 準備好了之後,就可以透過一些程式碼把 Notifier 註冊到系統的通知流程中。

我是放在 didFinishLaunchingWithOptions,也就是 Application Load 完之後,就立刻註冊進去。

你也可以擺在其他地方,只要能讓這個 Notifier 順利註冊到系統去收訊息即可。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
 // ... Other codes

 //  Register notification for Network status change
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil];   
 
    //  Initialize the listener for network status
    inetReach = [[Reachability reachabilityForInternetConnection] retain];
 [inetReach startNotifier];
}

Step 4. 根據 Notification 的狀態,解出目前上網的狀態


系統在網路狀態有變動的時候,會呼叫 Call back ,我們在這個 Call back 裡面,可以進一步取出 Reachability 的 Object,因為裡面有我們想要的資訊。

在我的作法裡面,是把這段處理的程式碼另外寫成一個 Method ,那個 Call back 就是單純把 Reachability 的物件解出來。

//  ------------------------------------------------------------------------
//  Implementation for Network status notification
- (void) updateInterfaceWithReachability: (Reachability*) curReach
{
    NetworkStatus curStatus;
 
 //  According to curReach, modify current internal flags
     
    //  Internet reachability
    //  Need network status to know real reachability method
    curStatus = [curReach currentReachabilityStatus];
     
    //  Modify current network status flags
    if (curStatus == ReachableViaWWAN) {
        m_bReachableViaWWAN = true;
    } else {
        m_bReachableViaWWAN = false;
    }

    if (curStatus == ReachableViaWiFi) {
        m_bReachableViaWifi = true;
    } else {
        m_bReachableViaWifi = false;
    }

    //  Reachable is the OR result of two internal connection flags
    m_bReachable = (m_bReachableViaWifi || m_bReachableViaWWAN);
 
    //  Send notification to CCViewController
    CCViewController *pControl = [self viewController];
    if (NULL != pControl) {
        if (m_bReachable == false) {
            m_bReachable = m_bReachableViaWifi || m_bReachableViaWWAN;
        }
         
        //  Send message to notify ViewController
        //  ViewController will further notify internal WebView JavaScript
        [pControl updateNetworkStatus:m_bReachable withWifiStatus:m_bReachableViaWifi andWWANStatus:m_bReachableViaWWAN];
    }
}



在上面的 Code 裡面,可以看到我用三個變數去表示目前的連線狀況,這樣其他的 Class 就可以透過這幾個變數簡單的判斷目前的網路連線狀況以及形式。

這一段就是個人創意發揮了,沒啥固定的樣子。

Step 5. 做出對應的處理


在拿到資訊之後,就可以針對你想要的處理做出對應的應對,例如沒有網路的時候該怎麼辦,網路走 3G 出去的時候該怎麼辦,走 Wifi 的時候又該如何處理,後續就是你自己 App 的行為。

簡單幾個步驟,就可以讓你的 App 增加對網路狀態知悉的能力,讓你的 App 可以更加靈活。


原始資料我是參考好幾個網站的,有興趣的話可以打入 Reachability 去搜尋,應該可以找到更多豐富的資料。



沒有留言:

張貼留言