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


Sé que esta pregunta parecerá ser un engaño de muchos otros, sin embargo, no siento que el caso simple esté bien explicado aquí. Viniendo de un fondo de Android y BlackBerry, realizar solicitudes a través de HTTPUrlConnection fallan instantáneamente si no hay conexión disponible. Esto parece un comportamiento completamente cuerdo, y me sorprendió encontrar NSURLConnection en iOS no lo emulaba.

Entiendo que Apple (y otros que lo han extendido) proporcionan una clase Reachability para ayudar a determinar la red estado. Estaba feliz de ver esto primero y esperaba ver algo como bool isNetworkAvailable(), pero en cambio, para mi sorpresa, encontré un sistema complejo que requiere registros de notificación y devoluciones de llamada, y un montón de detalles aparentemente innecesarios. Debe haber una manera mejor.

Mi aplicación ya maneja correctamente los errores de conexión, incluida la falta de conectividad. El usuario recibe una notificación del fallo y la aplicación continúa.

Por lo tanto, mis requisitos son simples: Función síncrona única que puedo llamar antes de todas las solicitudes HTTP para determinar si debería molestarme en enviar realmente la solicitud o no. Idealmente no requiere ninguna configuración y solo devuelve un booleano.

¿Esto realmente no es posible en iOS?

Author: Palec, 2012-01-11

16 answers

Investigué un poco más y estoy actualizando mi respuesta con una solución más actual. No estoy seguro de si ya lo has visto, pero hay un buen código de ejemplo proporcionado por Apple.

Descargue el código de ejemplo aquí

Incluya la Accesibilidad.h y Accesibilidad.m archivos en su proyecto. Echa un vistazo a ReachabilityAppDelegate.m para ver un ejemplo sobre cómo determinar la accesibilidad del host, la accesibilidad por WiFi, por WWAN, etc. Para una comprobación muy sencilla de la red accesibilidad, usted 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's: No olvides añadir SystemConfiguration.marco para su proyecto.

 249
Author: Semere Taézaz Sium,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-16 02:03:18

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

Lo que quieres 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 sincrónica (una vez que se haya iniciado el monitoreo):

-(BOOL) isInternetReachable
{
    return [AFNetworkReachabilityManager sharedManager].reachable;
}
 44
Author: sherbertman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-29 22:37:02

Lo siento por responder demasiado tarde, pero espero que esta respuesta pueda ayudar a alguien en el futuro.

A continuación se muestra 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<unistd.h>
#include<netdb.h>

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
    }
 38
Author: execv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-12 12:37:00

Actualmente uso este método síncrono simple que no requiere archivos adicionales en sus proyectos o delegados.

Importación:

#import <SystemConfiguration/SCNetworkReachability.h>

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 un MyNetworkClass:

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

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

Actualización:

  1. Al final usé un callback thread/asincrónico para evitar bloquear el principal thread; y regularmente volver a probar para que pueda usar un resultado en caché, aunque debe evitar mantener las conexiones de datos abiertas innecesariamente.

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

 31
Author: GilesDMiddleton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-24 20:37:14

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

Ejemplo:

#import <Foundation/Foundation.h>

@class Reachability;

@interface ConnectionManager : NSObject {
    Reachability *internetReachable;
    Reachability *hostReachable;
}

@property BOOL internetActive;
@property BOOL hostActive;

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

@end

Y el .m archivo:

#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
 11
Author: Danut Pralea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-11 08:33:51

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

EDITAR: O tonymillion/Reachability.

 6
Author: darvids0n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-12 23:41:40

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

#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;


}
 4
Author: Walty Yeung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-20 10:17:25

Creo que esto podría ayudar..

[[AFNetworkReachabilityManager sharedManager] startMonitoring];

if([AFNetworkReachabilityManager sharedManager].isReachable)
{
    NSLog(@"Network reachable");
}
else
{   
   NSLog(@"Network not reachable");
}
 3
Author: pooja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-20 07:11:44

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

Puede descargar los archivos necesarios desde SampleCode

Agregue Reachability.h y Reachability.m archivo a su proyecto,

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

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

#import "Reachability.h"

Ahora para comprobar 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
    }

}
 2
Author: Satyen Udeshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:27

También puede probar este si ya ha configurado 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;
}
}
 2
Author: Ravi Raja Jangid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-30 08:59:26

Aquí hay una buena solución para comprobar la conectividad usando Swift, sin usar la 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
    }
}

A continuación, puede comprobar la conectividad en cualquier parte de su proyecto mediante:

if Network.isConnectedToNetwork() == true {
    println("Internet connection OK")
} else {
    println("Internet connection FAILED")
}
 1
Author: blwinters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-24 18:31:37

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

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

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

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

 0
Author: SG1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-29 14:16:43

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 del 100% de paquetes when cuando un dispositivo está conectado al enrutador, pero el enrutador no está conectado a Internet. La accesibilidad y otros colgarán durante siglos. He creado una utilidad clase singleton para hacer frente a eso mediante la adición de un tiempo de espera asynch. Funciona bien en mi aplicación. Espero que ayude. Aquí está el enlace en github:

Https://github.com/fareast555/TFInternetChecker

 0
Author: Mike Critchley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-22 16:53:41

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. Me las arreglé para 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 de traducir a Swift.

Esto funciona tanto para conexiones 3G como WiFi.

No olvide agregar "Configuración del sistema.marco" para tu constructor de proyecto.

//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")
}
 0
Author: ViJay Avhad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-18 12:49:15

Reemplazo para la accesibilidad de Apple re-escrito en Swift con cierres, inspirado en tonymillion: https://github.com/ashleymills/Reachability.swift

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

  2. Recibe notificaciones sobre la 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()
    
 0
Author: Pierre F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-09 14:10:23

Alamofire

Si ya está utilizando Alamofire para toda la Api RESTful, esto es lo que puede benifit de eso.

Puede agregar la siguiente clase a su aplicación y llamar a MNNetworkUtils.main.isConnected() para obtener un booleano sobre si 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. Cada vez, cuando el usuario conecte o desconecte la red, se sobrescribirá self.reachable a verdadero/falso correctamente, porque comenzamos a escuchar la NetworkReachabilityManager en la inicialización de singleton.

También en para monitorear la accesibilidad, debe proporcionar un host, actualmente estoy usando google.com siéntase libre de cambiar a cualquier otro host o a uno de los suyos si es necesario.

 0
Author: nuynait,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-02 17:07:39