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. 获取GitHub上远程分支内容

    一.clone项目 二.获取远程特定分支的内容 1.查看所有分支 git branch --all # 默认有了ls和master分支,所以会看到如下三个分支 # master[本地主分支] orig ...

  2. Eclipse 手动增加linker library

    多个cu文件nvcc -cubin -m64 -lcudadevrt -lcublas_device -gencode arch=compute_35,code=sm_35 -o test.cubin ...

  3. python之路-----网络编程

    一:客户端/服务端j架构(C/S架构) 在生活中,最常见的C/S架构即是APP和网页服务器这个架构.Client和Server之间利用网络来进行通信,客户端和服务器端的程序不同,用户的程序主要在客户端 ...

  4. 汇编语言debug入门

    进入windows操作系统,因为我的虚拟机用的是win7 64位,所以装了一个Dos Box 的软件来执行这些指令. 输入debug回车,这样就进入了debug模式. 1: 输入 -r 查看或者修改寄 ...

  5. ﺑﯘﻟﺒﯘﻟﻼﺭ--思恋--IPA--维吾尔语

    很美的维语歌曲, 迪里拜尔将之唱得十分动人心弦.

  6. [Leetcode 46]全排列 Permutations 递归

    [题目] Given a collection of distinct integers, return all possible permutations. 数组的组合情况. Input: [1,2 ...

  7. 1.HTML初识

    一.认识什么是纯文本文件txt windows中自带一个软件,叫做记事本,记事本保存的文档格式就是txt格式,就是英语text的缩写,术语上,称呼这个文件为"纯文本格式" .doc ...

  8. [HAOI2007]反素数

    这道题其实就是求在 [1,n] 的区间内,那个数的约数个数最多,如果同样多,取最小... 那么我们只需要把质因数分解反过来做,然后更新答案就好了... 素数不需要筛出来,直接打表就好,因为只能用到几个 ...

  9. PAT B1029

    # PAT B1029 这道题主要有两个问题需要解决: 如何在不区分大小写的情况下判断第一个字符串中有哪些字符串没有在第二个中出现 如何确保同一个字符(不区分大小写)只输出一次,且英文均用大小写输出 ...

  10. Jsの练习-数组常用方法 -splice()

    splice() 功能:1.可以实现删除,插入和替换. 删除:可以删除任意数量的项,只需指定2个参数:要删除的第一项的位置和要删除的项数. 例如:splice(0,2)会删除数组中的前2项. 插入:可 ...