美文网首页iOS技术交流收藏
iOS 判断当前网络状态(WiFi/2G/3G/4G)

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

作者: 小盟城主 | 来源:发表于2019-01-23 18:45 被阅读72次

    方法一、第三方框架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 判断当前网络状态(WiFi/2G/3G/4G)

        本文链接:https://www.haomeiwen.com/subject/ecksjqtx.html