ChatGPT解决这个技术问题 Extra ChatGPT

如何在 iOS 或 macOS 上检查活动的 Internet 连接?

我想查看是否在 iOS 上使用 Cocoa Touch 库或在 macOS 上使用 Cocoa 库连接到 Internet。

我想出了一种使用 NSURL 的方法。我这样做的方式似乎有点不可靠(因为即使谷歌有一天可能会失败并且依赖第三方似乎很糟糕),虽然如果谷歌没有回应,我可以查看其他网站的回应,它对我的应用程序来说似乎是浪费和不必要的开销。

- (BOOL)connectedToInternet {
    NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
    return ( URLString != NULL ) ? YES : NO;
}

我做错了什么(更不用说在 iOS 3.0 和 macOS 10.4 中已弃用 stringWithContentsOfURL),如果是这样,有什么更好的方法来实现这一点?

而是 return (BOOL)URLString;,甚至更好,return !!URLStringreturn URLString != nil
我不知道您的用例是什么,但如果可以的话,最好尝试请求并处理任何错误,例如出现的缺少连接。如果你不能做到这一点,那么在这种情况下,这里有很多很好的建议。
您的解决方案很聪明,我更喜欢它。您还可以使用 NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://twitter.com/getibox"] encoding:NSUTF8StringEncoding error:nil]; 来摆脱烦人的警告。
尝试使用以下链接中的可达性类,它将为您工作github.com/tonymillion/Reachability
对于最近找到此答案的人:stackoverflow.com/a/8813279

P
Peter Mortensen

重要提示:此检查应始终异步执行。下面的大多数答案都是同步的,所以要小心,否则你会冻结你的应用程序。

迅速

通过 CocoaPods 或 Carthage 安装:https://github.com/ashleymills/Reachability.swift 通过闭包测试可达性 letreachability = Reachability()! reachability.whenReachable = { 可达性 in if reachability.connection == .wifi { print("通过 WiFi 可达") } else { print("通过蜂窝网络可达") } }reachability.whenUnreachable = { _ in print("不可达" ) } 做 { 尝试reachability.startNotifier() } catch { print("Unable to start notifier") }

Objective-C

将 SystemConfiguration 框架添加到项目中,但不要担心将其包含在任何地方 将 Tony Million 的 Reachability.h 和 Reachability.m 版本添加到项目中(可在此处找到:https://github.com/tonymillion/Reachability) 更新接口部分#import "Reachability.h" // 将此添加到视图控制器的 .m 文件中的接口 @interface MyViewController () { Reachability *internetReachableFoo; } @end 然后在你可以调用的视图控制器的 .m 文件中实现这个方法 // 检查我们是否有互联网连接 - (void)testInternetConnection { internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com "]; // Internet 是可达的 internetReachableFoo.reachableBlock = ^(Reachability*reach) { // 在主线程上更新 UI dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"Yayyy, we have the interwebs!"); }); }; // Internet 不可达 internetReachableFoo.unreachableBlock = ^(Reachability*reach) { // 在主线程上更新 UI dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"有人破坏了 internet :("); }); }; [internetReachableFoo startNotifier]; }

重要提示: Reachability 类是项目中最常用的类之一,因此您可能会遇到与其他项目的命名冲突。如果发生这种情况,您必须将成对的 Reachability.hReachability.m 文件之一重命名为其他名称以解决问题。

注意:您使用的域无关紧要。它只是测试通往任何域的网关。


@gonzobrains:您使用的域无关紧要。它只是测试通往任何域的网关。
@KaanDedeoglu 这只是一个例子,使用你想要的任何域。它只是检查通往 Internet 的网关,而不是检查该域是否实际可用。
哦,顺便说一句,您还需要将 SystemConfiguration.framework 添加到项目中(对于方法 1)。
使用 www.appleiphonecell.com 而不是 google.com - 这个 url 正是出于这个原因由苹果创建的。
@iWasRobbed - 泰。我发现一篇博文准确地说明了您在说什么:code.tutsplus.com/tutorials/…
P
Peter Mortensen

我喜欢让事情变得简单。我这样做的方法是:

//Class.h
#import "Reachability.h"
#import <SystemConfiguration/SystemConfiguration.h>

- (BOOL)connected;

//Class.m
- (BOOL)connected
{
    Reachability *reachability = [Reachability reachabilityForInternetConnection];
    NetworkStatus networkStatus = [reachability currentReachabilityStatus];
    return networkStatus != NotReachable;
}

然后,每当我想查看是否有连接时,我都会使用它:

if (![self connected]) {
    // Not connected
} else {
    // Connected. Do some Internet stuff
}

此方法不会等待更改的网络状态来执行操作。它只是在您要求时测试状态。


嗨@msec,您可以在此页面中尝试 Andrew Zimmer 解决方案,它可以在断开连接的 adsl(和连接 wifi)的情况下正常工作
对于那些像我用上面的代码一样复制和粘贴的人。还要手动添加 SystemConfiguration.framework 否则会出现链接错误。
如果我用 WiFi 连接,总是可以到达。 WiFi 并不意味着它有互联网连接。我想验证互联网连接,即使它有 WiFi 连接。你能帮帮我吗?
C
Cœur

使用 Apple 的 Reachability 代码,我创建了一个函数,可以正确检查这一点,而无需包含任何类。

在您的项目中包含 SystemConfiguration.framework。

做一些进口:

#import <sys/socket.h>
#import <netinet/in.h>
#import <SystemConfiguration/SystemConfiguration.h>

现在只需调用此函数:

/*
Connectivity testing code pulled from Apple's Reachability Example: https://developer.apple.com/library/content/samplecode/Reachability
 */
+(BOOL)hasConnectivity {
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
    if (reachability != NULL) {
        //NetworkStatus retVal = NotReachable;
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
            if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
            {
                // If target host is not reachable
                return NO;
            }

            if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
            {
                // If target host is reachable and no connection is required
                //  then we'll assume (for now) that your on Wi-Fi
                return YES;
            }


            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
                    return YES;
                }
            }

            if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
            {
                // ... but WWAN connections are OK if the calling application
                //     is using the CFNetwork (CFSocketStream?) APIs.
                return YES;
            }
        }
    }

    return NO;
}

iOS 5为您测试过。


@JezenThomas 这不会异步执行互联网检查,这就是它“更苗条”的原因......您应该始终通过订阅通知来异步执行此操作,这样您就不会在此过程中挂断应用程序。
谢谢,即使您使用 wifi adsl 并且 adsl 未连接,这项工作也正是我所需要的。
这会泄漏内存 - 需要使用 CFRelease() 释放“可读性”结构(对象、事物)。
奇怪的是,这个答案比我的(在标记为重复的问题上)早了 2 年,与我的完全一样,但直到今天我才看到它。
P
Peter Mortensen

这曾经是正确的答案,但现在已经过时了,因为您应该订阅通知以获得可访问性。此方法同步检查:

您可以使用 Apple 的可达性类。它还允许您检查是否启用了 Wi-Fi:

Reachability* reachability = [Reachability sharedReachability];
[reachability setHostName:@"www.example.com"];    // Set your host name here
NetworkStatus remoteHostStatus = [reachability remoteHostStatus];

if (remoteHostStatus == NotReachable) { }
else if (remoteHostStatus == ReachableViaWiFiNetwork) { }
else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { }

Reachability 类不随 SDK 一起提供,而是 this Apple sample application 的一部分。只需下载它,然后将 Reachability.h/m 复制到您的项目中。此外,您必须将 SystemConfiguration 框架添加到您的项目中。


请参阅我上面关于不使用这样的可达性的评论。在异步模式下使用它并订阅它发送的通知——不要。
这段代码是一个很好的起点,您可以在使用可访问性类的委托方法之前进行设置。
P
Peter Mortensen

这是一个非常简单的答案:

NSURL *scriptUrl = [NSURL URLWithString:@"http://www.google.com/m"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data)
    NSLog(@"Device is connected to the Internet");
else
    NSLog(@"Device is not connected to the Internet");

URL 应该指向一个非常小的网站。我在这里使用谷歌的移动网站,但如果我有一个可靠的网络服务器,我会上传一个只有一个字符的小文件,以获得最大的速度。

如果检查设备是否以某种方式连接到 Internet 是您想要做的一切,我绝对推荐使用这个简单的解决方案。如果您需要了解用户是如何连接的,那么使用可达性是您的最佳选择。

小心:这将在加载网站时短暂阻止您的线程。就我而言,这不是问题,但您应该考虑这一点(感谢 Brad 指出这一点)。


我真的很喜欢这个想法,但我会说 99.999% 的可靠性同时保持较小的响应大小,请使用 www.google.com/m,它是谷歌的移动视图。
很棒的解决方案@Erik。正如 rwyland 所说,我还建议您使用 www.google.com,而不是 www.google.com/m。这很奇怪,但根据我的测试,移动版总是比 www.google.com 多花大约 120 毫秒
Apple 文档建议不要这样做,因为它会阻塞慢速网络上的线程,可能导致应用程序在 iOS 中终止
感谢您的积极反馈,同意 www.google.com/m 是可靠的最佳解决方案!
大声笑,我相信谷歌感谢你建议人们将它们用作互联网检查资源。
k
klcjr89

以下是我在我的应用程序中执行此操作的方法:虽然 200 状态响应代码不能保证任何事情,但它对我来说足够稳定。这不需要与此处发布的 NSData 答案一样多的加载,因为我的只是检查 HEAD 响应。

SWIFT代码

func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
{
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    let url = NSURL(string: "http://www.google.com/")
    let request = NSMutableURLRequest(URL: url!)

    request.HTTPMethod = "HEAD"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
    request.timeoutInterval = 10.0

    NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
    {(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in

        UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        let rsp = response as! NSHTTPURLResponse?

        completionHandler(internet:rsp?.statusCode == 200)
    })
}

func yourMethod()
{
    self.checkInternet(false, completionHandler:
    {(internet:Bool) -> Void in

        if (internet)
        {
            // "Internet" aka Google URL reachable
        }
        else
        {
            // No "Internet" aka Google URL un-reachable
        }
    })
}

Objective-C 代码

typedef void(^connection)(BOOL);

- (void)checkInternet:(connection)block
{
    NSURL *url = [NSURL URLWithString:@"http://www.google.com/"];
    NSMutableURLRequest *headRequest = [NSMutableURLRequest requestWithURL:url];
    headRequest.HTTPMethod = @"HEAD";

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    defaultConfigObject.timeoutIntervalForResource = 10.0;
    defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;

    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];

    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:headRequest
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        if (!error && response)
        {
            block([(NSHTTPURLResponse *)response statusCode] == 200);
        }
    }];
    [dataTask resume];
}

- (void)yourMethod
{
    [self checkInternet:^(BOOL internet)
    {
         if (internet)
         {
             // "Internet" aka Google URL reachable
         }
         else
         {
             // No "Internet" aka Google URL un-reachable
         }
    }];
}

似乎这是最快的方法
警告:根据我的经验,此解决方案并非一直有效。在许多情况下,返回的响应是 403,经过一段时间后。这个解决方案看起来很完美,但不能保证 100% 的结果。
截至 2014 年 6 月,这在中国大陆将失败,因为中国政府现在完全封锁了 google.com。 (虽然google.cn可以工作,但在中国大陆,没有baidu.com,没有互联网)可能最好ping通您需要与之通信的任何服务器。
请改用 www.appleiphonecell.com - 苹果正是出于这个原因创建了这个网址。
我用的是appleiphonecell,因为它是苹果自己的,在中国也可以使用,而且它是一个非常快的网站。这与您的回答一起为我提供了最接近和最快的解决方案。谢谢
M
Moshe

Apple 提供 sample code 来检查不同类型的网络可用性。或者,在 iPhone 开发人员手册中有一个 example

注意:请参阅@KHG 对此答案关于使用 Apple 可达性代码的评论。


谢谢。我发现 3.0 中的 Xcode 文档也包含源代码,通过在文档中搜索“可达性”找到。
请注意,Apple 的 Reachability 示例代码的新版本 (09-08-09) 是异步的。
链接已失效
A
Aleksander Azizi

您可以使用  (available here) 旁的 Reachability

#import "Reachability.h"

- (BOOL)networkConnection {
    return [[Reachability reachabilityWithHostName:@"www.google.com"] currentReachabilityStatus];
}

if ([self networkConnection] == NotReachable) { /* No Network */ } else { /* Network */ } //Use ReachableViaWiFi / ReachableViaWWAN to get the type of connection.

@Supertecnoboff 不,它是异步的。
N
NANNAV

Apple 提供了一个示例应用程序,它正是这样做的:

Reachability


您应该注意,可达性示例仅检测哪些接口处于活动状态,而不检测哪些接口具有与 Internet 的有效连接。即使 Reachability 报告一切准备就绪,应用程序也应该优雅地处理故障。
令人高兴的是,3.0 中的情况要好得多,因为系统将为锁定 WiFi 后面的用户显示一个登录页面,您必须登录才能使用...您过去必须手动检查重定向(而且您仍然这样做如果开发 2.2.1 应用程序)
我不会说 Reachability 应用程序完全符合要求。然而,这是添加所需功能的一个很好的起点,
链接断开!,如果可以检查/修复,将不胜感激,非常感谢
P
Peter Mortensen

只有 Reachability 类已更新。您现在可以使用:

Reachability* reachability = [Reachability reachabilityWithHostName:@"www.apple.com"];
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];

if (remoteHostStatus == NotReachable) { NSLog(@"not reachable");}
else if (remoteHostStatus == ReachableViaWWAN) { NSLog(@"reachable via wwan");}
else if (remoteHostStatus == ReachableViaWiFi) { NSLog(@"reachable via wifi");}

除非自 4.0 发布以来发生了某些变化,否则该代码不是异步的,并且您可以保证看到它出现在崩溃报告中 - 我以前发生过。
我同意bpapa。使用同步代码不是一个好主意。谢谢你的信息
P
Peter Mortensen

iOS 5 的可达性版本是darkseed/Reachability.h。不是我的! =)


N
NANNAV

这里有一个漂亮的、使用 ARC 和 GCD 的可达性现代化:

Reachability


P
Peter Mortensen

使用 iOS 12 或 macOS v10.14 (Mojave) 或更新版本时,您可以使用 NWPathMonitor 而不是史前 Reachability 类。作为奖励,您可以轻松检测当前的网络连接类型:

import Network // Put this on top of your class

let monitor = NWPathMonitor()

monitor.pathUpdateHandler = { path in
    if path.status != .satisfied {
        // Not connected
    }
    else if path.usesInterfaceType(.cellular) {
        // Cellular 3/4/5g connection
    }
    else if path.usesInterfaceType(.wifi) {
        // Wi-Fi connection
    }
    else if path.usesInterfaceType(.wiredEthernet) {
        // Ethernet connection
    }
}

monitor.start(queue: DispatchQueue.global(qos: .background))

更多信息:https://developer.apple.com/documentation/network/nwpathmonitor


完美运行。比当前顶部更好的解决方案。
由于 Apple 已将 Reachability 替换为 NWPathMonitor,因此现在应该将其设置为正确答案。
这是检查互联网连接的方法吗?如果我在通过 wifi 连接的本地网络上怎么办?那么我确实有WIFI,但是当WAN调制解调器/路由器没有连接时,我仍然没有互联网连接。
B
Bruno Koga

如果您使用 AFNetworking,您可以使用它自己的实现来获取 Internet 可访问性状态。

使用 AFNetworking 的最佳方法是继承 AFHTTPClient 类并使用该类来进行网络连接。

使用此方法的优点之一是您可以使用 blocks 在可达性状态更改时设置所需的行为。假设我创建了一个名为 BKHTTPClientAFHTTPClient 单例子类(如 AFNetworking docs 上的“子类化说明”中所述),我会执行以下操作:

BKHTTPClient *httpClient = [BKHTTPClient sharedClient];
[httpClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
{
    if (status == AFNetworkReachabilityStatusNotReachable) 
    {
    // Not reachable
    }
    else
    {
        // Reachable
    }
}];

您还可以专门使用 AFNetworkReachabilityStatusReachableViaWWANAFNetworkReachabilityStatusReachableViaWiFi 枚举 (more here) 检查 Wi-Fi 或 WLAN 连接。


P
Peter Mortensen

我使用了 this discussion 中的代码,它似乎工作正常(阅读整个 线程!)。

我还没有对每一种可能的连接方式(比如 ad hoc Wi-Fi)进行详尽的测试。


这段代码并不完全好,因为它只是检查你是否有与路由器的 wifi 连接,而不是是否可以访问网络。您可以让 wifi 正常工作并继续启用以访问网络。
P
Peter Mortensen

非常简单....尝试以下步骤:

第 1 步:SystemConfiguration 框架添加到您的项目中。

第 2 步:将以下代码导入您的 header 文件。

#import <SystemConfiguration/SystemConfiguration.h>

第三步:使用下面的方法

类型 1: - (BOOL) currentNetworkStatus { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; BOOL 已连接; BOOL 已连接; const char *host = "www.apple.com"; SCNetworkReachabilityRef 可达性 = SCNetworkReachabilityCreateWithName(NULL, host); SCNetworkReachabilityFlags 标志;已连接 = SCNetworkReachabilityGetFlags(可达性, &flags);已连接 = 否; isConnected = 已连接 && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired); CFRelease(可达性);返回已连接; }

类型 2:导入标头:#import "Reachability.h" - (BOOL)currentNetworkStatus { Reachability *reachability = [ReachabilityreachabilityForInternetConnection]; NetworkStatus networkStatus = [可达性 currentReachabilityStatus];返回网络状态!= NotReachable; }

第4步:如何使用:

- (void)CheckInternet
{
    BOOL network = [self currentNetworkStatus];
    if (network)
    {
        NSLog(@"Network Available");
    }
    else
    {
        NSLog(@"No Network Available");
    }
}

类型 1 是异步的吗?
我想要你的答案中的类型 2 修复。我已经添加了可达性类,并尝试使用您的答案检查连接验证。即使我连接到 WiFi 但它没有互联网连接,它总是可以访问的。 WiFi 并不意味着它有互联网连接。我想验证互联网连接,即使它有 WiFi 连接。你能帮帮我吗?
M
Mutawe
-(void)newtworkType {

 NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews];
NSNumber *dataNetworkItemView = nil;

for (id subview in subviews) {
    if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
        dataNetworkItemView = subview;
        break;
    }
}


switch ([[dataNetworkItemView valueForKey:@"dataNetworkType"]integerValue]) {
    case 0:
        NSLog(@"No wifi or cellular");
        break;

    case 1:
        NSLog(@"2G");
        break;

    case 2:
        NSLog(@"3G");
        break;

    case 3:
        NSLog(@"4G");
        break;

    case 4:
        NSLog(@"LTE");
        break;

    case 5:
        NSLog(@"Wifi");
        break;


    default:
        break;
}
}

即使设备连接到 Wifi 或其他网络类型,互联网连接仍可能不可用。简单测试:连接到您的家庭 wifi,然后拔下您的电缆调制解调器。仍然连接到 wifi,但零互联网。
一个解释将是有序的。例如,想法/要点是什么?请通过 editing (changing) your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似内容 - 答案应该看起来好像是今天写的)。
P
Peter Mortensen
- (void)viewWillAppear:(BOOL)animated
{
    NSString *URL = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];

    return (URL != NULL ) ? YES : NO;
}

或者使用可达性类。

使用 iPhone SDK 检查 Internet 可用性的方法有两种:

1.检查谷歌页面是否打开。

2.可达性类

如需更多信息,请参阅Reachability(Apple 开发者)。


在 iPhone SDK 中检查互联网可用性有两种方法 1) 检查 Google 页面是否打开。
-1:这是一种同步方法,在尝试连接到 google.com 时会阻塞主线程(应用 UI 更改的那个)。如果您的用户的数据连接速度非常慢,则手机会表现得好像该过程没有响应。
P
Peter Mortensen

使用 http://huytd.github.io/datatify/。这比自己添加库和编写代码更容易。


P
Peter Mortensen

首先:在框架中添加 CFNetwork.framework

代码ViewController.m

#import "Reachability.h"

- (void)viewWillAppear:(BOOL)animated
{
    Reachability *r = [Reachability reachabilityWithHostName:@"www.google.com"];
    NetworkStatus internetStatus = [r currentReachabilityStatus];

    if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
    {
        /// Create an alert if connection doesn't work
        UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:@"No Internet Connection"   message:NSLocalizedString(@"InternetMessage", nil)delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [myAlert show];
        [myAlert release];
    }
    else
    {
         NSLog(@"INTERNET IS CONNECT");
    }
}

P
Peter Mortensen

斯威夫特 3 / 斯威夫特 4

您必须先导入

import SystemConfiguration

您可以通过以下方法检查 Internet 连接:

func isConnectedToNetwork() -> Bool {

    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)

    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }

    var flags = SCNetworkReachabilityFlags()
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
        return false
    }
    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
    return (isReachable && !needsConnection)
}

P
Peter Mortensen

首先下载可达性类并将reachability.h 和reachabilty.m 文件放入您的Xcode

最好的方法是制作一个通用的 Functions 类(NSObject),以便您可以在任何类中使用它。以下是网络连接可达性检查的两种方法:

+(BOOL) reachabiltyCheck
{
    NSLog(@"reachabiltyCheck");
    BOOL status =YES;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(reachabilityChanged:)
                                          name:kReachabilityChangedNotification
                                          object:nil];
    Reachability * reach = [Reachability reachabilityForInternetConnection];
    NSLog(@"status : %d",[reach currentReachabilityStatus]);
    if([reach currentReachabilityStatus]==0)
    {
        status = NO;
        NSLog(@"network not connected");
    }
    reach.reachableBlock = ^(Reachability * reachability)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    };
    reach.unreachableBlock = ^(Reachability * reachability)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    };
    [reach startNotifier];
    return status;
}

+(BOOL)reachabilityChanged:(NSNotification*)note
{
    BOOL status =YES;
    NSLog(@"reachabilityChanged");
    Reachability * reach = [note object];
    NetworkStatus netStatus = [reach currentReachabilityStatus];
    switch (netStatus)
    {
        case NotReachable:
            {
                status = NO;
                NSLog(@"Not Reachable");
            }
            break;

        default:
            {
                if (!isSyncingReportPulseFlag)
                {
                    status = YES;
                    isSyncingReportPulseFlag = TRUE;
                    [DatabaseHandler checkForFailedReportStatusAndReSync];
                }
            }
            break;
    }
    return status;
}

+ (BOOL) connectedToNetwork
{
    // Create zero addy
    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)
    {
        NSLog(@"Error. Could not recover network reachability flags");
        return NO;
    }
    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
    NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
    NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL  cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
    NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];
    return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
}

现在您可以通过调用此类方法检查任何类中的网络连接。


P
Peter Mortensen

还有另一种使用 iPhone SDK 检查 Internet 连接的方法。

尝试为网络连接实现以下代码。

#import <SystemConfiguration/SystemConfiguration.h>
#include <netdb.h>

/**
     Checking for network availability. It returns
     YES if the network is available.
*/
+ (BOOL) connectedToNetwork
{

    // Create zero addy
    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)
    {
        printf("Error. Could not recover network reachability flags\n");
        return NO;
    }

    BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
    BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);

    return (isReachable && !needsConnection) ? YES : NO;
}

P
Peter Mortensen

自己做这件事非常简单。以下方法将起作用。请确保不允许将主机名协议(例如 HTTP、HTTPS 等)与名称一起传入。

-(BOOL)hasInternetConnection:(NSString*)urlAddress
{
    SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [urlAddress UTF8String]);
    SCNetworkReachabilityFlags flags;
    if (!SCNetworkReachabilityGetFlags(ref, &flags))
    {
        return NO;
    }
    return flags & kSCNetworkReachabilityFlagsReachable;
}

它快速简单且无痛。


P
Peter Mortensen

我发现它简单易用的库 SimplePingHelper

示例代码:chrishulbert/SimplePingHelper (GitHub)


P
Peter Mortensen

下载 Reachability 文件,https://gist.github.com/darkseed/1182373 并在框架中添加 CFNetwork.framework 和 'SystemConfiguration.framework' 执行 #import "Reachability.h"

首先:在框架中添加 CFNetwork.framework

代码ViewController.m

- (void)viewWillAppear:(BOOL)animated
{
    Reachability *r = [Reachability reachabilityWithHostName:@"www.google.com"];
    NetworkStatus internetStatus = [r currentReachabilityStatus];

    if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
    {
        /// Create an alert if connection doesn't work
        UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:@"No Internet Connection"   message:NSLocalizedString(@"InternetMessage", nil)delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [myAlert show];
        [myAlert release];
    }
    else
    {
         NSLog(@"INTERNET IS CONNECT");
    }
}

P
Peter Mortensen

Reachability 类可以确定设备是否可以使用 Internet 连接...

但是在访问 Intranet 资源的情况下:

使用可达性类 ping 内网服务器始终返回 true。

因此,在这种情况下,一个快速的解决方案是创建一个名为 pingme 的 Web 方法以及服务上的其他 Web 方法。 pingme 应该返回一些东西。

所以我在常用函数上写了如下方法

-(BOOL)PingServiceServer
{
    NSURL *url=[NSURL URLWithString:@"http://www.serveraddress/service.asmx/Ping"];

    NSMutableURLRequest *urlReq=[NSMutableURLRequest requestWithURL:url];

    [urlReq setTimeoutInterval:10];

    NSURLResponse *response;

    NSError *error = nil;

    NSData *receivedData = [NSURLConnection sendSynchronousRequest:urlReq
                                                 returningResponse:&response
                                                             error:&error];
    NSLog(@"receivedData:%@",receivedData);

    if (receivedData !=nil)
    {
        return YES;
    }
    else
    {
        NSLog(@"Data is null");
        return NO;
    }
}

上面的方法对我来说非常有用,所以每当我尝试向服务器发送一些数据时,我总是使用这个低超时 URLRequest 检查我的 Intranet 资源的可达性。


P
Peter Mortensen

除了可达性之外,您还可以使用 Simple Ping helper library。它工作得非常好,并且易于集成。


P
Peter Mortensen

我认为这是最好的答案。

“是”表示已连接。 “否”表示断开连接。

#import "Reachability.h"

 - (BOOL)canAccessInternet
{
    Reachability *IsReachable = [Reachability reachabilityForInternetConnection];
    NetworkStatus internetStats = [IsReachable currentReachabilityStatus];

    if (internetStats == NotReachable)
    {
        return NO;
    }
    else
    {
        return YES;
    }
}

P
Peter Mortensen

对于我的 iOS 项目,我建议使用

可达性等级

在 Swift 中声明。对我来说,它与

Wi-Fi 和蜂窝数据

import SystemConfiguration

public class Reachability {

    class func isConnectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }

        var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }

        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        let ret = (isReachable && !needsConnection)
        return ret
    }
}

使用条件语句,

if Reachability.isConnectedToNetwork() {
    // Enter your code here
}
}
else {
    print("NO Internet connection")
}

此类几乎在您的应用程序使用 Internet 连接的所有情况下都很有用。例如如果条件为真,则可以调用 API 或执行任务。


受到Devang Tandel's answer的“启发”?