iphone - iphone SDK如何检查活动Internet Connection?

  显示原文与译文双语对照的内容

我想看看我是否使用 Cocoa Touch 库在iPhone上有一个互联网连接。

我提出了一种使用 NSURL 实现这一点的方法。 我application,上我做到了似乎有一些不可靠的( 因为即使谷歌一天都能关闭并依赖 3 rd的聚会似乎很糟糕) 而且,虽然我的方式可以检查,看看是否有一个其他网站如果谷歌未响应发送的响应,那它确实比较浪费和一个不必要的overhead.


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

是我做的坏事? ( 更不用说 stringWithContentsOfURL 在 3.0中被废弃了),如果是的话,更好的方法是什么?

时间:

1: 使用简单( 圆弧和梯边梁兼容) 类来实现它 方法

1 ) 将 SystemConfiguration 框架添加到项目中,但不考虑在任何地方包括它

2 ) 将 Reachability.hReachability.m的Tony版本添加到项目( 在这里找到: https://github.com/tonymillion/Reachability )

3 ) 更新接口部分


#import"Reachability.h"

//Add this to the interface in the. m file of your view controller
@interface MyViewController ()
{
 Reachability *internetReachableFoo;
}
@end

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];
}


方法 2: 使用过时的苹果可达类来实现旧的方法

1 ) 将 SystemConfiguration 框架添加到项目中,但不考虑在任何地方包括它

2 ) 将 Reachability.hReachability.m的苹果版本添加到项目( 你可以在这里获得 )

3 ) 将 @class Reachability; 添加到你正在执行代码的. h 文件

interface 部分的. h 4 ) 创建几个实例来检查


Reachability* internetReachable;
Reachability* hostReachable;

5 ) 在. h 中添加网络状态更新的方法:


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

6 ) 将 #import"Reachability.h" 添加到你正在执行检查的. m 文件中

7 ) 在执行检查的. m 文件中,你可以将它的放入第一个名为( init 或者 viewWillAppear 或者 viewDidLoad 等)的方法中:


-(void) viewWillAppear:(BOOL)animated
{
//check for internet connection
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];

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

//check if a pathway to a random host exists
 hostReachable = [Reachability reachabilityWithHostName:@"www.apple.com"];
 [hostReachable startNotifier];

//now patiently wait for the notification
}

8 ) 设置发送通知的方法和设置任何检查或者调用任何方法的方法( 在我的例子中,我只是设置一个 BOOL )


-(void) checkNetworkStatus:(NSNotification *)notice
{
//called after network status changes
 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;
 }
 }
}

9 ) 在 dealloc 或者 viewWillDisappear 或者类似方法中,将自己作为观察者删除


-(void) viewWillDisappear:(BOOL)animated
{
 [[NSNotificationCenter defaultCenter] removeObserver:self];
}

注意:可能有一个使用 viewWillDisappear的实例,在那里你收到一个内存警告,观察者永远不会被注销,所以你也应该考虑到。


注意域你是使用并不重要。 它只是测试一个通往任何域的网关。

其他项目比如重要提示:Reachability 类是一个被广泛使用的类放入到项目中,以便你可能遇到的命名 conflicts. 如果发生这种情况,你必须将 Reachability.hReachability.m 文件中的一个重命名为其他的,以解决这个问题。

我喜欢保持简单。 我这样做的方法是:


//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 
}

这里方法不等待更改的网络状态,以便执行操作,它只是在你请求。

使用apple代码的可达性,我创建了一个函数,它可以在不包含任何类的情况下正确检查。

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

进行一些导入


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

现在调用这个函数


/* 
Connectivity testing code pulled from Apple's Reachability Example: http://developer.apple.com/library/ios/#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;
}

它是为你测试的iOS5.

于可达instead,相关编辑: 这个习惯是正确的答案,但现在已经过时了,因为你可以订阅到 notifications. 这里方法同步检查:

你可以使用苹果类的可达性。 它还允许你检查是否启用了 WiFi:


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) { }

可以到达类不是随SDK一起发行的,而是示例应用程序 。xml的一部分。 只需下载并复制可以达到的。h/m 到你的项目。 另外,你必须将SystemConfiguration框架添加到你的项目中。

下面是一个非常简单的答案:


NSURL *scriptUrl = [NSURL URLWithString:@"http://apps.wegenerlabs.com/hi.html"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data)
 NSLog(@"Device is connected to the internet");
else
 NSLog(@"Device is not connected to the internet");

网址指向一个非常小的网站,可以在蜂窝网络中快速加载。 欢迎使用我的网站,但你也可以在自己的网站上放置一个小文件。

如果检查设备是否是否以某种方式使用这个简单的solution, 一台上网的一切你想做的,我肯定不会 recommend.

苹果提供示例代码来检查不同类型的网络可用性。 或者,在iPhone开发者的手册中也有一个示例

注意: 请参见 @KHG's 对此有什么评论回答关于那些使用苹果的可以到达性的代码。

以下是我在我的应用中的操作: 200状态响应代码不保证任何东西,它对我来说足够稳定了。 这不需要尽可能多的加载作为NSData答案张贴在这里,和我只是检查头部的回应。

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
 }
 else
 {
//No"Internet" aka no Google
 }
 })
}

Objective C 代码


typedef void(^connection)(BOOL);

- (void)checkInternet:(connection)block
{
 [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

 NSURL *url = [NSURL URLWithString:@"http://www.google.com/"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
 request.HTTPMethod = @"HEAD";
 request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
 request.timeoutInterval = 10.0;

 [NSURLConnection sendAsynchronousRequest:request
 queue:[NSOperationQueue mainQueue]
 completionHandler:
 ^(NSURLResponse *response, NSData *data, NSError *connectionError)
 {
 [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
 block([(NSHTTPURLResponse *)response statusCode] == 200);
 }];
}

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

苹果提供了一个示例应用,它可以做到:

可达

精确检查( 可达方法):

导入:


#import"Reachability.h"

布尔:


-(BOOL)CheckNetwork {
ATReachability *Reachability = [ATReachability reachabilityWithHostName:@"www.google.com"];
NetworkStatus NetworkStatus = [Reachability currentReachabilityStatus];
return NetworkStatus; }

检查代码:


if([self CheckNetwork] == NotReachable) {/* No Network */} else {/* Network */}

例如:


- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
 if([self CheckNetwork] == NotReachable) {
/* No Network */
 } else { 
/* Network */
 }
}

或者你可以做( UIWebView方法):


-(IBAction)NetworkCheck {
//Use this to"call" the check
 UIWebView *networkChecker = [[UIWebView alloc] init];
 [networkChecker loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/"]]];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
 NSString *checkError = [[error debugDescription] substringFromIndex:[[error debugDescription] length] -35];

 if ([checkError isEqualToString:@""Could not connect to the server."}"]) {/* No Network */}
 if ([checkError isEqualToString:@"Could not connect to the server."}"]) {/* No Network */}
 if ([checkError isEqualToString:@""connection appears to be offline."}"]) {/* No Network */}
 if ([checkError isEqualToString:@"connection appears to be offline."}"]) {/* No Network */}
}

很好的话题,有点老了,不过还是谢谢了。 只更新了可达类。 你现在可以使用:


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");}

...