iOS 之Reachability的使用

本文介绍如何使用Reachability库检查iOS设备的网络状态,包括WiFi和3G/GPRS连接,并通过实时通知更新网络状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 示例说明:此示例用于演示关于如何使用SystemConfiguratio Reachalility程序接口来判定相关的网络连接状态及状态变化,所以在使用此示例中的Reachability.(h/m)文件于自有的项目中的前提是必须引入SystemConfiguration.framework。

2. 首选分析Reachability.h文件:

-> 首先引入<SystemConfiguration/SystemConfiguration.h>

#import <SystemConfiguration/SystemConfiguration.h>

-> 定义代表网络状态的枚举类型NetworkStatus:

复制代码
// 定义网络请求可到达状态
typedef enum 
{
    NotReachable = 0,   // 不可到达
    ReachableViaWiFi,   // 通过WiFi可到达
    ReachableViaWWAN    // 通过无线广域网可到达(WWAN,即Wireless Wide Area Network,无线广域网。)
} NetworkStatus;
复制代码

-> 宏定义关于网络连接变更的通知标识名称:

#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"

-> 定义相关属性:

BOOL localWiFiRef;    
// 用来保存创建测试连接返回的引用
SCNetworkReachabilityRef reachabilityRef;

 

-> 声明各相关的方法:

// 用于检查网络请求是否可到达指定的主机名
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
// 用于检查网络请求是否可到达指定的IP地址
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
// 用于检查路由连接是否有效
+ (Reachability*) reachabilityForInternetConnection;
// 用于检查本地的WiFi连接是否有效
+ (Reachability*) reachabilityForLocalWiFi;
// 在当前程序的运行回路中开始监听网络请求可到达的通知
- (BOOL) startNotifier;
- (void) stopNotifier;
// 当前网络请求可到达状态
- (NetworkStatus) currentReachabilityStatus;
// 当前网络请求可到达状态
- (NetworkStatus) currentReachabilityStatus;
// 连接需求
- (BOOL) connectionRequired;
复制代码
- (void) applicationDidFinishLaunching: (UIApplication* )application 
{
    [[NSNotificationCenter defaultCenter]  addObserver:self
                            selector:@selector(reachabilityChanged:)
                              name:kReachabilityChangedNotification
                             object:nil];  
    hostReach = [[Reachability reachabilityWithHostName:@"www.apple.com"] retain];
    [hostReach startNotifier];

    internetReach = [[Reachability reachabilityForInternetConnection] retain];
    [internetReach startNotifier];
    [self updateInterfaceWithReachability:internetReach];

    wifiReach = [[Reachability reachabilityForLocalWiFi] retain];
    [wifiReach startNotifier]; 
    [self updateInterfaceWithReachability:wifiReach];

    [window makeKeyAndVisible];
}

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

- (void)updateInterfaceWithReachability:(Reachability *)curReach
{
    if (curReach == hostReach)
    {
        [self configureTextField:remoteHostStateField imageView:remoteHostIcon reachability:curReach];
        NetworkStatus netStatus = [curReach currentReachabilityStates];
        BOOL connectionRequired = [curReach connectionRequired];
        
        summaryLabel.hidden = (netStatus != ReachabilityViaWWAN);
        NSString *baseLabel = @"";
        if (connectionRequired)
        {
            baseLabel = @"Cellular data network is available.\n Internet traffic will be routed through it after a connection is established.";
        }
        else
     {
            baseLabel = @"Cellular data network is active.\n Internet traffic will be routed through it.";
        }
        summaryLabel.text = baseLabel;
    }
    if (curReach == internetReach)
    {
        [self configureTextField:internetConnectionStatusField imageView:internetConnectionIcon reachability:curReach];
    }
    if (curReach == wifiReach)
    {
        [self configureTextField:localWiFiConnectionStatusField imageView:localWiFiConnectionIcon reachability:curReach];
    }
}

- (void)configureTextField:(UITextField *)textField imageView:(UIImageView *)imageView reachability:(Reachability *)curReach
{
    NetworkStatus netStatus = [curReach currentReachabilityStatus];
    BOOL connectionRequired = [curReach connectionRequired];
    NSString *statusString = @"";
    switch (netStatus)
    {
        case NotReachable:
        {
            statusString = @"Access Not Available";
            imageView.image = [UIImage imageNamed:@"stop-32.png"];
            connectionRequired = NO;

            break;
        }
        case ReachableViaWWAN:
        {
            statusString = @"Reachable WWAN";
            imageView.image = [UIImage imageNamed:@"WWAN5.png"];
        
            break;
        }
        case ReachableViaWiFi:
        {
            statusString = @"";
            imageView.image = [UIImage imageNamed:@"Airport.png"];

            break;
        }
    }
    if (connectionRequired)
    {
        statusString = [NSString stringWithFormat:@"%@, Connection Required", statusString];
    }
    textField.text = statusString;
}
复制代码

 

. 关于Reachability.m

参考此链接:http://blog.sina.com.cn/s/blog_65a8ab5d010110w5.html

4. 关于Reachability的使用:

本文转载自:http://www.cnblogs.com/SnailFish/archive/2012/09/18/SCNetworkReachability.html


下面是Reachability的具体使用情况

什么是UDPTCP的区别是什么?
TCP的全称为传输控制协议。这种协议可以提供面向连接的、可靠的、点到点的通信。
UDP全称为用户数据报协议,它可以提供非连接的不可靠的点到多点的通信。
TCP还是UDP,那要看你的程序注重哪一个方面?可靠还是快速?

 

 

 

TCP/IP 建立连接的过程 
TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。 
第一次握手:建立连接时,客户端发送连接请求到服务器,并进入SYN_SEND状态,等待服务器确认; 
第二次握手:服务器收到客户端连接请求,向客户端发送允许连接应答,此时服务器进入SYN_RECV状态; 
第三次握手:客户端收到服务器的允许连接应答,向服务器发送确认,客户端和服务器进入通信状态,完成三次握手。
 
(所谓的三次握手就是要有三次连接信息的发送/接收过程TCP连接的建立需要进行三次连接信息的发送/接收

 


一:确认网络环境3G/WIFI

    1. 添加源文件和framework
    
    开发Web等网络应用程序的时候,需要确认网络环境,连接情况等信息。如果没有处理它们,是不会通过Apple的审(我们的)查的。
    Apple 的 例程 Reachability 中介绍了取得/检测网络状态的方法。要在应用程序程序中使用Reachability,首先要完成如下两部:
    
    1.1. 添加源文件:
    在你的程序中使用 Reachability 只须将该例程中的 Reachability.h 和 Reachability.m 拷贝到你的工程中。如下图:

    
    
    1.2.添加framework:
    将SystemConfiguration.framework 添加进工程。如下图:
    
    
    2. 网络状态
    
    Reachability.h中定义了三种网络状态:
    typedef enum {
        NotReachable = 0,            //无连接
        ReachableViaWiFi,            //使用3G/GPRS网络
        ReachableViaWWAN            //使用WiFi网络
    } NetworkStatus;
    
    因此可以这样检查网络状态:

    Reachability *r = [Reachability reachabilityWithHostName:@“www.apple.com”];
    switch ([r currentReachabilityStatus]) {
            case NotReachable:
                    // 没有网络连接
                    break;
            case ReachableViaWWAN:
                    // 使用3G网络
                    break;
            case ReachableViaWiFi:
                    // 使用WiFi网络
                    break;
    }
    
    3.检查当前网络环境
    程序启动时,如果想检测可用的网络环境,可以像这样
    // 是否wifi
    + (BOOL) IsEnableWIFI {
        return ([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable);
    }

    // 是否3G
    + (BOOL) IsEnable3G {
        return ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable);
    }
    例子:
    - (void)viewWillAppear:(BOOL)animated {    
    if (([Reachability reachabilityForInternetConnection].currentReachabilityStatus == NotReachable) && 
            ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == NotReachable)) {
            self.navigationItem.hidesBackButton = YES;
            [self.navigationItem setLeftBarButtonItem:nil animated:NO];
        }
    }

    4. 链接状态的实时通知
    网络连接状态的实时检查,通知在网络应用中也是十分必要的。接续状态发生变化时,需要及时地通知用户:
    
    Reachability 1.5版本
    // My.AppDelegate.h
    #import "Reachability.h"

    @interface MyAppDelegate : NSObject <UIApplicationDelegate> {
        NetworkStatus remoteHostStatus;
    }

    @property NetworkStatus remoteHostStatus;

    @end

    // My.AppDelegate.m
    #import "MyAppDelegate.h"

    @implementation MyAppDelegate
    @synthesize remoteHostStatus;

    // 更新网络状态
    - (void)updateStatus {
        self.remoteHostStatus = [[Reachability sharedReachability] remoteHostStatus];
    }

    // 通知网络状态
    - (void)reachabilityChanged:(NSNotification *)note {
        [self updateStatus];
        if (self.remoteHostStatus == NotReachable) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"AppName", nil)
                         message:NSLocalizedString (@"NotReachable", nil)
                        delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
            [alert release];
        }
    }

    // 程序启动器,启动网络监视
    - (void)applicationDidFinishLaunching:(UIApplication *)application {
    
        // 设置网络检测的站点
        [[Reachability sharedReachability] setHostName:@"www.apple.com"];
        [[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES];
        // 设置网络状态变化时的通知函数
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:)
                                                 name:@"kNetworkReachabilityChangedNotification" object:nil];
        [self updateStatus];
    }

    - (void)dealloc {
        // 删除通知对象
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        [window release];
        [super dealloc];
    } 
    
    Reachability 2.0版本
    

    // MyAppDelegate.h
    @class Reachability;

        @interface MyAppDelegate : NSObject <UIApplicationDelegate> {
            Reachability  *hostReach;
        }

    @end

    // MyAppDelegate.m
    - (void)reachabilityChanged:(NSNotification *)note {
        Reachability* curReach = [note object];
        NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
        NetworkStatus status = [curReach currentReachabilityStatus];
    
        if (status == NotReachable) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AppName""
                              message:@"NotReachable"
                              delegate:nil
                              cancelButtonTitle:@"YES" otherButtonTitles:nil];
                              [alert show];
                              [alert release];
        }
    }
                              
    - (void)applicationDidFinishLaunching:(UIApplication *)application {
        // ...
                  
        // 监测网络情况
        [[NSNotificationCenter defaultCenter] addObserver:self
                              selector:@selector(reachabilityChanged:)
                              name: kReachabilityChangedNotification
                              object: nil];
        hostReach = [[Reachability reachabilityWithHostName:@"www.google.com"] retain];
        hostReach startNotifer];
        // ...
    }

使用情况的文本转自:http://blog.youkuaiyun.com/z251257144/article/details/7175647


Reachabiliy 想说爱你不容易


[iOS]网络编程专题:Reachability想说爱你不容易

分类: 网络编程专题 iOS iphone   403人阅读  评论(0)  收藏  举报

Reachability是苹果官方给的检查网络状态的库,想必每个基于网络的应用都会用它来检查网络状态吧,当然笔者也不例外.可是正当自信满满的我,用这个库用的不亦乐乎的时候,突然发现我写的基于网络的程序工作的不是那么流畅了,尤其是仔细检查以后确定是因为用了Reachability的时候,一下子觉得的不可理喻,这瞬间的落差让前一分钟还在美滋滋的认为"写程序是艺术,用程序是享受"的我情何以堪?

这种情况就是:连接到了Wifi,但是并不能上网.这时候用Reachability检查会认为设备处在wifi情况下(没错,好像就是wifi环境下),如果这时候你相当然的认为可以正常上网而去获取网络数据的话你就等待网络请求超时吧,而默认的超时时间似乎有15秒之久,程序卡住这么久在用户体验上不可接受的.以前的时候一直觉得Reachability挺神奇的,可以检查出来是wifi还是3G网络,还暗自想它是不是偷偷的连接到了哪台服务器判断网络情况,这次仔细看了下,觉得挺失败的,它区分网络连接的时候只是简单的查看有没有ip地址,哎.这就难怪出现以为是wifi但是上不了网的情况了.解决办法呢?如果是用ASI进行http请求的话,可以简单设置一下超时时间可以在一定程度上避开这个问题:[request setTimeOutSeconds:5];如果是用的NSURLRequest的话,可以用忽略本地缓存并增加超时的方法:NSURLRequest *request = [NSURLRequest requestWithURL:url1 cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];研究到这里,笔者突然觉得发现了一个判断网络连接的办法:


  
  1. NSURL *url1 = [NSURL URLWithString:@"http://rainbird.blog.51cto.com"]; 
  2. NSURLRequest *request = [NSURLRequest requestWithURL:url1 cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10]; 
  3. NSHTTPURLResponse *response; 
  4. [NSURLConnection sendSynchronousRequest:request returningResponse: &response error: nil]; 
  5. if (response == nil) { 
  6.     NSLog(@"没有网络"); 
  7. else
  8.     NSLog(@"网络是通的"); 
简单来说就是进行一个网络请示并设置一下超时时间,然后根据返回结果判断网络连接.当然了你的网络请求最好是返回很简单的数据,请求地址最好也是你将要请求的网络地址(你想想:你要请求baidu的东西,判断google的网络连接性有用么?).友情提示一下,上面一段代码搁在主线程里用依然会卡住界面的哟.
仔细想来Reachability并没有错.错就错在我把用来判断网络连接类型的东西用来判断网络连通性.所以合理的利用工具,做正确的事.

原文出处:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值