• Reachability实时监控网络变化


    Reachability是一种实时观察网络发生变化控件,如当你的手机处于WiFi情况下,他就会检测环境,当处于GPS的情况下改变环境,当处于无网络的情况下又是一种环境。下面我们看下关于Reachability的用法、

    1.用到Reachability的情况下,首先引入SystemConfiguration;

    Reachability.h:

    #import <Foundation/Foundation.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    #import <netinet/in.h>


    typedef enum : NSInteger {
        NotReachable = 0,
        ReachableViaWiFi,
        ReachableViaWWAN
    } NetworkStatus;


    extern NSString *kReachabilityChangedNotification;


    @interface Reachability : NSObject


    + (instancetype)reachabilityWithHostName:(NSString *)hostName;


    + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;


    + (instancetype)reachabilityForInternetConnection;


    + (instancetype)reachabilityForLocalWiFi;

    - (BOOL)startNotifier;
    - (void)stopNotifier;

    - (NetworkStatus)currentReachabilityStatus;

    Reachability.m:

    #import <arpa/inet.h>
    #import <ifaddrs.h>
    #import <netdb.h>
    #import <sys/socket.h>

    #import <CoreFoundation/CoreFoundation.h>

    #import "Reachability.h"


    NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";


    #pragma mark - Supporting functions

    #define kShouldPrintReachabilityFlags 1

    static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
    {
    #if kShouldPrintReachabilityFlags

        NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
              (flags & kSCNetworkReachabilityFlagsIsWWAN)                ? 'W' : '-',
              (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',

              (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
              (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
              (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
              (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
              (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
              (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
              (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
              comment
              );
    #endif
    }


    static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
    {
    #pragma unused (target, flags)
        NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
        NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");

        Reachability* noteObject = (__bridge Reachability *)info;
        // Post a notification to notify the client that the network reachability changed.
        [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
    }


    #pragma mark - Reachability implementation

    @implementation Reachability
    {
        BOOL _alwaysReturnLocalWiFiStatus; //default is NO
        SCNetworkReachabilityRef _reachabilityRef;
    }

    + (instancetype)reachabilityWithHostName:(NSString *)hostName
    {
        Reachability* returnValue = NULL;
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
        if (reachability != NULL)
        {
            returnValue= [[self alloc] init];
            if (returnValue != NULL)
            {
                returnValue->_reachabilityRef = reachability;
                returnValue->_alwaysReturnLocalWiFiStatus = NO;
            }
        }
        return returnValue;
    }


    + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress
    {
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);

        Reachability* returnValue = NULL;

        if (reachability != NULL)
        {
            returnValue = [[self alloc] init];
            if (returnValue != NULL)
            {
                returnValue->_reachabilityRef = reachability;
                returnValue->_alwaysReturnLocalWiFiStatus = NO;
            }
        }
        return returnValue;
    }



    + (instancetype)reachabilityForInternetConnection
    {
        struct sockaddr_in zeroAddress;
        bzero(&zeroAddress, sizeof(zeroAddress));
        zeroAddress.sin_len = sizeof(zeroAddress);
        zeroAddress.sin_family = AF_INET;
        
        return [self reachabilityWithAddress:&zeroAddress];
    }


    + (instancetype)reachabilityForLocalWiFi
    {
        struct sockaddr_in localWifiAddress;
        bzero(&localWifiAddress, sizeof(localWifiAddress));
        localWifiAddress.sin_len = sizeof(localWifiAddress);
        localWifiAddress.sin_family = AF_INET;

        // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.
        localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);

        Reachability* returnValue = [self reachabilityWithAddress: &localWifiAddress];
        if (returnValue != NULL)
        {
            returnValue->_alwaysReturnLocalWiFiStatus = YES;
        }
        
        return returnValue;
    }


    #pragma mark - Start and stop notifier

    - (BOOL)startNotifier
    {
        BOOL returnValue = NO;
        SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};

        if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
        {
            if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
            {
                returnValue = YES;
            }
        }
        
        return returnValue;
    }


    - (void)stopNotifier
    {
        if (_reachabilityRef != NULL)
        {
            SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
        }
    }


    - (void)dealloc
    {
        [self stopNotifier];
        if (_reachabilityRef != NULL)
        {
            CFRelease(_reachabilityRef);
        }
    }


    #pragma mark - Network Flag Handling

    - (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
    {
        PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
        NetworkStatus returnValue = NotReachable;

        if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
        {
            returnValue = ReachableViaWiFi;
        }
        
        return returnValue;
    }


    - (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;
        }
        
        return returnValue;
    }


    - (BOOL)connectionRequired
    {
        NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
        SCNetworkReachabilityFlags flags;

        if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
        {
            return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
        }

        return NO;
    }


    - (NetworkStatus)currentReachabilityStatus
    {
        NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");
        NetworkStatus returnValue = NotReachable;
        SCNetworkReachabilityFlags flags;
        
        if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
        {
       
            
            if (_alwaysReturnLocalWiFiStatus)
            {
                returnValue = [self localWiFiStatusForFlags:flags];
                
             
                
            }
            else
            {
                returnValue = [self networkStatusForFlags:flags];
                
                
            }
        }
        
        return returnValue;
    }


    @end

    以上只是第三方组件,加之一些个人对其封装的一些方法,下面我门就要具体道每个Controller上了,来检测网络环境发生的变化

    Controller.h

    #import <UIKit/UIKit.h>
    #import "Reachability.h"

    @interface ReachViewController : UIViewController
    - (void) reachabilityChanged:(NSNotification *)note;
    - (void)updateInterfaceWithReachability:(Reachability *)reachability;
    - (void)configureTextField:(UITextField *)textField imageView:(UIImageView *)imageView reachability:(Reachability *)reachability;

    @end

    Controller.m

    #import "ReachViewController.h"
    #import "MBProgressHUD.h"
    #import "HUD.h"
    @interface ReachViewController ()
    @property (nonatomic) Reachability *hostReachability;
    @property (nonatomic) Reachability *internetReachability;
    @property (nonatomic) Reachability *wifiReachability;

    @end

    @implementation ReachViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
        

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
        NSString *remoteHostName = @"www.apple.com";
        NSString *remoteHostLabelFormatString = NSLocalizedString(@"Remote Host: %@", @"Remote host label format string");

        self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
        [self.hostReachability startNotifier];
        [self updateInterfaceWithReachability:self.hostReachability];
        

    }


    - (void) reachabilityChanged:(NSNotification *)note
    {
        Reachability* curReach = [note object];
        NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
        [self updateInterfaceWithReachability:curReach];
    }


    - (void)updateInterfaceWithReachability:(Reachability *)reachability
    {
        
        NetworkStatus netStatus = [reachability currentReachabilityStatus];

        switch (netStatus) {
            case ReachableViaWWAN:
            {
                [HUD promptWithString:@"正在使用流量,建议用WiFi" onView:self.view];

            }
                break;
            case ReachableViaWiFi:
            {
                [HUD promptWithString:@"WiFi已连接" onView:self.view];
            
            }
                break;
            default:
                break;
        }
        
        
        
        
    }

    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    当你网络环境发生变化的时候你就可以实时观察到。代码没有任何bug,新建demo,复制粘贴就可以看下效果,如果你的开发环境出现错误就是版本问题了。

  • 相关阅读:
    000_linux之Ubuntu安装
    001_linux基础命令
    018_linux驱动之_阻塞和非阻塞
    019_linux驱动之_定时器的引入
    017_linux驱动之_信号量
    016_linux驱动之_原子操作
    python logging模块整理
    python sys与shutil模块
    python configparser模块
    python os模块
  • 原文地址:https://www.cnblogs.com/hanguoqing/p/4466161.html
Copyright © 2020-2023  润新知