Pregunta ¿Cómo 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 el Cocoa Touch bibliotecas o en macOS utilizando el Cacao bibliotecas.

Se me ocurrió una forma de hacer esto usando un NSURL. La forma en que lo hice parece un tanto poco confiable (porque incluso Google podría estar un día decepcionado y depender de un tercero parece malo), y si bien podría verificar si hay respuesta de otros sitios web si Google no respondía, parece derrochador y una carga innecesaria en mi aplicación.

- (BOOL) connectedToInternet
{
    NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
    return ( URLString != NULL ) ? YES : NO;
}

Es lo que he hecho mal, (sin mencionar stringWithContentsOfURL está en desuso en iOS 3.0 y macOS 10.4) y, de ser así, ¿cuál es la mejor manera de lograr esto?


1223
2017-07-05 08:45


origen


Respuestas:


Importante: Esta verificación debería siempre se realizará de forma asíncrona. La mayoría de las respuestas a continuación son sincrónicas, así que ten cuidado, de lo contrario, congelarás tu aplicación.


Rápido

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

2) Prueba de accesibilidad a través de 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) Agregar SystemConfiguration marco para el proyecto, pero no se preocupe por incluirlo en cualquier lugar

2) Agregue la versión de Tony Million de Reachability.h y Reachability.m al proyecto (se encuentra aquí: https://github.com/tonymillion/Reachability)

3) Actualiza la sección de interfaz

#import "Reachability.h"

// Add this to the interface in the .m file of your view controller
@interface MyViewController ()
{
    Reachability *internetReachableFoo;
}
@end

4) Luego implementa este método en el archivo .m de tu controlador de vista al que puedes 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: los Reachability la clase es una de las clases más utilizadas en los proyectos, por lo que podría encontrarse con conflictos de nombres con otros proyectos. Si esto sucede, tendrá que cambiar el nombre de uno de los pares de Reachability.h y Reachability.m archivos a otra cosa para resolver el problema.

Nota: El dominio que usas no importa. Solo está probando una puerta de acceso a cualquier dominio.


1220
2017-08-29 23:58



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 una conexión:

if (![self connected]) {
    // Not connected
} else {
    // Connected. Do some Internet stuff
}

Este método no espera cambios en los estados de la red para hacer cosas. Simplemente prueba el estado cuando se lo pides.


303
2017-08-26 13:34



Utilizando el código de Accesibilidad de Apple, creé una función que verificará esto correctamente sin tener que incluir ninguna clase.

Incluya SystemConfiguration.framework en su proyecto.

Realice algunas importaciones:

#import <sys/socket.h>
#import <netinet/in.h>
#import <SystemConfiguration/SystemConfiguration.h>

Ahora solo llame 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 es iOS 5 probado por ti


143
2017-10-28 20:37



Esta solía ser la respuesta correcta, pero ahora está desactualizada, ya que debería suscribirse a las notificaciones de accesibilidad. Este método comprueba sincrónicamente:


Puedes usar la clase de Accesibilidad de Apple. También le permitirá verificar si 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 envía con el SDK, sino que forma parte de esta aplicación de ejemplo de Apple. Simplemente descárguelo y copie Reachability.h / m a su proyecto. Además, debe agregar la estructura SystemConfiguration a su proyecto.


118
2017-07-05 10:58



Aquí hay una respuesta muy simple:

NSURL *scriptUrl = [NSURL URLWithString:@"http://www.google.com/m"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data)
    NSLog(@"Device is connected to the Internet");
else
    NSLog(@"Device is not connected to the Internet");

La URL debe apuntar a un sitio web extremadamente pequeño. Utilizo el sitio web móvil de Google aquí, pero si tuviera un servidor web confiable, lo subiría un archivo pequeño con solo un personaje en él para la velocidad máxima.

Si comprueba si el dispositivo es de algun modo conectado a Internet es todo lo que desea hacer, definitivamente recomendaría usar esta solución simple. Si necesita saber cómo está conectado el usuario, el uso de Accesibilidad es el camino a seguir.

Cuidado: Esto bloqueará brevemente su hilo mientras carga el sitio web. En mi caso, esto no fue un problema, pero debes considerar esto (créditos a Brad por señalar esto).


78
2018-05-14 22:25



Así es como lo hago en mis aplicaciones: mientras que un código de respuesta de 200 estados no garantiza nada, es lo suficientemente estable para mí. Esto no requiere tanta carga como las respuestas NSData publicadas aquí, ya que la mía simplemente verifica la respuesta HEAD.

código SWIFT

func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
{
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    let url = NSURL(string: "http://www.appleiphonecell.com/")
    let request = NSMutableURLRequest(URL: url!)

    request.HTTPMethod = "HEAD"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
    request.timeoutInterval = 10.0

    NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
    {(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in

        UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        let rsp = response as! NSHTTPURLResponse?

        completionHandler(internet:rsp?.statusCode == 200)
    })
}

func yourMethod()
{
    self.checkInternet(false, completionHandler:
    {(internet:Bool) -> Void in

        if (internet)
        {
            // "Internet" aka Apple's region universal URL reachable
        }
        else
        {
            // No "Internet" aka Apple's region universal URL un-reachable
        }
    })
}

Código Objective-C

typedef void(^connection)(BOOL);

- (void)checkInternet:(connection)block
{
    NSURL *url = [NSURL URLWithString:@"http://www.appleiphonecell.com/"];
    NSMutableURLRequest *headRequest = [NSMutableURLRequest requestWithURL:url];
    headRequest.HTTPMethod = @"HEAD";

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    defaultConfigObject.timeoutIntervalForResource = 10.0;
    defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;

    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];

    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:headRequest
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        if (!error && response)
        {
            block([(NSHTTPURLResponse *)response statusCode] == 200);
        }
    }];
    [dataTask resume];
}

- (void)yourMethod
{
    [self checkInternet:^(BOOL internet)
    {
         if (internet)
         {
             // "Internet" aka Apple's region universal URL reachable
         }
         else
         {
             // No "Internet" aka Apple's region universal URL un-reachable
         }
    }];
}

70
2017-11-30 03:26



Suministros de Apple Código de muestra para verificar los diferentes tipos de disponibilidad de red. Alternativamente hay un ejemplo en el libro de cocina de los desarrolladores de iPhone.

Nota: Consulte el comentario de @KHG sobre esta respuesta con respecto al uso del código de accesibilidad de Apple.


54
2017-07-05 08:59



Podrías usar Reachability por  (disponible aquí)

#import "Reachability.h"

- (BOOL)networkConnection {
    return [[Reachability reachabilityWithHostName:@"www.google.com"] currentReachabilityStatus];
}

if ([self networkConnection] == NotReachable) { /* No Network */ } else { /* Network */ } //Use ReachableViaWiFi / ReachableViaWWAN to get the type of connection.

43
2018-04-25 12:20



Apple proporciona una aplicación de muestra que hace exactamente esto:

Accesibilidad


39
2017-07-05 08:58