在iOS上检测Internet连接的最简单方法?

Rea*_*lly 147 internet-connection nsurlconnection reachability ios

我知道这个问题似乎是许多其他问题的愚蠢,但是,我觉得这个简单的案例并没有得到很好的解释.来自Android和BlackBerry背景,HTTPUrlConnection如果没有可用连接,立即发出请求失败.这似乎是完全理智的行为,我很惊讶地发现NSURLConnection在iOS中没有效仿它.

我知道Apple(以及其他扩展它的人)提供了一个Reachability帮助确定网络状态的类.我很高兴第一次看到这一点并完全期望看到类似的内容bool isNetworkAvailable(),但令我惊讶的是,我发现了一个复杂的系统,需要通知注册和回调,以及一堆看似不必要的细节.肯定有更好的办法.

我的应用程序已经优雅地处理连接失败,包括没有连接.用户会收到失败通知,然后应用程序继续运行.

因此我的要求很简单:我可以在所有HTTP请求之前调用单个同步函数来确定我是否应该打扰实际发送请求.理想情况下,它不需要设置,只返回一个布尔值.

这在iOS上真的不可能吗?

Sem*_*ium 250

我做了一些研究,我正在用更新的解决方案更新我的答案.我不确定你是否已经看过它,但Apple提供了一个很好的示例代码.

此处下载示例代码

在项目中包含Reachability.h和Reachability.m文件.看看ReachabilityAppDelegate.m,看看如何通过WiFi,WWAN等确定主机可达性,可达性的示例.只需检查网络可达性,就可以做到这样的事情.

Reachability *networkReachability = [Reachability reachabilityForInternetConnection];   
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];    
if (networkStatus == NotReachable) {        
    NSLog(@"There IS NO internet connection");        
} else {        
     NSLog(@"There IS internet connection");        
}
Run Code Online (Sandbox Code Playgroud)

@ BenjaminPiette:不要忘记将SystemConfiguration.framework添加到您的项目中.

  • 不要忘记将SystemConfiguration.framework添加到项目中. (46认同)
  • 小心这个.我发现它在网络恢复时不能可靠地工作,至少在模拟器中是这样.我启动wifi关闭,它正确报告没有网络可用; 但随后我重新打开wifi,SCNetworkReachabilityGetFlags继续返回0,即使实际网络查询工作正常. (3认同)
  • 请注意,这只会告诉您与特定主机的连接是否为*可路由*.这并不意味着你实际上能够连接.示例:您将iPhone的wifi连接到相机的wifi.Wifi与默认网关连接:所有主机都将报告可达.但事实并非如此 - 相机是一个死胡同. (3认同)
  • 我相信我的答案(http://stackoverflow.com/a/26593728/557362)需要较少的工作(不下载其他文件),但这只是我的意见. (2认同)

小智 45

看到这个帖子是这类问题的最佳google结果,我想我会提供适合我的解决方案.我已经在使用AFNetworking,但搜索没有透露如何使用AFNetworking完成此任务,直到我的项目中途.

你想要的是 AFNetworkingReachabilityManager.

// -- Start monitoring network reachability (globally available) -- //
[[AFNetworkReachabilityManager sharedManager] startMonitoring];

[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

    NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status));


    switch (status) {
        case AFNetworkReachabilityStatusReachableViaWWAN:
        case AFNetworkReachabilityStatusReachableViaWiFi:
            // -- Reachable -- //
            NSLog(@"Reachable");
            break;
        case AFNetworkReachabilityStatusNotReachable:
        default:
            // -- Not reachable -- //
            NSLog(@"Not Reachable");
            break;
    }

}];
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下方法同步测试可达性(一旦监控开始):

-(BOOL) isInternetReachable
{
    return [AFNetworkReachabilityManager sharedManager].reachable;
}
Run Code Online (Sandbox Code Playgroud)

  • 我赞成将'AFNetworkReachabilityManager`带入光明之中! (3认同)

exe*_*ecv 40

很抱歉回复得太晚了,但我希望这个答案可以帮助将来的某些人.

以下是一个小的本机C代码片段,可以检查互联网连接,而无需任何额外的课程.

添加以下标头:

#include<unistd.h>
#include<netdb.h>
Run Code Online (Sandbox Code Playgroud)

码:

-(BOOL)isNetworkAvailable
{
    char *hostname;
    struct hostent *hostinfo;
    hostname = "google.com";
    hostinfo = gethostbyname (hostname);
    if (hostinfo == NULL){
        NSLog(@"-> no connection!\n");
        return NO;
    }
    else{
        NSLog(@"-> connection established!\n");
        return YES;
    }
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特3

func isConnectedToInternet() -> Bool {
    let hostname = "google.com"
    //let hostinfo = gethostbyname(hostname)
    let hostinfo = gethostbyname2(hostname, AF_INET6)//AF_INET6
    if hostinfo != nil {
        return true // internet available
      }
     return false // no internet
    }
Run Code Online (Sandbox Code Playgroud)

  • @Laurent:最好的选择是使用您要从中请求数据的服务器地址.google.com就在这里只是一个例子. (8认同)
  • 这只是在进行DNS查找吗?如果是这样,缓存的DNS结果是否可能导致该功能错误地认为网络可用? (7认同)
  • 效果比Apple Reachability好得多.但是根据docs gethostbyname是过时的,你应该使用getaddrinfo:struct addrinfo*res = NULL; int s = getaddrinfo("apple.com",NULL,NULL和res); bool network_ok =(s == 0 && res!= NULL); freeaddrinfo(RES); (3认同)
  • @amar循环运行将消耗无线数据,而您不想这样做。 (2认同)

Gil*_*ton 31

我目前使用这种简单的同步方法,在您的项目或委托中不需要额外的文件.

进口:

#import <SystemConfiguration/SCNetworkReachability.h>
Run Code Online (Sandbox Code Playgroud)

创建此方法:

+(bool)isNetworkAvailable
{
    SCNetworkReachabilityFlags flags;
    SCNetworkReachabilityRef address;
    address = SCNetworkReachabilityCreateWithName(NULL, "www.apple.com" );
    Boolean success = SCNetworkReachabilityGetFlags(address, &flags);
    CFRelease(address);

    bool canReach = success
                    && !(flags & kSCNetworkReachabilityFlagsConnectionRequired)
                    && (flags & kSCNetworkReachabilityFlagsReachable);

    return canReach;
}
Run Code Online (Sandbox Code Playgroud)

然后,如果你把它放在MyNetworkClass:

if( [MyNetworkClass isNetworkAvailable] )
{
   // do something networky.
}
Run Code Online (Sandbox Code Playgroud)

如果您在模拟器中进行测试,请打开和关闭Mac的wifi,因为看起来模拟器将忽略手机设置.

更新:

  1. 最后我使用了一个线程/异步回调来避免阻塞主线程; 并定期重新测试,以便我可以使用缓存结果 - 尽管你应该避免不必要地打开数据连接.

  2. 正如@thunk所描述的那样,有更好的URL可供使用,Apple自己使用这些URL.http://cadinc.com/blog/why-your-apple-ios-7-device-wont-connect-to-the-wifi-network

  • 这对我有用,但当我连接到没有互联网连接的Wi-Fi网络时运行它时,它将我的UI锁定了大约30秒.在这种情况下需要异步方法. (3认同)
  • `www.apple.com`是一个大网站......更好的选择是`www.google.com` (2认同)
  • 很好的答案!一个建议是:测试网址"www.appleiphonecell.com"据说可以严格用于此目的,并且在中国显然没有被屏蔽. (2认同)

Dan*_*lea 11

这是可能的,如果你在完成实现时看一下它真的很简单,这又是 - 非常简单,因为你需要的唯一项目是两个布尔变量:互联网可达性和主机可达性(你经常需要不止一个) ).一旦组装了可以确定连接状态的帮助程序类,您实际上并不关心知道这些过程所需的实现.

例:

#import <Foundation/Foundation.h>

@class Reachability;

@interface ConnectionManager : NSObject {
    Reachability *internetReachable;
    Reachability *hostReachable;
}

@property BOOL internetActive;
@property BOOL hostActive;

- (void) checkNetworkStatus:(NSNotification *)notice;

@end
Run Code Online (Sandbox Code Playgroud)

和.m文件:

#import "ConnectionManager.h"
#import "Reachability.h"

@implementation ConnectionManager
@synthesize internetActive, hostActive;

-(id)init {
    self = [super init];
    if(self) {

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

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

    hostReachable = [[Reachability reachabilityWithHostName:@"www.apple.com"] retain];
    [hostReachable startNotifier];

    return self;
}

- (void) checkNetworkStatus:(NSNotification *)notice {
    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
    switch (internetStatus)

    {
        case NotReachable:
        {
            NSLog(@"The internet is down.");
            self.internetActive = NO;

            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"The internet is working via WIFI.");
            self.internetActive = YES;

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"The internet is working via WWAN.");
            self.internetActive = YES;

            break;

        }
    }

    NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
    switch (hostStatus)

    {
        case NotReachable:
        {
            NSLog(@"A gateway to the host server is down.");
            self.hostActive = NO;

            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"A gateway to the host server is working via WIFI.");
            self.hostActive = YES;

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"A gateway to the host server is working via WWAN.");
            self.hostActive = YES;

            break;

        }
    }

}

// If lower than SDK 5 : Otherwise, remove the observer as pleased.

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

@end
Run Code Online (Sandbox Code Playgroud)


dar*_*s0n 6

有人已经在一个简单的,可重复使用之前的方法解决了这个.DDGReachability.

编辑:或tonymillion/Reachability.