大多數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,歡迎使用!
最後,如果有什麼不對,歡迎大家留言指正.