因?yàn)閕OS的系統(tǒng)是封閉的,所以是沒(méi)有直接的APi去獲取當(dāng)前的網(wǎng)絡(luò)狀態(tài)。但是道高一尺,魔高一尺。開(kāi)發(fā)者總會(huì)有辦法獲取自己想要的東西。

1.一般設(shè)備下的網(wǎng)絡(luò)狀態(tài)獲取
獲取當(dāng)前的網(wǎng)絡(luò)類(lèi)型
獲取當(dāng)前的網(wǎng)絡(luò)類(lèi)型是通過(guò)獲取狀態(tài)欄,然后遍歷狀態(tài)欄的視圖完成的。
先導(dǎo)入頭文件,如下:
#import"AppDelegate.h"
實(shí)現(xiàn)方法如下:
+?(NSString?*)getNetworkType
{
????UIApplication?*app?=?[UIApplication?sharedApplication];
????NSArray?*subviews?=?[[[app?valueForKeyPath:@"statusBar"]?valueForKeyPath:@"foregroundView"]?subviews];
????NSString?*network?=?@"";
????for(id?subview?insubviews)?{
????????if([subview?isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")])?{
????????????intnetworkType?=?[[subview?valueForKeyPath:@"dataNetworkType"]?intValue];
????????????switch(networkType)?{
????????????????case0:
????????????????????network?=?@"NONE";
????????????????????break;
????????????????case1:
????????????????????network?=?@"2G";
????????????????????break;
????????????????case2:
????????????????????network?=?@"3G";
????????????????????break;
????????????????case3:
????????????????????network?=?@"4G";
????????????????????break;
????????????????case5:
????????????????????network?=?@"WIFI";
????????????????????break;
????????????????default:
????????????????????break;
????????????}
????????}
????}
????if([network?isEqualToString:@""])?{
????????network?=?@"NO?DISPLAY";
????}
????returnnetwork;
}
獲取當(dāng)前的Wifi信息
獲取當(dāng)前的Wifi信息需要借助系統(tǒng)的SystemConfiguration這個(gè)庫(kù)。
先導(dǎo)入頭文件,如下:
1#import
實(shí)現(xiàn)方法如下:
#pragma?mark?獲取Wifi信息
+?(id)fetchSSIDInfo
{
????NSArray?*ifs?=?(__bridge_transfer?id)CNCopySupportedInterfaces();
????id?info?=?nil;
????for(NSString?*ifnam?inifs)?{
????????info?=?(__bridge_transfer?id)CNCopyCurrentNetworkInfo((__bridge?CFStringRef)ifnam);
????????if(info?&&?[info?count])?{
????????????break;
????????}
????}
????returninfo;
}
#pragma?mark?獲取WIFI名字
+?(NSString?*)getWifiSSID
{
????return(NSString?*)[self?fetchSSIDInfo][@"SSID"];
}
#pragma?mark?獲取WIFI的MAC地址
+?(NSString?*)getWifiBSSID
{
????return(NSString?*)[self?fetchSSIDInfo][@"BSSID"];
}
獲取當(dāng)前的Wifi信號(hào)強(qiáng)度
獲取信號(hào)強(qiáng)度與獲取網(wǎng)絡(luò)狀態(tài)有點(diǎn)類(lèi)似,通過(guò)遍歷狀態(tài)欄,從而獲取WIFI圖標(biāo)的信號(hào)強(qiáng)度。在獲取前需注意當(dāng)前狀態(tài)是否為WIFI。如下:
+?(int)getWifiSignalStrength{
????intsignalStrength?=?0;
//????判斷類(lèi)型是否為WIFI
????if([[self?getNetworkType]isEqualToString:@"WIFI"])?{
????UIApplication?*app?=?[UIApplication?sharedApplication];
????id?statusBar?=?[app?valueForKey:@"statusBar"];
????UIView?*foregroundView?=?[statusBar?valueForKey:@"foregroundView"];
????NSArray?*subviews?=?[foregroundView?subviews];
????NSString?*dataNetworkItemView?=?nil;
????for(id?subview?insubviews)?{
????????if([subview?isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView")?class]])?{
????????????dataNetworkItemView?=?subview;
????????????break;
????????}
????}
????intsignalStrength?=?[[dataNetworkItemView?valueForKey:@"_wifiStrengthBars"]?intValue];
????}
????returnsignalStrength;
}
2.iPhone X下的網(wǎng)絡(luò)狀態(tài)獲取
在iPhone X下,小編尋找資料,找了一圈都沒(méi)有發(fā)現(xiàn)可以使小編滿意的答案,只找到了一個(gè)開(kāi)源類(lèi)Reachability,這個(gè)類(lèi)可以獲取iPhone X下的網(wǎng)絡(luò)狀態(tài),當(dāng)然普通設(shè)備也可以用。但是在之后,小編根據(jù)結(jié)構(gòu),一步步尋找,終于找到自己想要的東西。
Reachability的使用
下載開(kāi)源類(lèi)Reachability,然后根據(jù)文檔使用即可(該類(lèi)把移動(dòng)網(wǎng)絡(luò)統(tǒng)稱(chēng)為WWAN):
+?(NSString?*)getNetworkTypeByReachability
{
????NSString?*network?=?@"";
????switch([[Reachability?reachabilityForInternetConnection]currentReachabilityStatus])?{
????????caseNotReachable:
????????????network?=?@"NONE";
????????????break;
????????caseReachableViaWiFi:
????????????network?=?@"WIFI";
????????????break;
????????caseReachableViaWWAN:
????????????network?=?@"WWAN";
????????????break;
????????default:
????????????break;
????}
????if([network?isEqualToString:@""])?{
????????network?=?@"NO?DISPLAY";
????}
????returnnetwork;
}
通過(guò)結(jié)構(gòu)獲取網(wǎng)絡(luò)類(lèi)型
在研究這部分之前,小編在想,為什么在其他設(shè)備可以通過(guò)遍歷狀態(tài)欄發(fā)現(xiàn)網(wǎng)絡(luò)狀態(tài),但是在iPhone X不行。通過(guò)打斷點(diǎn)一步步摸索發(fā)現(xiàn),iPhone X的狀態(tài)欄的結(jié)果和其他設(shè)備不太一樣。在分級(jí)上復(fù)雜了許多,而且移動(dòng)網(wǎng)絡(luò)和WIFI竟然是調(diào)用了兩個(gè)完全不太的類(lèi)。如下:

這讓小編感覺(jué)到了。。。(自行腦補(bǔ)),在不斷的探索下,終于完成了在上面的基礎(chǔ)適配iPhone X的網(wǎng)絡(luò)類(lèi)型獲取。
首先,通過(guò)添加宏判斷是否是iPhone X,如下:
#define?KIsiPhoneX?([UIScreen?instancesRespondToSelector:@selector(currentMode)]???CGSizeEqualToSize(CGSizeMake(1125,?2436),?[[UIScreen?mainScreen]?currentMode].size)?:?NO)
然后通過(guò)層級(jí)結(jié)構(gòu)判斷類(lèi)型,如下:
+?(NSString?*)getNetworkType
{
????UIApplication?*app?=?[UIApplication?sharedApplication];
????id?statusBar?=?[app?valueForKeyPath:@"statusBar"];
????NSString?*network?=?@"";
????if(KIsiPhoneX)?{
//????????iPhone?X
????????id?statusBarView?=?[statusBar?valueForKeyPath:@"statusBar"];
????????UIView?*foregroundView?=?[statusBarView?valueForKeyPath:@"foregroundView"];
????????NSArray?*subviews?=?[[foregroundView?subviews][2]?subviews];
????????for(id?subview?insubviews)?{
????????????if([subview?isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")])?{
????????????????network?=?@"WIFI";
????????????}elseif([subview?isKindOfClass:NSClassFromString(@"_UIStatusBarStringView")])?{
????????????????network?=?[subview?valueForKeyPath:@"originalText"];
????????????}
????????}
????}else{
//????????非?iPhone?X
????????UIView?*foregroundView?=?[statusBar?valueForKeyPath:@"foregroundView"];
????????NSArray?*subviews?=?[foregroundView?subviews];
????????for(id?subview?insubviews)?{
????????????if([subview?isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")])?{
????????????????intnetworkType?=?[[subview?valueForKeyPath:@"dataNetworkType"]?intValue];
????????????????switch(networkType)?{
????????????????????case0:
????????????????????????network?=?@"NONE";
????????????????????????break;
????????????????????case1:
????????????????????????network?=?@"2G";
????????????????????????break;
????????????????????case2:
????????????????????????network?=?@"3G";
????????????????????????break;
????????????????????case3:
????????????????????????network?=?@"4G";
????????????????????????break;
????????????????????case5:
????????????????????????network?=?@"WIFI";
????????????????????????break;
????????????????????default:
????????????????????????break;
????????????????}
????????????}
????????}
????}
????if([network?isEqualToString:@""])?{
????????network?=?@"NO?DISPLAY";
????}
????returnnetwork;
}
通過(guò)結(jié)構(gòu)獲取WIFI信號(hào)強(qiáng)度
因?yàn)樯厦娅@取SSID和BSSID的方法在iPhone X依然可用,因此就不多加說(shuō)明了,獲取iPhone X信號(hào)強(qiáng)度的方法也類(lèi)似于上方獲取類(lèi)型。首先判斷是否屬于WIFI網(wǎng)絡(luò),然后根據(jù)iPhone X特有的結(jié)構(gòu)找到特定的地方獲取值就行,如下:
#pragma?mark?獲取Wifi信號(hào)強(qiáng)度
+?(int)getWifiSignalStrength{
????intsignalStrength?=?0;
//????判斷類(lèi)型是否為WIFI
????if([[self?getNetworkType]isEqualToString:@"WIFI"])?{
????????UIApplication?*app?=?[UIApplication?sharedApplication];
????????id?statusBar?=?[app?valueForKey:@"statusBar"];
????????if(KIsiPhoneX)?{
//????????????iPhone?X
????????????id?statusBarView?=?[statusBar?valueForKeyPath:@"statusBar"];
????????????UIView?*foregroundView?=?[statusBarView?valueForKeyPath:@"foregroundView"];
????????????NSArray?*subviews?=?[[foregroundView?subviews][2]?subviews];
????????????for(id?subview?insubviews)?{
????????????????if([subview?isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")])?{
????????????????????signalStrength?=?[[subview?valueForKey:@"_numberOfActiveBars"]?intValue];
????????????????}
????????????}
????????}else{
//????????????非?iPhone?X
????????????UIView?*foregroundView?=?[statusBar?valueForKey:@"foregroundView"];
????????????NSArray?*subviews?=?[foregroundView?subviews];
????????????NSString?*dataNetworkItemView?=?nil;
????????????for(id?subview?insubviews)?{
????????????????if([subview?isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView")?class]])?{
????????????????????dataNetworkItemView?=?subview;
????????????????????break;
????????????????}
????????????}
????????????signalStrength?=?[[dataNetworkItemView?valueForKey:@"_wifiStrengthBars"]?intValue];
????????}
????}
????returnsignalStrength;
}