方法一、第三方框架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
环境下。因为ARC
是Xcode
根据情况隐式添加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 ?: @"";
}
网友评论