網(wǎng)絡連接狀態(tài)檢測對于我們的iOS app開發(fā)來說是一個非常通用的需求。為了更好的用戶體驗峡迷,我們會在無網(wǎng)絡時展現(xiàn)本地或者緩存的內(nèi)容棍矛,并對用戶進行合適的提示。對絕大部分iOS開發(fā)者來說乳蛾,從蘋果示例代碼改變而來的各種Reachablity框架是實現(xiàn)這個需求的普遍選擇,比如這個庫暗赶。但事實上,基于此方案的所有實現(xiàn)肃叶,都無法幫助我們檢測真正的網(wǎng)絡連接狀態(tài)蹂随,它們能檢測的只是本地連接狀態(tài);這種情況包括但不限于如下場景: 1.現(xiàn)在很流行的公用wifi因惭,需要網(wǎng)頁鑒權岳锁,鑒權之前無法上網(wǎng),但本地連接已經(jīng)建立蹦魔; 2.存在了本地網(wǎng)絡連接激率,但信號很差,實際無法連接到服務器勿决; 3.iOS連接的路由設備本身沒有連接外網(wǎng)柱搜。 cocoachina上已有很多網(wǎng)友對此進行提問和吐槽,比如: 如何判斷設備是否真正連上互聯(lián)網(wǎng)剥险?而不是只有網(wǎng)絡連接 [Reachability reachabilityWithHostName:]完全沒用聪蘸!
蘋果的Reachability示例中有如下說明,告訴我們其能力受限于此:
“Reachability cannot tell your application if you can connect to a particular host, only that an interface is available that might allow a connection, and whether that interface is the WWAN.”
蘋果的SCNetworkReachability API則告訴了我們更多: “Reachability does not guarantee that the data packet will actually be received by the host. ” 而Reachability相關的所有框架在底層實現(xiàn)都是通過SCNetworkReachability進行檢測,所以無法檢測實際網(wǎng)絡連接情況健爬。 有鑒于此控乾,筆者希望打造一個通用、簡單娜遵、可靠的實際網(wǎng)絡連接狀態(tài)檢測框架蜕衡,于是RealReachability誕生了。
RealReachability簡單介紹
RealReachability是筆者幾個月前發(fā)布到github的開源庫设拟,目前有1000多個star,200多個fork,幾經(jīng)修改完善后慨仿,當前pod版本為1.1.5。 項目地址如下: https://github.com/dustturtle/RealReachability纳胧。 此框架開發(fā)的初衷來源于項目實際需求镰吆,離線模式對網(wǎng)絡連接狀態(tài)的要求比較苛刻,且實際場景經(jīng)常會遇到“偽連接”的情況跑慕,Reachability面對此場景力不從心万皿。多方研究后引入了ping能力(此方案流量開銷最小,也最簡單)核行,實現(xiàn)了簡單的實際網(wǎng)絡連接監(jiān)測牢硅;后面經(jīng)過提煉和優(yōu)化,就有了這個框架芝雪〖跤啵可以告訴大家的是,這個框架在appstore上架應用中已經(jīng)經(jīng)受了考驗惩系,目前也不斷完善中佳励,追求穩(wěn)定的朋友可以使用最新的pod版本(修復了已知的絕大部分問題,參考demo的使用方式即可)蛆挫。
集成和使用介紹
集成
- 最簡便的集成方法當屬pod: pod ‘RealReachability’赃承。
- 手動集成:將RealReachability文件夾加入到工程即可。
- 依賴:Xcode5.0+悴侵,支持ARC, iOS6+.項目需要引入SystemConfiguration.framework.
使用介紹
其接口的設計和調(diào)用方法和Reachability非常相似瞧剖,大家可以無縫上手,非常方便可免。 開啟網(wǎng)絡監(jiān)聽(建議在didFinishLaunchingWithOptions中進行監(jiān)聽):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GLobalRealReachability startNotifier];
return YES;
}
- 監(jiān)聽網(wǎng)絡變化通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChanged:) name:kRealReachabilityChangedNotification object:nil];
- 通知回調(diào)代碼示例:
- (void)networkChanged:(NSNotification *)notification{
RealReachability *reachability = (RealReachability *)notification.object;
ReachabilityStatus status = [reachability currentReachabilityStatus];
NSLog(@"currentStatus:%@",@(status));}
- 觸發(fā)實時網(wǎng)絡狀態(tài)查詢代碼示例:
[GLobalRealReachability reachabilityWithBlock:^(ReachabilityStatus status) {
switch (status) {
case NotReachable: {
// case NotReachable handler
break;
}
case ReachableViaWiFi: {
// case ReachableViaWiFi handler
break;
}
case ReachableViaWWAN: {
// case ReachableViaWWAN handler
break;
}
default: break;
}
}];
- 查詢當前實際網(wǎng)絡連接狀態(tài):
ReachabilityStatus status = [reachability currentReachabilityStatus];
- 設置ping檢測用的host服務器地址(可選):
注意:
- 這里你需要確保該服務器支持ping操作抓于。不設置的情況下我們默認使用www.apple.com作為ping服務器。 可以使用自己的服務器浇借,或者使用穩(wěn)定捉撮、可靠的網(wǎng)絡地址(比如百度、qq等)妇垢。設置示例如下:
GLobalRealReachability.hostForPing = @"www.apple.com";
- 獲取當前的數(shù)據(jù)網(wǎng)絡連接類型(高級功能):
WWANAccessType accessType = [GLobalRealReachability currentWWANtype];
- 該類型可以被用來優(yōu)化應用程序的體驗巾遭,比如不同的網(wǎng)絡類型下設置不同的網(wǎng)絡超時時間等肉康,關于此方面的優(yōu)化方案,可以參考攜程給出的分享:
http://www.infoq.com/cn/articles/how-ctrip-improves-app-networking-performance
Demo:
我們在github的repository中已經(jīng)包含了簡單的Demo工程灼舍,直接下載運行即可吼和。相關的Api調(diào)用也可以參考demo中的實現(xiàn)。 demo截圖:RealReachability的實現(xiàn)原理
RealReachability架構圖:
</br>
RealReachability主要包含3大模塊:connection骑素、ping炫乓、FSM;
其中Ping模塊通過對同樣是蘋果提供的ping樣例代碼進行了封裝献丑,connection模塊實現(xiàn)了基于SCNetworkReachability的本地狀態(tài)檢測末捣,F(xiàn)SM模塊是有限狀態(tài)機。通過FSM的狀態(tài)管理控制connection模塊和Ping模塊協(xié)同工作创橄,并通過可配置的定時策略等業(yè)務邏輯優(yōu)化箩做,最終得到了我們的實現(xiàn)。
PS:其中connection模塊和ping模塊也可獨立使用筐摘,分別提供本地網(wǎng)絡檢測和ping的能力卒茬,感興趣的讀者也可以嘗試(調(diào)用方式請參考RealReachability開源代碼)船老。
更新:github上的master版本已經(jīng)支持IPV6,請開發(fā)者盡快升級咖熟。