¿Cómo puedo comprobar si hay una conexión a Internet activa en iOS o macOS?

Resuelto Brock Woolf asked hace 54 años • 39 respuestas

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 stringWithContentsOfURLque está obsoleto en iOS 3.0 y macOS 10.4) y, de ser así, cuál es una mejor manera de lograrlo?

Brock Woolf avatar Jan 01 '70 08:01 Brock Woolf
Aceptado

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

  1. Instalar a través de CocoaPods o Carthage: https://github.com/ashleymills/Reachability.swift

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

  1. Agregue SystemConfigurationframework al proyecto pero no se preocupe por incluirlo en ningún lado

  2. Agregue la versión de Tony Million de Reachability.hy Reachability.mal proyecto (que se encuentra aquí: https://github.com/tonymillion/Reachability )

  3. 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
    
  4. 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 Reachabilityclase 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.hy Reachability.ma otro para resolver el problema.

Nota: El dominio que utilices no importa. Es solo una prueba de una puerta de entrada a cualquier dominio.

iwasrobbed avatar Aug 29 '2010 23:08 iwasrobbed

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.

cannyboy avatar Aug 26 '2011 13:08 cannyboy

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.

Andrew Zimmer avatar Oct 28 '2011 20:10 Andrew Zimmer

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.

Daniel Rinser avatar Jul 05 '2009 10:07 Daniel Rinser