iOS 判断当前网络状态(WiFi/2G/3G/4G)

释放双眼,带上耳机,听听看~!

方法一、第三方框架AFNetworkReachabilityManager

如常用的AFNetworking中有一个AFNetworkReachabilityManager的类,可以检测当前的网络状态。
AFNetworkReachabilityManager头文件中我们可以看到网络状态的枚举值,如下:

typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown          = -1, //位置网络
AFNetworkReachabilityStatusNotReachable     = 0, // 无网络
AFNetworkReachabilityStatusReachableViaWWAN = 1, //流量
AFNetworkReachabilityStatusReachableViaWiFi = 2, // WiFi
};

(1)获取网络状态:

#import "AFNetworkReachabilityManager.h"
+ (void)getNetworkStates {
// 监控网络状态
AFNetworkReachabilityManager *reachability = [AFNetworkReachabilityManager sharedManager];
[reachability setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"状态不知道");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"没网络");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"流量");
break;
default:
break;
}
}];
//开始监控
[reachability startMonitoring];
}

(2)当用户为手机流量时,判断具体网络类型

这时可以使用系统自带的API来判断是2G、3G还是4G,这就用到了CTTelephonyNetworkInfo这类,记得在工程添加CoreTelephony.framework框架,并导入头文件#import <CoreTelephony/CTTelephonyNetworkInfo.h>

#import <CoreTelephony/CTTelephonyNetworkInfo.h>
- (NSString *)getNetType{
CTTelephonyNetworkInfo *info = [CTTelephonyNetworkInfo new];
NSString *networkType = @"";
if ([info respondsToSelector:@selector(currentRadioAccessTechnology)]) {
NSString *currentStatus = info.currentRadioAccessTechnology;
NSArray *network2G = @[CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge, CTRadioAccessTechnologyCDMA1x];
NSArray *network3G = @[CTRadioAccessTechnologyWCDMA, CTRadioAccessTechnologyHSDPA, CTRadioAccessTechnologyHSUPA, CTRadioAccessTechnologyCDMAEVDORev0, CTRadioAccessTechnologyCDMAEVDORevA, CTRadioAccessTechnologyCDMAEVDORevB, CTRadioAccessTechnologyeHRPD];
NSArray *network4G = @[CTRadioAccessTechnologyLTE];
if ([network2G containsObject:currentStatus]) {
networkType = @"2G";
}else if ([network3G containsObject:currentStatus]) {
networkType = @"3G";
}else if ([network4G containsObject:currentStatus]){
networkType = @"4G";
}else {
networkType = @"未知网络";
}
}
return networkType;
}

在网络为流量时,还可以通过另一个方法CTRadioAccessTechnologyDidChangeNotification来通过通知NSNotificationCenter来获取蜂窝网络切换状态。这里面CTTelephonyNetworkInfo初始化要使用全局实例变量,因为局部变量在某个地方被release了,这个错误和定位功能使用局部变量定义CLLocationManager如出一辙,通知代理方法不执行。这种错误容易出现在ARC环境下。因为ARCXcode根据情况隐式添加release方法,block语句和代理方法都不是立即执行的,等到执行的时候,networkInfo对象可能已经被release了。Xcode编译时,看到后面没有用到networkInfo对象,以为不需要了,所以就把它release掉了,MRC应该不会出现类似情况。
如果使用通知的这个方法就必须要用实例变量了,所以用self.networkInfo.currentRadioAccessTechnology是可以收到通知的

//定义全局实例变量
@property (nonatomic, strong) CTTelephonyNetworkInfo *networkInfo;
- (void)viewDidLoad {
[super viewDidLoad];
self.networkInfo = [[CTTelephonyNetworkInfo alloc] init];
NSLog(@"Initial connection: %@", self.networkInfo.currentRadioAccessTechnology);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:
CTRadioAccessTechnologyDidChangeNotification object:nil];
}
- (void)radioAccessChanged {
NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology);
}

方法二、通过系统statusBar判断,此方法用到了私有API(不建议使用)

//获取statusBar的网络状态
//支持iPhone X
- (NSString *)getNetWorkStates{
NSArray *children;
UIApplication *app = [UIApplication sharedApplication];
NSString *state = @"无网络";
//iPhone X
if ([[app valueForKeyPath:@"_statusBar"] isKindOfClass:NSClassFromString(@"UIStatusBar_Modern")]) {
children = [[[[app valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_statusBar"] valueForKeyPath:@"foregroundView"] subviews];
for (UIView *view in children) {
for (id child in view.subviews) {
//wifi
if ([child isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]) {
state = @"wifi";
}
//2G 3G 4G
if ([child isKindOfClass:NSClassFromString(@"_UIStatusBarStringView")]) {
if ([[child valueForKey:@"_originalText"] containsString:@"G"]) {
state = [child valueForKey:@"_originalText"];
}
}
}
}
}else {
children = [[[app valueForKeyPath:@"_statusBar"] valueForKeyPath:@"foregroundView"] subviews];
for (id child in children) {
if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
//获取到状态栏
switch ([[child valueForKeyPath:@"dataNetworkType"] intValue]) {
case 0:
state = @"无网络";
//无网模式
break;
case 1:
state = @"2G";
break;
case 2:
state = @"3G";
break;
case 3:
state = @"4G";
break;
case 5:
state = @"wifi";
break;
default:
break;
}
}
}
}
return state;
}

三、获取运营商信息

#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
- (NSString *)getMobileProvider{
CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = info.subscriberCellularProvider;
//运营商,如中国移动,中国联通,中国电信
NSString *carrierName = [carrier carrierName];
return carrierName ?: @"";
}

人已赞赏
iOS文章

iOS 实现简易抽屉效果和双边抽屉的效果

2020-1-6 12:00:20

iOS文章

iOS 数据持久化

2020-1-6 12:27:33

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索