1405 votes

Comment puis-je vérifier si une connexion Internet est active sur iOS ou macOS ?

J'aimerais vérifier si je dispose d'une connexion Internet sur iOS à l'aide de la fonction Cocoa Touch ou sur macOS en utilisant les bibliothèques Cacao bibliothèques.

J'ai trouvé un moyen d'y parvenir en utilisant une NSURL . La façon dont je l'ai fait semble un peu peu peu fiable (car même Google pourrait un jour être en panne et dépendre d'un tiers semble mauvais), et bien que je puisse vérifier la réponse de certains autres sites Web si Google ne répond pas, cela semble un gaspillage et une surcharge inutile pour mon application.

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

Est-ce que ce que j'ai fait est mal, (sans mentionner stringWithContentsOfURL est déprécié dans iOS 3.0 et macOS 10.4) et, si c'est le cas, quelle est la meilleure façon d'y parvenir ?

0 votes

Vous pourriez remplacer la dernière ligne par : return (id)URLString ; (Omettre le cast fonctionnera également, mais pourrait vous donner un avertissement du compilateur).

12 votes

Plutôt return (BOOL)URLString; ou mieux encore, return !!URLString o return URLString != nil

3 votes

Je ne sais pas quel est votre cas d'utilisation, mais si vous le pouvez, il est préférable d'essayer la requête et de traiter toute erreur telle que l'absence de connexion qui survient. Si vous ne pouvez pas le faire, alors il y a beaucoup de bons conseils ici dans ce cas.

1320voto

iWasRobbed Points 26926

Important : Ce contrôle doit toujours être effectuée de manière asynchrone. La majorité des réponses ci-dessous sont synchrones, alors faites attention sinon vous allez geler votre application.


Swift

  1. Installer via CocoaPods ou Carthage : https://github.com/ashleymills/Reachability.swift

  2. Test d'accessibilité via des fermetures

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

Objectif-C

  1. Ajouter SystemConfiguration au projet, mais ne vous souciez pas de l'inclure partout.

  2. Ajoutez la version de Tony Million Reachability.h y Reachability.m au projet (trouvé ici : https://github.com/tonymillion/Reachability )

  3. Mise à jour de la section interface

    #import "Reachability.h"
    
    // Add this to the interface in the .m file of your view controller
    @interface MyViewController ()
    {
        Reachability *internetReachableFoo;
    }
    @end
  4. Ensuite, implémentez cette méthode dans le fichier .m de votre contrôleur de vue que vous pouvez appeler

    // 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];
    }

Note importante : Le site Reachability est l'une des classes les plus utilisées dans les projets. Vous risquez donc de rencontrer des conflits de noms avec d'autres projets. Si c'est le cas, vous devrez renommer l'une des paires de classes Reachability.h y Reachability.m à quelque chose d'autre pour résoudre le problème.

Note : Le domaine que vous utilisez n'a pas d'importance. Il s'agit juste de tester une passerelle vers n'importe quel domaine.

0 votes

Quand ils disent que l'hôte est joignable, ils parlent en fait de savoir si oui ou non une passerelle l'hôte est joignable ou non. Il ne s'agit pas de dire que "google.com" ou "apple.com" est disponible, mais plutôt qu'un moyen d'y accéder est disponible.

0 votes

Ma méthode checkNetworkStatus n'est pas appelée Je retiens dans la méthode init. Quelqu'un d'autre a ce problème ?

0 votes

Ah - il faut l'appeler manuellement, puisque la connexion internet n'est pas "changée" au démarrage. Dans mon ConnectionService init : _internetReachable = [[Reachability reachabilityForInternetConnection] retain] ; [self checkNetworkStatus] ; fonctionne. Merci ! +1

316voto

cannyboy Points 8747

J'aime garder les choses simples. La façon dont je le fais est la suivante :

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

Ensuite, je l'utilise chaque fois que je veux voir si j'ai une connexion :

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

Cette méthode n'attend pas le changement d'état du réseau pour agir. Elle teste simplement l'état lorsque vous le lui demandez.

0 votes

Bonjour @msec, vous pouvez essayer la solution d'Andrew Zimmer sur cette page, elle fonctionne bien avec l'adsl déconnecté (et le wifi connecté).

2 votes

Pour ceux qui ne font que copier et coller comme je l'ai fait avec le code ci-dessus. Ajoutez également SystemConfiguration.framework manuellement ou vous obtiendrez une erreur de liaison.

0 votes

Je suis toujours joignable si je me connecte en WiFi. WiFi ne signifie pas qu'il y a une connexion Internet. Je veux vérifier la connexion Internet même s'il y a une connexion WiFi. Pouvez-vous m'aider ?

147voto

Andrew Zimmer Points 2282

En utilisant le code Reachability d'Apple, j'ai créé une fonction qui vérifiera cela correctement sans que vous ayez à inclure de classes.

Incluez le SystemConfiguration.framework dans votre projet.

Faites des importations :

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

Maintenant, il suffit d'appeler cette fonction :

/*
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;
}

Et c'est iOS 5 testé pour vous.

0 votes

@JezenThomas Cela n'effectue pas la vérification d'Internet de manière asynchrone, c'est pourquoi c'est "beaucoup plus mince"... Vous devriez toujours effectuer cette vérification de manière asynchrone en vous abonnant aux notifications afin de ne pas bloquer l'application pendant ce processus.

0 votes

Merci, cela fonctionne même si vous utilisez le wifi adsl et que l'adsl n'est pas connecté, c'est exactement ce dont j'ai besoin.

6 votes

Cela entraîne une fuite de mémoire - la structure de "lisibilité" (objet, chose) doit être libérée avec CFRelease().

124voto

Daniel Rinser Points 5755

C'était autrefois la bonne réponse, mais elle est désormais dépassée, car vous devez plutôt vous abonner aux notifications d'accessibilité. Cette méthode vérifie de manière synchrone :


Vous pouvez utiliser la classe Reachability d'Apple. Elle vous permettra également de vérifier si le Wi-Fi est activé :

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 classe Reachability n'est pas livrée avec le SDK, mais fait plutôt partie de la classe cet exemple d'application Apple . Il suffit de le télécharger, et de copier Reachability.h/m dans votre projet. Vous devez également ajouter le framework SystemConfiguration à votre projet.

7 votes

Voir mon commentaire ci-dessus sur le fait de ne pas utiliser Reachability de cette façon. Utilisez-le en mode asynchrone et abonnez-vous aux notifications qu'il envoie - ne le faites pas.

0 votes

Ce code est un bon point de départ pour les choses que vous devez définir avant de pouvoir utiliser les méthodes de délégué pour la classe d'accessibilité.

83voto

Erik Points 735

Voici une réponse très 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");

L'URL doit pointer vers un site web extrêmement petit. J'utilise ici le site web mobile de Google, mais si j'avais un serveur web fiable, je téléchargerais un petit fichier contenant un seul caractère pour une vitesse maximale.

Si vous vérifiez si l'appareil est en quelque sorte connecté à l'Internet est tout ce que vous voulez faire, je vous recommande vivement d'utiliser cette solution simple. Si vous avez besoin de savoir comment l'utilisateur est connecté, il faut utiliser Reachability.

Attention : Cela bloquera brièvement votre fil pendant qu'il charge le site web. Dans mon cas, ce n'était pas un problème, mais vous devriez y réfléchir (merci à Brad pour l'avoir signalé).

10 votes

J'aime beaucoup cette idée, mais je dirais que pour une fiabilité de 99,999 % tout en maintenant une petite taille de réponse, utilisez www.google.com/m qui est la vue mobile de Google.

1 votes

Excellente solution @Erik. Ce que je vous recommande également, c'est d'utiliser www.google.com, au lieu de www.google.com/m, comme l'a dit rwyland. C'est bizarre, mais d'après mes tests, la version mobile prend toujours environ 120 ms de plus que la version www.google.com.

5 votes

Les documents d'Apple recommandent de ne pas le faire car cela peut bloquer le fil de discussion sur un réseau lent, ce qui peut entraîner la fermeture de l'application dans iOS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X