¿Cómo puedo comprobar si hay una conexión a Internet activa en iOS o macOS?
Me gustaría comprobar si tengo una conexión a Internet en iOS usando las bibliotecas Cocoa Touch o en macOS usando las bibliotecas Cocoa .
Se me ocurrió una manera de hacer esto usando un archivo NSURL
. La forma en que lo hice parece un poco poco confiable (porque incluso Google podría algún día dejar de funcionar y depender de un tercero parece malo), y aunque podría verificar la respuesta de otros sitios web si Google no respondiera, Parece un desperdicio y una sobrecarga innecesaria en mi aplicación.
- (BOOL)connectedToInternet {
NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
return ( URLString != NULL ) ? YES : NO;
}
¿Lo que he hecho está mal (sin mencionar stringWithContentsOfURL
que está obsoleto en iOS 3.0 y macOS 10.4) y, de ser así, cuál es una mejor manera de lograrlo?
Importante : esta comprobación siempre debe realizarse de forma asincrónica. La mayoría de las respuestas a continuación son sincrónicas, así que tenga cuidado, de lo contrario congelará su aplicación.
Rápido
Instalar a través de CocoaPods o Carthage: https://github.com/ashleymills/Reachability.swift
Probar la accesibilidad mediante cierres
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") }
C objetivo
Agregue
SystemConfiguration
framework al proyecto pero no se preocupe por incluirlo en ningún ladoAgregue la versión de Tony Million de
Reachability.h
yReachability.m
al proyecto (que se encuentra aquí: https://github.com/tonymillion/Reachability )Actualizar la sección de la interfaz
#import "Reachability.h" // Add this to the interface in the .m file of your view controller @interface MyViewController () { Reachability *internetReachableFoo; } @end
Luego implemente este método en el archivo .m de su controlador de vista al que puede llamar
// 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]; }
Nota importante: la Reachability
clase es una de las clases más utilizadas en proyectos, por lo que podría tener conflictos de nombres con otros proyectos. Si esto sucede, tendrá que cambiar el nombre de uno de los pares de archivos Reachability.h
y Reachability.m
a otro para resolver el problema.
Nota: El dominio que utilices no importa. Es solo una prueba de una puerta de entrada a cualquier dominio.
Me gusta mantener las cosas simples. La forma en que hago esto es:
//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;
}
Luego, uso esto cada vez que quiero ver si tengo conexión:
if (![self connected]) {
// Not connected
} else {
// Connected. Do some Internet stuff
}
Este método no espera a que cambien los estados de la red para poder hacer cosas. Simplemente prueba el estado cuando se lo pides.
Usando el código de Accesibilidad de Apple, creé una función que verificará esto correctamente sin que tengas que incluir ninguna clase.
Incluya SystemConfiguration.framework en su proyecto.
Realiza algunas importaciones:
#import <sys/socket.h>
#import <netinet/in.h>
#import <SystemConfiguration/SystemConfiguration.h>
Ahora simplemente llama a esta función:
/*
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;
}
Y está probado iOS 5 para ti.
Esta solía ser la respuesta correcta, pero ahora está desactualizada, ya que en su lugar debes suscribirte a las notificaciones para estar accesible. Este método comprueba sincrónicamente:
Puede utilizar la clase Accesibilidad de Apple. También te permitirá comprobar si el Wi-Fi está habilitado:
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) { }
La clase Accesibilidad no se incluye con el SDK, sino que forma parte de esta aplicación de muestra de Apple . Simplemente descárguelo y copie Reachability.h/m a su proyecto. Además, debe agregar el marco SystemConfiguration a su proyecto.