大多數App都嚴重依賴於網絡,一款用戶體驗良好的的app是必須要考慮網絡狀態變化的.iOSSinger下一般使用Reachability這個類來檢測網絡的變化.
Reachability
這個是蘋果開發文檔裡面的一個類,官方寫的,用來判斷網絡的變化,包括無網絡,wifi,和蜂窩三種情況
優點
使用簡單,只有一個類,官方還有Demo,容易上手
靈敏度高,基本網絡一有變化,基本馬上就能判斷出來
能夠判斷有網狀態的切換比如2G/3G/4G切換
缺點
不能判斷路由器本身是否能聯網
能否連接到指定服務器,比如國內訪問牆外的服務器
有網,但是信號很差,網速很慢,跟沒網一樣.這時候應該認為無網.
解決方案
事實上Reachability已經很好了,但是實際上客戶端到達服務器需要很多道"關卡",例如路由器,電信服務器,防火牆等.其實說白了就是解決一個問題:客戶端是否能夠成功訪問服務器.這裡介紹另外一個官方的類:SimplePing點我查看
SimplePing
SimplePing也是官方文檔的一個類,目的是ping服務器,可以判斷客戶端是否可以連接到指定服務器.ping 類似於心跳包功能,隔一段時間就ping下服務器,看是否暢通無阻.因此ping不可能做到及時判斷網絡變化,會有一定的延遲.可能大家已經猜到了我的思路,沒錯,把他們兩個合在一起.下面說說我的思路:
首先利用Reachability判斷設備是否聯網,至於能不能連接到服務器用ping來檢查
如果Reachability判斷為有網,並且ping也判斷為有網,那麼表示真的有網,否則就是沒網.
ping 雖然能夠判斷客戶端到服務器是否暢通,但是由於網絡抖動或者網絡很弱等原因,可能出現ping失敗的情況,解決方案就是加上失敗次數限制,超過限制就認為斷網了.
2/3/4G切換的時候,Reachability雖然檢測到了網絡變化,但是類型還是蜂窩移動,不能給出具體的網絡類型.這裡可以通過獲取狀態欄上的屬性來判斷.
- (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,歡迎使用!
最後,如果有什麼不對,歡迎大家留言指正.