在iOS上检测互联网连接最简单的方法?

我知道这个问题似乎是其他许多人的问题,但是,我不觉得这里简单的例子很好解释。 从Android和黑莓的背景来看,如果没有可用的连接,通过HTTPUrlConnection发出请求HTTPUrlConnection立即失败。 这似乎是完全理智的行为,我很惊讶地发现iOS中的NSURLConnection没有效仿它。

据我所知,苹果(和其他扩展了它的人)提供了一个Reachability类来协助确定networking状态。 我很高兴首先看到这一点,并完全期待看到像bool isNetworkAvailable() ,但相反,令我惊讶,我发现一个复杂的系统需要通知注册和callback,以及一堆看似不必要的细节。 一定有更好的办法。

我的应用程序已经正常处理连接失败,包括没有连接。 用户被通知失败,应用程序继续前进。

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

这真的不可能在iOS?

我做了一些更多的研究,并用更新的解决scheme更新我的答案。 我不确定你是否已经看过,但有一个很好的示例代码提供的苹果。

在这里下载示例代码

在您的项目中包含Reachability.h和Reachability.m文件。 看看ReachabilityAppDelegate.m看看如何确定主机的可达性,通过WiFi,WWAN等可达性的例子。为了一个非常简单的networking可达性检查,你可以做这样的事情

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

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

看到这个线程是这类问题的顶级谷歌结果,我想我会提供解决scheme,为我工作。 我已经在使用AFNetworking ,但是直到我的项目进行到中途,search都没有透露如何用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; } }]; 

您也可以使用以下内容来同步testing可达性(一旦监控已经开始):

 -(BOOL) isInternetReachable { return [AFNetworkReachabilityManager sharedManager].reachable; } 

对不起,回复太晚了,但我希望这个答案可以帮助未来的人。

以下是一个小的原生C代码片断,可以检查没有任何额外的类的互联网连接。

添加以下标题:

 #include<unistd.h> #include<netdb.h> 

码:

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

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

我目前使用这个简单的同步方法,不需要额外的文件在您的项目或代表。

import:

 #import <SystemConfiguration/SCNetworkReachability.h> 

创build这个方法:

 +(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; } 

那么,如果你把它放在MyNetworkClass

 if( [MyNetworkClass isNetworkAvailable] ) { // do something networky. } 

如果您在模拟器中进行testing,请开启或closures您的Mac无线networking,因为看起来模拟器将忽略电话设置。

更新:

  1. 最后我用了一个线程/asynchronouscallback来避免阻塞主线程; 并定期重新testing,以便我可以使用caching的结果 – 尽pipe您应该避免不必要地打开数据连接。

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

这是可能的,如果你在完成实现时看起来很简单,这很简单,因为你需要的只有两个布尔variables:互联网可达性和主机可达性(你通常需要多于一个)。 一旦组装了可以确定连接状态的帮助程序类,就不必再为了解这些过程所需的实现了。

例:

 #import <Foundation/Foundation.h> @class Reachability; @interface ConnectionManager : NSObject { Reachability *internetReachable; Reachability *hostReachable; } @property BOOL internetActive; @property BOOL hostActive; - (void) checkNetworkStatus:(NSNotification *)notice; @end 

和.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 

有人已经以简单,可重用的方式解决了这个问题。 DDGReachability

编辑:或tonymillion/Reachability

我提取了代码,并把它放在一个单一的方法,希望能帮助别人。

 #import <SystemConfiguration/SystemConfiguration.h> #import <netinet/in.h> #import <netinet6/in6.h> 

 - (BOOL)isInternetReachable { 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); SCNetworkReachabilityFlags flags; if(reachability == NULL) return false; if (!(SCNetworkReachabilityGetFlags(reachability, &flags))) return false; if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) // if target host is not reachable return false; BOOL isReachable = false; 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 isReachable = true; } 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 isReachable = true; } } if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { // ... but WWAN connections are OK if the calling application // is using the CFNetwork (CFSocketStream?) APIs. isReachable = true; } return isReachable; } 

我认为这可以帮助..

 [[AFNetworkReachabilityManager sharedManager] startMonitoring]; if([AFNetworkReachabilityManager sharedManager].isReachable) { NSLog(@"Network reachable"); } else { NSLog(@"Network not reachable"); } 

我正在写这个被接受的答案的迅捷版本,如果有人发现它有用,代码写成swift 2,

您可以从SampleCode下载所需的文件

Reachability.hReachability.m文件添加到您的项目中,

现在需要创buildBridging-Header.h文件,如果项目不存在的话,

在您的Bridging-Header.h文件中添加以下行:

 #import "Reachability.h" 

现在为了检查Internet连接

 static func isInternetAvailable() -> Bool { let networkReachability : Reachability = Reachability.reachabilityForInternetConnection() let networkStatus : NetworkStatus = networkReachability.currentReachabilityStatus() if networkStatus == NotReachable { print("No Internet") return false } else { print("Internet Available") return true } } 

这里是使用Swift检查连接性的一个很好的解决scheme,而不使用Reachability。 我在这个博客上find了它。

在您的项目中创build一个名为Network.swift的新Swift文件(例如)。 将该代码粘贴到该文件中:

 import Foundation public class Network { class func isConnectedToNetwork()->Bool{ var Status:Bool = false let url = NSURL(string: "http://google.com/") let request = NSMutableURLRequest(URL: url!) request.HTTPMethod = "HEAD" request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData request.timeoutInterval = 10.0 var response: NSURLResponse? var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData? if let httpResponse = response as? NSHTTPURLResponse { if httpResponse.statusCode == 200 { Status = true } } return Status } } 

然后,您可以使用以下方法检查项目中的任何位置的连接:

 if Network.isConnectedToNetwork() == true { println("Internet connection OK") } else { println("Internet connection FAILED") } 

检查(iOS)Xcode 8.2,Swift 3.0中的Internet连接可用性

这是检查networking可用性的简单方法。 我设法把它翻译成Swift 2.0,在这里是最终的代码。 现有的Apple Reachability类和其他第三方库似乎太复杂,无法转换成Swift。

这适用于3G和WiFi连接。

不要忘记将“SystemConfiguration.framework”添加到您的项目构build器中。

 //Create new swift class file Reachability in your project. import SystemConfiguration public class Reachability { class 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) } } // Check network connectivity from anywhere in project by using this code. if Reachability.isConnectedToNetwork() == true { print("Internet connection OK") } else { print("Internet connection FAILED") } 

如果您已经在您的项目中configuration了AFNetworking,您也可以试试这个。

 -(void)viewDidLoad{ // -- add connectivity notification --// [[NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(ReachabilityDidChangeNotification:) name:AFNetworkingReachabilityDidChangeNotification object:nil];} -(void)ReachabilityDidChangeNotification:(NSNotification *)notify { // -- NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status)); -- // NSDictionary *userInfo =[notif userInfo]; AFNetworkReachabilityStatus status= [[userInfo valueForKey:AFNetworkingReachabilityNotificationStatusItem] intValue]; switch (status) { case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: // -- Reachable -- // // -- Do your stuff when internet connection is available -- // [self getLatestStuff]; NSLog(@"Reachable"); break; case AFNetworkReachabilityStatusNotReachable: default: // -- Not reachable -- // // -- Do your stuff for internet connection not available -- // NSLog(@"Not Reachable"); break; } } 

编辑:这将不适用于networkingURL(请参阅评论)

从iOS 5开始,有一个新的NSURL实例方法:

 - (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error 

指向您关心的网站或指向apple.com; 我认为这是一个新的单线电话,看看互联网是否在你的设备上工作。

我也不满意互联网检查选项(为什么这不是一个本地的API?!?!)

我自己的问题是100%的数据包丢失 – 当一个设备连接到路由器,但路由器没有连接到Internet。 可达性和其他人将会持续很长时间。 我创build了一个实用单例类,通过添加一个asynchronous超时来处理这个类。 它在我的应用程序工作正常。 希望它有帮助。 以下是github上的链接:

https://github.com/fareast555/TFInternetChecker

replace苹果的可达性重写在Swift与闭幕,灵感来自tonymillion: https : //github.com/ashleymills/Reachability.swift

  1. 把文件Reachability.swift放到你的项目中。 或者,使用CocoaPods或Carthage – 请参阅项目README的安装部分。

  2. 获取有关networking连接的通知:

     //declare this property where it won't go out of scope relative to your listener let reachability = Reachability()! reachability.whenReachable = { reachability in if reachability.isReachableViaWiFi { 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") } 

    并停止通知

     reachability.stopNotifier()