如何使用可达性类来检测有效的互联网连接?

Posted

技术标签:

【中文标题】如何使用可达性类来检测有效的互联网连接?【英文标题】:How to use reachability class to detect valid internet connection? 【发布时间】:2011-03-04 14:28:34 【问题描述】:

我是 ios 开发的新手,正在努力让reachability.h 类正常工作。这是我的视图控制器代码:

- (void)viewWillAppear:(BOOL)animated

    [[NSNotificationCenter defaultCenter]
     addObserver:self 
     selector:@selector(checkNetworkStatus:) 
     name:kReachabilityChangedNotification 
     object:nil];

    internetReachable = [Reachability reachabilityForInternetConnection];
    [internetReachable startNotifier];


- (void)checkNetworkStatus:(NSNotification *)notice 
    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
    NSLog(@"Network status: %i", internetStatus);

看起来不错,但在运行应用程序并切换到该视图时,xcode 控制台中没有出现任何内容。

我正在使用可达性 2.2 和 iOS 4.2。

有什么明显的我做错了吗?

【问题讨论】:

【参考方案1】:

已编辑:如果您想在执行某些代码之前检查可访问性,您应该使用

Reachability *reachability = [Reachability reachabilityForInternetConnection];    
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if (internetStatus != NotReachable) 
    //my web-dependent code

else 
    //there-is-no-connection warning

您还可以在某处添加可达性观察者(即在 viewDidLoad 中):

Reachability *reachabilityInfo;
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(myReachabilityDidChangedMethod)
                                             name:kReachabilityChangedNotification
                                           object:reachabilityInfo];

当您不再需要可达性检测(即在dealloc 方法中)时,不要忘记调用[[NSNotificationCenter defaultCenter] removeObserver:self];

【讨论】:

感谢您,但我收到一条错误消息,提示找不到 -isReachable。您的示例是否是旧版本的可达性? 这可能会造成很大的麻烦。按需 *** 连接以及其他有问题的事情怎么样? 当然不是必须的,但我无法想象没有任何可达性的良好网络服务相关应用【参考方案2】:

这就是我的做法。我在我的 init 方法中设置了一个实例变量:

_reachability = [[APReachability reachabilityForInternetConnection] retain];

当我需要查询网络状态时,我会这样做:

NetworkStatus networkStatus = [_reachability currentReachabilityStatus];
if (networkStatus != NotReachable) 
    // Network related code

else 
    // No network code

如果你关心wifi等,网络状态可以是:

    NotReachable // No network
    ReachableViaWiFi // Reachable via Wifi
    ReachableViaWWAN // Reachable via cellular

【讨论】:

【参考方案3】:

更新:2013 年 11 月 4 日

在 iOS7 上使用 Reachability 3.0 版本

建立在@NR4TR 和@codecaffeine 的答案之上:

有 5 种方法可以做到这一点(未编译:)

#include <ifaddrs.h>
#include <arpa/inet.h>

//1 - Is www.apple.com reachable?
Reachability *rHostName = [Reachability reachabilityWithHostName:@"www.apple.com"];
NetworkStatus s1 = [rHostName currentReachabilityStatus];

//2 - Is local wifi router or access point reachable?
Reachability *rLocalWiFi = [Reachability reachabilityForLocalWiFi];
NetworkStatus s2 = [rLocalWiFi currentReachabilityStatus];

//3 - Is my access point connected to a router and the router connected to the internet?
Reachability *rConnection = [Reachability reachabilityForInternetConnection];
NetworkStatus s3 = [rConnection currentReachabilityStatus];

//4  IPv4 standard addresses checking instead of host to avoid dns lookup step
struct sockaddr_in saIPv4;
inet_pton(AF_INET, "74.125.239.51", &(saIPv4.sin_addr));
saIPv4.sin_len = sizeof(saIPv4);
saIPv4.sin_family = AF_INET;
Reachability *rIPv4 = [Reachability reachabilityWithAddress:&saIPv4];
NetworkStatus s4 = [rIPv4 currentReachabilityStatus];

//5  IPv6 addresses checking instead of host to avoid dns lookup step
struct sockaddr_in saIPv6;
inet_pton(AF_INET, "2607:f8b0:4010:801::1014", &(saIPv6.sin_addr));
saIPv6.sin_len = sizeof(saIPv6);
saIPv6.sin_family = AF_INET;
Reachability *rIPv6 = [Reachability reachabilityWithAddress:&saIPv6];
NetworkStatus s5 = [rIPv6 currentReachabilityStatus];

处理状态相同

if (ReachableViaWiFi == s1)
    return @"WiFi"; //@"WLAN"

if (ReachableViaWWAN == s1)
    return @"Cellular"; //@"WWAN"

return @"None";

【讨论】:

【参考方案4】:

点击这个链接,它有非常有用的源代码和步骤 https://github.com/tonymillion/Reachability。 这为您提供了有关如何在 Reachability 中使用不同方法进行游戏的信息。

添加 system.configuration.framewok,并将 Reachability.m 和 Reachability.h 文件添加到您的项目中。使用后有类似的方法

+(instancetype)reachabilityWithHostName:(NSString*)hostname;
+(instancetype)reachabilityForInternetConnection;
+(instancetype)reachabilityWithAddress:(void *)hostAddress;
+(instancetype)reachabilityForLocalWiFi;

示例 sn-p:

- (void)CheckConnection



    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(reachabilityChanged:) 
                                                 name:kReachabilityChangedNotification 
                                               object:nil];


    Reachability * reach = [Reachability reachabilityWithHostname:@"www.google.com"];

    reach.reachableBlock = ^(Reachability * reachability)
    
        dispatch_async(dispatch_get_main_queue(), ^
            _blockLabel.stringValue = @"Block Says Reachable";
        );
    ;

    reach.unreachableBlock = ^(Reachability * reachability)
    
        dispatch_async(dispatch_get_main_queue(), ^
            _blockLabel.stringValue = @"Block Says Unreachable";
        );
    ;

    [reach startNotifier];

希望对你有帮助

【讨论】:

【参考方案5】:

只需导入可达性类,然后

-(BOOL) connectedToNetwork
 
const char *host_name = "www.google.com";
  BOOL _isDataSourceAvailable = NO;
Boolean success;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL,host_name);
SCNetworkReachabilityFlags flags;
success = SCNetworkReachabilityGetFlags(reachability, &flags);
_isDataSourceAvailable = success &&
(flags & kSCNetworkFlagsReachable) &&
!(flags & kSCNetworkFlagsConnectionRequired);

CFRelease(reachability);

return _isDataSourceAvailable;

【讨论】:

【参考方案6】:

参考下面的代码检查Internet Connectivity

struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
// Recover reachability flags
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr*)&zeroAddress);
SCNetworkReachabilityFlags flags;
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags) 
    return 0;

BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;

BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
NSURL *testURL = [NSURL URLWithString:@"http://www.google.com/"];
NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];

NSURLResponse *response = nil;
NSError *error = nil;

NSData *connectiondata = [NSURLConnection sendSynchronousRequest:testRequest
returningResponse:&response

BOOL connection=NO;

if ([connectiondata length] > 0 &&
error == nil)
    NSLog(@"Connection present” );
    connection=YES;
 else 
    NSLog(@"No Connection" );
    connection=NO;


return ((isReachable && !needsConnection) || nonWiFi) ? (connection ? YES : NO) : NO;

【讨论】:

【参考方案7】:

最简单的方法(一旦您将Reachability 添加到您的项目中):

Reachability *reachability = [Reachability reachabilityForInternetConnection];
if (reachability.isReachable) 
    NSLog(@"We have internet!");
 else 
    NSLog(@"No internet!");

【讨论】:

以上是关于如何使用可达性类来检测有效的互联网连接?的主要内容,如果未能解决你的问题,请参考以下文章

蜂窝数据的可达性测试

如何在 iOS 中测试可达性并重试连接?

检测 Internet 连接并显示 UIAlertview Swift 3

使用 AFNetworking 2 和可达性没有互联网连接警报

如何以编程方式通过 ipad 检测并连接到 3G 网络

如何在没有互联网连接的情况下持续显示警报?