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. 【转】react入门实例教程

    作者: 阮一峰 日期: 2015年3月31日 写在前面:原文链接http://www.ruanyifeng.com/blog/2015/03/react.html    github地址https:/ ...

  2. vue项目中的tab页实现

    //需要自己弄雪碧图 <template> <div class="tab" id="tab"> <router-link to= ...

  3. linux c使用socket进行http 通信,并接收任意大小的http响应(一)

    如何进行http通信呢?我们打开任意一个浏览器,按F12,再选择网络,然后打开任意一个网站,我们就可以看到浏览器和网站通信的过程 如下图: 然后,我们任意点击一条记录,可以看到 然后,查找http协议 ...

  4. 简单易懂的 Vue.js 基础知识 !

    根 vue 实例 let viewModel = new Vue({ // 包含数据.模板.挂载元素.方法.生命周期钩子等选项 }) Hello Wrold  <!-- 这是我们的 View - ...

  5. js带“.”的对象属性名怎么使用

    问题:这样的json对象(event) { "title": "title", "alert":"ding", &quo ...

  6. AFN\HTTPS\UIWebView

    1.AFN使用技巧 1.在开发的时候可以创建一个工具类,继承自我们的AFN中的请求管理者,再控制器中真正发请求的代码使用自己封装的工具类. 2.这样做的优点是以后如果修改了底层依赖的框架,那么我们修改 ...

  7. Zookeeper之入门(原理、基础知识)

    Zookeeper介绍 Zookeeper是分布式应用程序的协调服务框架,是Hadoop的重要组件.ZK要解决的问题: 1.分布式环境下的数据一致性. 2.分布式环境下的统一命名服务 3.分布式环境下 ...

  8. node.js 调用第三方服务

    node作为客户端调用第三方服务   nodejs.cn/api 1. let http = require('http'); let util = require("util") ...

  9. git 在某个分支下创建新分支

    首先要强调一个观念,那就是在某个分支A下创建新的分支B,是指使用A分支下的代码,并不是A/B这样的层级结构. 比如,我想要在非主分支dev 下面创建子分支dev_dev >>>1.创 ...

  10. 4.python字符串格式化

    格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格式.Python用一个tuple将多个值传递给模板,每个值对应一个格式符.py ...