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,复制粘贴就可以看下效果,如果你的开发环境出现错误就是版本问题了。

Reachability实时监控网络变化的更多相关文章

  1. IOS 监控网络变化案例源码

    随着移动网络升级:2G->3G->4G甚至相传正在研发的5G,网络速度是越来越快,但这流量也像流水一般哗哗的溜走. 网上不是流传一个段子:睡觉忘记关流量,第二天房子就归移动了! 这固然是一 ...

  2. iOS实时监控网络状态的改变

    在网络应用中,有的时候需要对用户设备的网络状态进行实时监控,有两个目的: (1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能) (2)根据用户的网络状态进行智能处理,节省用户流量,提高用户体 ...

  3. Iframe 自适应高度并实时监控高度变化的js代码

    不得不用到iframe,且被强烈要求不能让它出现滚动条!嵌入的页面肯定是高度不一的,页面中也不能出现大片空白,所以也不能写死高度!真是麻鬼烦啊!google N次 + 百度M次 + 试验了1605次之 ...

  4. sqlserver ,镜像数据库,CDC,实时监控数据变化

    1.数据库镜像配置 1)主机环境:计算机名称修改SQL1.xiaoping.com 添加用户sqluser 密码永不变,率属于administrators sqlserver安装时,将所有sqlser ...

  5. 实时监控文件变化以及处理xml(仅用作笔记用,防止以后要用)

    private static void WatcherStrat(string path, string filter) { try { FileSystemWatcher watcher = new ...

  6. iftop实时监控网络流量

    需要安装,linux自身不自带该命令 中间的<= =>这两个左右箭头,表示的是流量的方向. TX:发送流量 RX:接收流量 TOTAL:总流量 Cumm:运行iftop到目前时间的总流量 ...

  7. 在windows下实时监控、接受文件变化小工具

    在windows下实时监控文件变化小工具   在测试的时候,我们可能想实时监控系统打出的log信息,在unix系统上我们可以用"tail -f"实现,在windows下一般就无法做 ...

  8. 3、架构--cp、scp、rsync、实时监控与同步

    笔记 1.晨考 1.VPN的搭建步骤 2.vpn中的iptables是什么作用? 网络转发 2.昨日问题 1.yum源问题 2.VPN链接正常,但是没办法通过172 3.VPN链接时,出现了DNS错误 ...

  9. 用c#监控网络状态

    1.查询当前网络状态: using Microsoft.VisualBasic.Devices; //判断当前网络连接状态 Network nw=new Network(); if(nw.IsAvai ...

随机推荐

  1. win10下vs2015编译的程序如何运行在win7等系统(无需安装Redistributable)

    最近新写的程序要做beta测试,在做绿色版(免安装版)时遇到了问题,vs2015做的项目本以为像之前的vs版本一样把msvcrXXX.dll还有另外几个运行时库都放到exe旁边即可,然并卵...,在w ...

  2. day18_python_1124

    01 鸡汤 荷花定律 山竹定律 金蝉定律 荷花定律: 明天比今天要生长多一倍,池塘三十天生长满,第29天是一半. 山竹定律: 竹子在生长时,前三年只出地表3厘米,从第四年开始,以每天30cm的速度开始 ...

  3. angularjs 下滑线滑动

    css: .detail_row { width: 410px; height: 34px; clear: both; border-bottom: 1px solid #eaeeef; font-s ...

  4. Android : Android Studio 更新至gradle 4.10.1后Variants API变化

    同步警告: WARNING: API 'variantOutput.getPackageApplication()' is obsolete and has been replaced with 'v ...

  5. 事务理解及Spring中的事务

    一.隔离级别理解 1.脏读 首先理解,一个事务对数据进行了改变,尽管该事务尚未提交,但此时其他事务中的查询语句(注意一定是处于事务中的语句,不处于事务中的语句查到的是正常的)查到的数据,是该事务修改之 ...

  6. 《JavaScript Dom 编程艺术》读书笔记-第6章

    本章继续对图片库进行改进,主要内容包括三个方面: 1. 把事件处理函数移出文档: 2. 向后兼容: 3. 确保可访问. 之前代码的HTML片段,此时如果浏览器不支持JS,图片显示也能正常工作,只是体验 ...

  7. Spring中的@Bean注解、@Configuration注解、@Value

    1.首先是注册bean类:@Component.@Responsitory.@Controller.@Service.Configuration这些注解是把要实例化的对象装化成一个bean,放到Ioc ...

  8. python中Requests库错误和异常

    主要有以下四种: 1.Requests抛出一个ConnectionError异常,原因为网络问题(如DNS查询失败.拒接连接等错误) 2.Response.raise_for_status()抛出一个 ...

  9. python day 25--正则表达式

    一.字符组 1.[0-9]表示匹配0-9中的数字 2.[a-z]表示匹配a-z之间的字母 3.[A-Z]表示匹配大写的字母 4.[0-9a-zA-Z]匹配所有字母数字 二.元字符 1.\d 匹配任意数 ...

  10. 二进制安装MySQL数据库

    今天安装的是二进制的mysql包5.7.21的包,在配置文件的时候采了好多坑,左后还是搞定了,来和大家分享一下 二进制msyql5.7.21版本的主从复制安装 新建/picclife目录 mkdir  ...