在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,因为看起来模拟器将忽略电话设置。
更新:
-
最后我用了一个线程/asynchronouscallback来避免阻塞主线程; 并定期重新testing,以便我可以使用caching的结果 – 尽pipe您应该避免不必要地打开数据连接。
-
正如@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.h
和Reachability.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上的链接:
replace苹果的可达性重写在Swift与闭幕,灵感来自tonymillion: https : //github.com/ashleymills/Reachability.swift
-
把文件
Reachability.swift
放到你的项目中。 或者,使用CocoaPods或Carthage – 请参阅项目README的安装部分。 -
获取有关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()