如何在 iOS 或 macOS 上检查活动的互联网连接?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1083701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check for an active Internet connection on iOS or macOS?
提问by Brock Woolf
I would like to check to see if I have an Internet connection on iOS using the Cocoa Touchlibraries or on macOS using the Cocoalibraries.
我想检查一下我是否在使用Cocoa Touch库的iOS或使用Cocoa库的macOS上有互联网连接。
I came up with a way to do this using an NSURL
. The way I did it seems a bit unreliable (because even Google could one day be down and relying on a third party seems bad), and while I could check to see for a response from some other websites if Google didn't respond, it does seem wasteful and an unnecessary overhead on my application.
我想出了一种使用NSURL
. 我这样做的方式似乎有点不可靠(因为即使有一天谷歌可能会宕机并且依赖第三方似乎很糟糕),虽然如果谷歌没有回应,我可以查看其他一些网站的回应,它对我的应用程序来说似乎是浪费和不必要的开销。
- (BOOL) connectedToInternet
{
NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
return ( URLString != NULL ) ? YES : NO;
}
Is what I have done bad, (not to mention stringWithContentsOfURL
is deprecated in iOS 3.0 and macOS 10.4) and if so, what is a better way to accomplish this?
我做的不好(更不用说stringWithContentsOfURL
在 iOS 3.0 和 macOS 10.4 中已弃用),如果是这样,有什么更好的方法来实现这一目标?
采纳答案by iwasrobbed
Important: This check should alwaysbe performed asynchronously. The majority of answers below are synchronous so be careful otherwise you'll freeze up your app.
重要提示:此检查应始终异步执行。下面的大多数答案都是同步的,所以要小心,否则你会冻结你的应用程序。
Swift
迅速
1) Install via CocoaPods or Carthage: https://github.com/ashleymills/Reachability.swift
1) 通过 CocoaPods 或 Carthage 安装:https: //github.com/ashleymills/Reachability.swift
2) Test reachability via closures
2) 通过闭包测试可达性
let reachability = Reachability()!
reachability.whenReachable = { reachability in
if reachability.connection == .wifi {
print("Reachable via WiFi")
} else {
print("Reachable via Cellular")
}
}
reachability.whenUnreachable = { _ in
print("Not reachable")
}
do {
try reachability.startNotifier()
} catch {
print("Unable to start notifier")
}
Objective-C
目标-C
1) Add SystemConfiguration
framework to the project but don't worry about including it anywhere
1)将SystemConfiguration
框架添加到项目中,但不要担心将其包含在任何地方
2) Add Tony Million's version of Reachability.h
and Reachability.m
to the project (found here: https://github.com/tonymillion/Reachability)
2) 将 Tony Million 的Reachability.h
和版本添加Reachability.m
到项目中(在此处找到:https: //github.com/tonymillion/Reachability)
3) Update the interface section
3)更新界面部分
#import "Reachability.h"
// Add this to the interface in the .m file of your view controller
@interface MyViewController ()
{
Reachability *internetReachableFoo;
}
@end
4) Then implement this method in the .m file of your view controller which you can call
4) 然后在你可以调用的视图控制器的 .m 文件中实现这个方法
// Checks if we have an internet connection or not
- (void)testInternetConnection
{
internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com"];
// Internet is reachable
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Yayyy, we have the interwebs!");
});
};
// Internet is not reachable
internetReachableFoo.unreachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Someone broke the internet :(");
});
};
[internetReachableFoo startNotifier];
}
Important Note:The Reachability
class is one of the most used classes in projects so you might run into naming conflicts with other projects. If this happens, you'll have to rename one of the pairs of Reachability.h
and Reachability.m
files to something else to resolve the issue.
重要提示:本Reachability
类是最常用的类别中的一个项目,所以你可能会遇到的命名与其他项目冲突。如果发生这种情况,您必须将Reachability.h
和Reachability.m
文件对中的一个重命名为其他名称以解决问题。
Note:The domain you use doesn't matter. It's just testing for a gateway to any domain.
注意:您使用的域无关紧要。它只是测试通往任何域的网关。
回答by cannyboy
I like to keep things simple. The way I do this is:
我喜欢保持简单。我这样做的方法是:
//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;
}
Then, I use this whenever I want to see if I have a connection:
然后,每当我想查看是否有连接时,我都会使用它:
if (![self connected]) {
// Not connected
} else {
// Connected. Do some Internet stuff
}
This method doesn't wait for changed network statuses in order to do stuff. It just tests the status when you ask it to.
此方法不会等待更改的网络状态来执行操作。它只是在您要求时测试状态。
回答by Andrew Zimmer
Using Apple's Reachability code, I created a function that'll check this correctly without you having to include any classes.
使用 Apple 的 Reachability 代码,我创建了一个函数,它可以正确检查这一点,而无需包含任何类。
Include the SystemConfiguration.framework in your project.
在您的项目中包含 SystemConfiguration.framework。
Make some imports:
做一些进口:
#import <sys/socket.h>
#import <netinet/in.h>
#import <SystemConfiguration/SystemConfiguration.h>
Now just call this function:
现在只需调用此函数:
/*
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;
}
And it's iOS 5tested for you.
它是为您测试的iOS 5。
回答by Daniel Rinser
This used to be the correct answer, but it is now outdated as you should subscribe to notifications for reachability instead. This method checks synchronously:
这曾经是正确的答案,但现在已经过时了,因为您应该订阅可访问性通知。此方法同步检查:
You can use Apple's Reachability class. It will also allow you to check if Wi-Fi is enabled:
您可以使用 Apple 的 Reachability 类。它还允许您检查是否启用了 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) {?}
The Reachability class is not shipped with the SDK, but rather a part of this Apple sample application. Just download it, and copy Reachability.h/m to your project. Also, you have to add the SystemConfiguration framework to your project.
Reachability 类未随 SDK 一起提供,而是此 Apple 示例应用程序的一部分。只需下载它,然后将 Reachability.h/m 复制到您的项目中。此外,您必须将 SystemConfiguration 框架添加到您的项目中。
回答by Erik
Here's a very simple answer:
这是一个非常简单的答案:
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");
The URL should point to an extremely small website. I use Google's mobile website here, but if I had a reliable web server I'd upload a small file with just one character in itfor maximum speed.
URL 应该指向一个非常小的网站。我在这里使用谷歌的移动网站,但如果我有一个可靠的网络服务器,我会上传一个只有一个字符的小文件以获得最大速度。
If checking whether the device is somehowconnected to the Internet is everything you want to do, I'd definitely recommend using this simple solution. If you need to know how the user is connected, using Reachability is the way to go.
如果检查设备是否以某种方式连接到 Internet 是您想做的一切,我绝对建议您使用这个简单的解决方案。如果您需要知道用户是如何连接的,那么使用 Reachability 是一种可行的方法。
Careful: This will briefly block your thread while it loads the website. In my case, this wasn't a problem, but you should consider this (credits to Brad for pointing this out).
小心:这将在加载网站时暂时阻止您的线程。就我而言,这不是问题,但您应该考虑这一点(感谢 Brad 指出这一点)。
回答by klcjr89
Here is how I do it in my apps: While a 200 status response code doesn't guarantee anything, it is stable enough for me. This doesn't require as much loading as the NSData answers posted here, as mine just checks the HEAD response.
以下是我在我的应用程序中的做法:虽然 200 状态响应代码并不能保证任何事情,但它对我来说已经足够稳定了。这不需要像此处发布的 NSData 答案那样多的加载,因为我的只是检查 HEAD 响应。
Swift Code
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 Code
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
}
}];
}
回答by teabot
Apple supplies sample codeto check for different types of network availability. Alternatively there is an examplein the iPhone developers cookbook.
Apple 提供示例代码来检查不同类型的网络可用性。或者,iPhone 开发人员手册中有一个示例。
Note:Please see @KHG's comment on this answer regarding the use of Apple's reachability code.
注意:请参阅@KHG 对此答案的评论,有关 Apple 的可达性代码的使用。
回答by Aleksander Azizi
You could use Reachability
by ? (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.
回答by Aleksander Azizi
回答by Ben Groot
Only the Reachability class has been updated. You can now use:
只有 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");}