標籤:
大多數App都嚴重依賴於網路,一款使用者體驗良好的的app是必須要考慮網路狀態變化的.iOSSinger下一般使用Reachability這個類來檢測網路的變化.
Reachability
這個是蘋果開發文檔裡面的一個類,官方寫的,用來判斷網路的變化,包括無網路,wifi,和蜂窩三種情況.Reachability類實際上是蘋果公司對SCNetworkReachability API的封裝,使用方法比較簡單,這裡不再介紹.說說它的優缺點:
優點
使用簡單,只有一個類,官方還有Demo,容易上手
靈敏度高,基本網路一有變化,基本馬上就能判斷出來
能夠判斷有網狀態的切換比如2G/3G/4G切換
缺點
不能判斷路由器本身是否能連網
能否串連到指定伺服器,比如國內訪問牆外的伺服器
有網,但是訊號很差,網速很慢,跟沒網一樣.這時候應該認為無網.
解決方案
事實上Reachability已經很好了,但是實際上用戶端到達伺服器需要很多道"關卡",例如路由器,電信伺服器,防火牆等.其實說白了就是解決一個問題:用戶端是否能夠成功訪問伺服器.這裡介紹另外一個官方的類:SimplePing點我查看
SimplePing
SimplePing也是官方文檔的一個類,目的是ping伺服器,可以判斷用戶端是否可以串連到指定伺服器.ping 類似於心跳包功能,隔一段時間就ping下伺服器,看是否暢通無阻.因此ping不可能做到及時判斷網路變化,會有一定的延遲.可能大家已經猜到了我的思路,沒錯,把他們兩個合在一起.下面說說我的思路:
首先利用Reachability判斷裝置是否連網,至於能不能串連到伺服器用ping來檢查
如果Reachability判斷為有網,並且ping也判斷為有網,那麼表示真的有網,否則就是沒網.
ping 雖然能夠判斷用戶端到伺服器是否暢通,但是由於網路抖動或者網路很弱等原因,可能出現ping失敗的情況,解決方案就是加上失敗次數限制,超過限制就認為斷網了.
2/3/4G切換的時候,Reachability雖然檢測到了網路變化,但是類型還是蜂窩移動,不能給出具體的網路類型.這裡可以通過擷取狀態列上的屬性來判斷.
| 12345678910111213141516171819202122232425262728293031323334353637383940 |
- (SGNetworkStatus)netWorkDetailStatus{ UIApplication *app = [UIApplication sharedApplication]; UIView *statusBar = [app valueForKeyPath:@"statusBar"]; UIView *foregroundView = [statusBar valueForKeyPath:@"foregroundView"]; UIView *networkView = nil; for (UIView *childView in foregroundView.subviews) { if ([childView isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) { networkView = childView; } } SGNetworkStatus status = SGNetworkStatusNone; if (networkView) { int netType = [[networkView valueForKeyPath:@"dataNetworkType"]intValue]; switch (netType) { case 0: status = SGNetworkStatusNone; break; case 1://實際上是2G status = SGNetworkStatusUkonow; break; case 2: status = SGNetworkStatus3G; break; case 3: status = SGNetworkStatus4G; break; case 5: status = SGNetworkStatusWifi; break; default: status = SGNetworkStatusUkonow; break; } } return status;} |
可喜的是,即使隱藏了狀態列,判斷依然有效!
其他細節
預設採用host為`www.baidu.com`,別噴我,不是給百度打廣告,而是因為百度真的只適合判斷有沒有網,因為響應真的很快.當然也可以用自己的伺服器位址,這樣更加真實,萬一你家的伺服器很渣或者突然crash了也能夠完美判斷.
判斷具體網路類型的時候,實際上用kvc擷取了控制項的私人屬性,根據網上的反應,沒有因此被拒的情況,因此不用擔心.如果因為這個原因被拒,請聯絡我第一時間修改.
支援全域通知和代理的方式.預設全域發送通知,如果設定了‘delegate‘這個屬性,那麼只有代理會收到通知,不在發送全域通知.如果想兩種方式並存,可以建立一個‘SGNetObserver‘對象.
PS:貌似蘋果官方的原話是‘調用了系統的私人api會被拒‘.
支援模擬器,支援IPv4,IPv6
詳細代碼在這裡:GitHub地址 支援cocoapods,歡迎使用!
iOS完美的網路狀態判斷工具