+ (Reachability*) reachabilityWithHostName: (NSString*) hostName; + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; + (Reachability*) reachabilityForInternetConnection; + (Reachability*) reachabilityForLocalWiFi;
通過以上函數初始化一個Reachability實例,然後調用 1 - (NetworkStatus) currentReachabilityStatus; 返回枚舉類型NetworkStatus,即可獲得網絡連通方式,其中
typedef enum { NotReachable = 0, ReachableViaWiFi, ReachableViaWWAN, ReachableVia2G, ReachableVia3G, ReachableVia4G, } NetworkStatus;
2、connectedToNetWork(from 網絡) 第二種方式來源於網上,且只能判斷網絡是否連通而無法確定具體的連通方式,作為Reachablity類的成員函數添加到Reachability類裡的,代碼如下:
+ (BOOL)connectedToNetWork { struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof(zeroAddress)); zeroAddress.sin_len = sizeof(zeroAddress); zeroAddress.sin_family = AF_INET; SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); SCNetworkReachabilityFlags flags; BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); CFRelease(defaultRouteReachability); if (!didRetrieveFlags) { printf("Error. Count not recover network reachability flags\n"); return NO; } BOOL isReachable = flags & kSCNetworkFlagsReachable; BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired; return (isReachable && !needsConnection) ? YES : NO; }
3、statusBar+connectedToNetWork(私有API,可能會被AppStore拒掉,慎用) 第二種方式因為是定義為類函數,所以使用起來比較方便,但是會有延時,也就是說如果用戶關掉wifi開關和流量開關然後立馬進行網絡判斷,那麼這個函數依舊會返回YES,延時大約有2~3s。所以第三中方式通過將statusBar和connectedToNetWork結合來提高網絡連通性判斷的准確性。依舊是作為Reachability的一個類函數,代碼如下:
+ (BOOL)isNetworkAvailable{ //step1:調用類方法connectedToNetWork判斷網絡連通情況 BOOL connected_1=[Reachability connectedToNetWork]; //step2:通過statusBar上的網絡圖標來判斷網絡連通情況 BOOL connected_2=YES; UIApplication *app=[UIApplication sharedApplication]; if(app.statusBarHidden==NO){ NSNumber *networkType=nil; NSArray *subViewOfStatusBar=[[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews]; for(id child in subViewOfStatusBar){ if([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]){ //1-2G;2-3G;5-wifi networkType=[child valueForKeyPath:@"dataNetworkType"]; break; } } if(networkType == nil){ connected_2=NO; } } return (connected_1 && connected_2); }
說明:斷網情況下,即statusBar上沒有網絡圖標(wifi、2G、3G或4G),那麼statusBar的foregroundView的subview裡是沒有UIStatusBarDataNetworkItemView的,這樣一來,networkType的值就會為一開始賦值的nil,而不會像網上說的為0。