Reachability是蘋果官方給的檢查網絡狀態的庫,想必每個基於網絡的應用都會用它來檢查網絡狀態吧,當然筆者也不例外.可是正當自信滿滿的我,用這個庫用的不亦樂乎的時候,突然發現我寫的基於網絡的程序工作的不是那麼流暢了,尤其是仔細檢查以後確定是因為用了Reachability的時候,一下子覺得的不可理喻,這瞬間的落差讓前一分鐘還在美滋滋的認為”寫程序是藝術,用程序是享受”的我情何以堪?
這種情況就是:連接到了Wifi,但是並不能上網.這時候用Reachability檢查會認為設備處在wifi情況下(沒錯,好像就是wifi環境下),如果這時候你相當然的認為可以正常上網而去獲取網絡數據的話你就等待網絡請求超時吧,而默認的超時時間似乎有15秒之久,程序卡住這麼久在用戶體驗上不可接受的.以前的時候一直覺得Reachability挺神奇的,可以檢查出來是wifi還是3G網絡,還暗自想它是不是偷偷的連接到了哪台服務器判斷網絡情況,這次仔細看了下,覺得挺失敗的,它區分網絡連接的時候只是簡單的查看有沒有ip地址,哎.這就難怪出現以為是wifi但是上不了網的情況了.解決辦法呢?如果是用ASI進行http請求的話,可以簡單設置一下超時時間可以在一定程度上避開這個問題:[request setTimeOutSeconds:5];如果是用的NSURLRequest的話,可以用忽略本地緩存並增加超時的方法:NSURLRequest *request = [NSURLRequest requestWithURL:url1 cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];研究到這裡,筆者突然覺得發現了一個判斷網絡連接的辦法:
NSURL *url1 = [NSURL URLWithString:@"http://www.51ios.net/"]; NSURLRequest *request = [NSURLRequest requestWithURL:url1 cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10]; NSHTTPURLResponse *response; [NSURLConnection sendSynchronousRequest:request returningResponse: &response error: nil]; if (response == nil) { NSLog(@"沒有網絡"); } else{ NSLog(@"網絡是通的"); }
簡單來說就是進行一個網絡請示並設置一下超時時間,然後根據返回結果判斷網絡連接.當然了你的網絡請求最好是返回很簡單的數據,請求地址最好也是你將要請求的網絡地址(你想想:你要請求baidu的東西,判斷google的網絡連接性有用麼?).友情提示一下,上面一段代碼擱在主線程裡用依然會卡住界面的喲.
仔細想來Reachability並沒有錯.錯就錯在我把用來判斷網絡連接類型的東西用來判斷網絡連通性.所以合理的利用工具,做正確的事:)轉自Rainbird的個人博客
使用Reachability實時檢測網絡連接狀況
//在程序的啟動處,開啟通知 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //..... //開啟網絡狀況的監聽 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil]; hostReach = [[Reachability reachabilityWithHostName:@"http://www.51ios.net/"] retain];//可以以多種形式初始化 [hostReach startNotifier]; //開始監聽,會啟動一個run loop [self updateInterfaceWithReachability: hostReach]; //..... } // 連接改變 - (void) reachabilityChanged: (NSNotification* )note { Reachability* curReach = [note object]; NSParameterAssert([curReach isKindOfClass: [Reachability class]]); [self updateInterfaceWithReachability: curReach]; } //處理連接改變後的情況 - (void) updateInterfaceWithReachability: (Reachability*) curReach { //對連接改變做出響應的處理動作。 NetworkStatus status = [curReach currentReachabilityStatus]; if (status == NotReachable) { //沒有連接到網絡就彈出提實況 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"My App Name" message:@"NotReachable" delegate:nil cancelButtonTitle:@"YES" otherButtonTitles:nil]; [alert show]; [alert release]; } }