La forma más fácil de detectar la conexión a Internet en iOS?

Sé que esta pregunta parecerá una trampa para muchos otros, sin embargo, no creo que el caso simple esté bien explicado aquí. Procedente de un fondo de Android y BlackBerry, las solicitudes a través de HTTPUrlConnection fallan instantáneamente si no hay conexión disponible. Esto parece un comportamiento completamente sensato, y me sorprendió descubrir que NSURLConnection en iOS no lo emulaba.

Entiendo que Apple (y otras personas que lo han extendido) ofrecen una clase de Reachability para ayudar a determinar el estado de la red. Me alegró ver esto por primera vez y esperé ver algo como bool isNetworkAvailable() , pero para mi sorpresa encontré un sistema complejo que requería registros de notificación y devoluciones de llamada, y un montón de detalles aparentemente innecesarios. Debe haber una mejor manera.

Mi aplicación ya maneja correctamente las fallas de conexión, incluida la falta de conectividad. El usuario recibe una notificación de la falla y la aplicación continúa.

Por lo tanto, mis requisitos son simples: función única y sincrónica a la que puedo llamar antes de todas las solicitudes HTTP para determinar si realmente me molesto en enviar la solicitud o no. Idealmente, no requiere configuración y simplemente devuelve un valor booleano.

¿Esto realmente no es posible en iOS?

Hice un poco más de investigación y estoy actualizando mi respuesta con una solución más actual. No estoy seguro si ya lo ha mirado pero hay un buen código de muestra proporcionado por Apple.

Descargue el código de muestra aquí

Incluya los archivos Reachability.hy Reachability.m en su proyecto. Eche un vistazo a ReachabilityAppDelegate.m para ver un ejemplo sobre cómo determinar la accesibilidad del host, accesibilidad por WiFi, por WWAN, etc. Para una verificación muy simple de la accesibilidad de la red, puede hacer algo como esto

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

@ BenjaminPiette: No olvides agregar SystemConfiguration.framework a tu proyecto.

Viendo que este hilo es el resultado principal de google para este tipo de pregunta, pensé que podría proporcionar la solución que funcionó para mí. Ya estaba usando AFNetworking , pero la búsqueda no reveló cómo lograr esta tarea con AFNetworking hasta la mitad de mi proyecto.

Lo que quiere es 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; } }]; 

También puede usar lo siguiente para probar la accesibilidad de forma síncrona (una vez que se ha iniciado la monitorización):

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

Lamento haber respondido demasiado tarde, pero espero que esta respuesta pueda ayudar a alguien en el futuro.

Lo que sigue es un pequeño fragmento de código C nativo que puede verificar la conectividad a Internet sin ninguna clase adicional.

Agregue los siguientes encabezados:

 #include #include 

Código:

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

Actualmente uso este método simple sincrónico que no requiere archivos adicionales en sus proyectos o delegates.

Importar:

 #import  

Crea este método:

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

Entonces, si has puesto esto en MyNetworkClass :

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

Si está realizando pruebas en el simulador, encienda y apague el wifi de su Mac, ya que parece que el simulador ignorará la configuración del teléfono.

Actualizar:

  1. Al final usé un hilo / callback asincrónica para evitar el locking del hilo principal; y volver a realizar pruebas regularmente para poder utilizar un resultado en caché, aunque debe evitar mantener las conexiones de datos abiertas innecesariamente.

  2. Como se describe en @thunk, hay mejores URL para usar, que Apple usa. http://cadinc.com/blog/why-your-apple-ios-7-device-wont-connect-to-the-wifi-network

Es posible y es muy simple si lo miras al finalizar la implementación, que es de nuevo, muy simple, ya que los únicos elementos que necesitas son dos variables booleanas: accesibilidad de internet y accesibilidad del host (a menudo necesitas más de uno de estos ) Una vez que ensambla su clase de ayudante que puede determinar el estado de las conexiones, realmente no le importa la implementación necesaria para conocer estos procedimientos.

Ejemplo:

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

Y el archivo .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 

Alguien ha resuelto esto de una manera simple y reutilizable antes. DDGReachability .

EDITAR: O tonymillion/Reachability .

Extraje el código y lo puse en un solo método, espero que ayude a otros.

 #import  #import  #import  

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

Creo que esto podría ayudar …

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

Estoy escribiendo aquí la versión rápida de la respuesta aceptada, en caso de que alguien lo encuentre útil, el código se escribe rápidamente 2,

Puede descargar los archivos necesarios desde SampleCode

Agregue los Reachability.h Reachability.m a su proyecto,

Ahora uno necesitará crear Bridging-Header.h archivo Bridging-Header.h si no existe ninguno para su proyecto.

Dentro de su archivo Bridging-Header.h agregue esta línea:

 #import "Reachability.h" 

Ahora para verificar la conexión a 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 } } 

También puede probar este si ya configuró AFNetworking en su proyecto.

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

Aquí hay una buena solución para verificar la conectividad usando Swift, sin usar Accesibilidad. Lo encontré en este blog .

Cree un nuevo archivo Swift en su proyecto llamado Network.swift (por ejemplo). Pegue este código dentro de ese archivo:

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

Luego puede verificar la conectividad en cualquier lugar de su proyecto al usar:

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

EDITAR: Esto no funcionará para las URL de red (ver comentarios)

A partir de iOS 5, hay un nuevo método de instancia NSURL:

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

Dirígete al sitio web que te interesa o apunta a apple.com; Creo que es la nueva llamada de una línea para ver si Internet está funcionando en su dispositivo.

Tampoco estaba contento con las opciones de comprobación de Internet disponibles (¿Por qué no es una API nativa?!?!)

Mi propio problema fue con la pérdida de paquetes al 100%: cuando un dispositivo está conectado al enrutador, pero el enrutador no está conectado a Internet. Accesibilidad y otros colgarán por siglos. Creé una clase singleton de utilidad para manejar eso agregando un tiempo de espera de asincronización. Funciona bien en mi aplicación. Espero eso ayude. Aquí está el enlace en github:

https://github.com/fareast555/TFInternetChecker

Comprobación de la disponibilidad de conexión a Internet en (iOS) Xcode 8.2, Swift 3.0

Este es un método simple para verificar la disponibilidad de la red. Logré traducirlo a Swift 2.0 y aquí el código final. La clase Apple Reachability existente y otras bibliotecas de terceros parecían ser demasiado complicadas para traducir a Swift.

Esto funciona tanto para conexiones 3G como WiFi.

No olvide agregar “SystemConfiguration.framework” a su creador de proyectos.

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

Reemplazo de Reachability de Apple reescrito en Swift con cierres , inspirado en tonymillion: https://github.com/ashleymills/Reachability.swift

  1. Reachability.swift el archivo Reachability.swift en su proyecto. Alternativamente, use CocoaPods o Carthage – Consulte la sección Instalación del archivo README del proyecto.

  2. Recibe notificaciones sobre conectividad de red:

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

    y para detener notificaciones

     reachability.stopNotifier() 

Alamofire

Si ya está utilizando Alamofire para todos los RESTful Api, aquí está lo que puede beneficiarse de eso.

Puede agregar la siguiente clase a su aplicación y llamar a MNNetworkUtils.main.isConnected() para obtener un booleano, ya sea que esté conectado o no.

 #import Alamofire class MNNetworkUtils { static let main = MNNetworkUtils() init() { manager = NetworkReachabilityManager(host: "google.com") listenForReachability() } private let manager: NetworkReachabilityManager? private var reachable: Bool = false private func listenForReachability() { self.manager?.listener = { [unowned self] status in switch status { case .notReachable: self.reachable = false case .reachable(_), .unknown: self.reachable = true } } self.manager?.startListening() } func isConnected() -> Bool { return reachable } } 

Esta es una clase singleton. En todo momento, cuando el usuario se conecta o desconecta de la red, anulará el self.reachable de self.reachable en verdadero / falso correctamente, porque comenzamos a escuchar el NetworkReachabilityManager en la inicialización de singleton.

Además, para controlar la accesibilidad, debe proporcionar un host. En este momento estoy usando google.com Siéntase libre de cambiar a cualquier otro host o uno de los suyos si es necesario.

    Intereting Posts