美文网首页
检测网络状态

检测网络状态

作者: 半江瑟瑟 | 来源:发表于2016-09-08 14:35 被阅读99次

    vc中使用 viewDidLoad---dealloc willAppear --- willDidDisappear
    #pragma mark - 苹果提供的方法
    /// 当检测到网络断开时会间隔15s再次检测,如果还是断开则弹窗提醒,防止过于频繁操作
    - (void)appleReachabilityTest {
    /// Reachability使用了通知,当网络状态发生变化时发送通知kReachabilityChangedNotification
    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(appReachabilityChanged:)
    name:kReachabilityChangedNotification
    object:nil];

    // 被通知函数运行的线程应该由startNotifier函数执行的线程决定
    typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSString *remoteHostName = @"www.bing.com";
        /**
         *  有可能有问题这个带host的实例化方法--判断不准确--可以用reachabilityForInternetConnection来替代
         */
        weakSelf.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
        [weakSelf.hostReachability startNotifier];
        
        weakSelf.routerReachability = [Reachability reachabilityForInternetConnection];
        [weakSelf.routerReachability startNotifier];
        // 开启当前线程消息循环
        [[NSRunLoop currentRunLoop] run];
    });
    }
    
    /// 当网络状态发生变化时调用
     - (void)appReachabilityChanged:(NSNotification *)notification{
    Reachability *reach = [notification object];
    if([reach isKindOfClass:[Reachability class]]){
        NetworkStatus status = [reach currentReachabilityStatus];
        // 两种检测:路由与服务器是否可达  三种状态:手机流量联网、WiFi联网、没有联网
        if (reach == self.routerReachability) {
            if (status == NotReachable) {
    //                NSLog(@"routerReachability NotReachable");
                // 15秒后再次检测
                [self performSelector:@selector(appReachabilityChangedConfirm) withObject:nil afterDelay:15];
            } else if (status == ReachableViaWiFi) {
                NSLog(@"routerReachability ReachableViaWiFi--%@",[NSThread currentThread]);
            } else if (status == ReachableViaWWAN) {
                NSLog(@"routerReachability ReachableViaWWAN");
            } else if (status == kReachableVia4G){
                NSLog(@"routerReachability ReachableVia4G");
            } else if(status == kReachableVia3G){
                NSLog(@"routerReachability ReachableVia3G");
            }else if(status == kReachableVia2G){
                NSLog(@"routerReachability ReachableVia2G");
            }
        }
        if (reach == self.hostReachability) {
            if (status == NotReachable) {
                NSLog(@"hostReachability failed");
            }else if (status == ReachableViaWiFi) {
                NSLog(@"hostReachability ReachableViaWiFi--%@",[NSThread currentThread]);
            } else if (status == ReachableViaWWAN) {
                NSLog(@"hostReachability ReachableViaWWAN");
            } else if (status == kReachableVia4G){
                NSLog(@"hostReachability ReachableVia4G");
            } else if(status == kReachableVia3G){
                NSLog(@"hostReachability ReachableVia3G");
            }else if(status == kReachableVia2G){
                NSLog(@"hostReachability ReachableVia2G");
            }
        }
    }
    }
    /// 再次检测网络,如果还是断开,则视为网络已经断开
    - (void)appReachabilityChangedConfirm {
    if([self.routerReachability isKindOfClass:[Reachability class]]){
        if ([self.routerReachability currentReachabilityStatus] == NotReachable) {
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"网络中断" message:@"请检查网络" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *cancelBtn = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
                UIAlertAction *okBtn = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
                [alert addAction:cancelBtn];
                [alert addAction:okBtn];
                [self presentViewController:alert animated:YES completion:nil];
            });
        }
    }
    }
    

    修改源文件增加检测2G/3G/4G功能
    .h修改枚举值
    typedef enum : NSInteger { NotReachable = 0, ReachableViaWiFi, ReachableViaWWAN, kReachableVia4G, kReachableVia2G, kReachableVia3G } NetworkStatus;

    .m
    增加头文件
    #import <UIKit/UIDevice.h>
    #import <CoreTelephony/CTTelephonyNetworkInfo.h>

    /Radio Access Technology values/

    Paste_Image.png

    然后修改此方法
    - (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
    {
    PrintReachabilityFlags(flags, "networkStatusForFlags");
    if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
    {
    // The target host is not reachable.
    return NotReachable;
    }

    NetworkStatus returnValue = NotReachable;
    
    if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
    {
        /*
         If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
         */
        returnValue = ReachableViaWiFi;
    }
    
    if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
         (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
    {
        /*
         ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
         */
        
        if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
        {
            /*
             ... and no [user] intervention is needed...
             */
            returnValue = ReachableViaWiFi;
        }
    }
    //
    // if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
    // {
    //  /*
    //         ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
    //         */
    //  returnValue = ReachableViaWWAN;
    // }
    
    if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
    {
        /*
         ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
         */
        returnValue = ReachableViaWWAN;
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
            CTTelephonyNetworkInfo *phonyNetwork = [[CTTelephonyNetworkInfo alloc] init];
            NSString *currentStr = phonyNetwork.currentRadioAccessTechnology;
            if (currentStr) {
                if ([currentStr isEqualToString:CTRadioAccessTechnologyLTE]) {
                    returnValue = kReachableVia4G;
                }else if ([currentStr isEqualToString:CTRadioAccessTechnologyGPRS]|| [currentStr isEqualToString:CTRadioAccessTechnologyEdge]){
                    returnValue = kReachableVia2G;
                }else{
                    returnValue = kReachableVia3G;
                }
            }
        }else{
            if ((flags & kSCNetworkReachabilityFlagsTransientConnection) == kSCNetworkReachabilityFlagsTransientConnection) {
                
                returnValue = kReachableVia3G;
                
                if((flags & kSCNetworkReachabilityFlagsConnectionRequired) == kSCNetworkReachabilityFlagsConnectionRequired) {
                    returnValue = kReachableVia2G;
                }
            }
        }
    }
    
    return returnValue;
    }
    

    <发现有时候通知会发出2次;有时候通知发出1次?why!>
    我觉得应该发出2次才对啊 startNotifier方法调用了2次啊!

    Paste_Image.png Paste_Image.png Paste_Image.png

    demo地址:
    https://github.com/jiangweike/networkStatus
    参考文章
    https://blog.6ag.cn/1310.html
    http://xiongzenghuidegithub.github.io/blog/2013/12/30/reachabilityyuan-ma-xue-xi/
    http://blog.csdn.net/Axing1991/article/details/46649939
    http://www.jianshu.com/p/d95c8879d8d5
    http://www.cnblogs.com/mddblog/p/5304346.html
    http://www.cnblogs.com/scut-linmaojiang/p/iOS-Reachability.html
    https://github.com/mddios/NetworkStauts
    http://blog.csdn.net/applelg/article/details/47660577
    http://www.ithao123.cn/content-2198058.html
    https://www.mgenware.com/blog/?p=487
    http://www.jianshu.com/p/1b0901d0902b

    相关文章

      网友评论

          本文标题:检测网络状态

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