web-dev-qa-db-fra.com

Meilleure approche pour vérifier la connexion Internet dans iOS

Je cherchais sur Internet le meilleur moyen de vérifier la connexion Internet dans iOS qui fonctionne à la fois en environnement réseau IPv4 et IPv6. J'ai trouvé qu'il y avait beaucoup de réponses possibles mais très confuses sur laquelle appliquer. Ce que je dois faire est le suivant:

   // Check for internet connection

if (internetConnectionIsAvailable) {
   // make rest calls
}else
   // show cached data
}

J'ai trouvé les options suivantes qui sont suggérées dans Internet.

OPTION 1:Utiliser la classe Apple Reachability

Avec Accessibilité, je peux vérifier la connectivité Internet comme suit, qui est courte et directe, et je n’attends aucune réponse.

 - (BOOL)connected
    {
        Reachability *reachability = [Reachability reachabilityForInternetConnection];
        NetworkStatus networkStatus = [reachability currentReachabilityStatus];
        return !(networkStatus == NotReachable);
    }

- (void)viewDidLoad {
    [super viewDidLoad];

    if (![self connected]){
     // Not connected
    }else{
    // Connected
    }

}

Mais ici, la vérification de l’internet est effectuée avant le vol, ce qui va à l’encontre de la suggestion de l’ingénieur Apple, comme indiqué sur vidéo WWDC . De plus, si vous cochez ReadMe.md, il a été mentionné que Reachability prend entièrement en charge IPv6. Mais si la méthode reachabilityForInternetConnection est cochée dans Reachability.m, ils ont utilisé sockaddr_in, sockaddr_in6 n'a pas été utilisé, ce qui est recommandé pour le réseau IPv6. Donc, je ne sais pas si cela fonctionnera dans le réseau IPv6.

OPTION 2: Utilisez Alamofire pour vous connecter 

  • Essayez simplement de vous connecter comme dans l'un des stackoverflow answer . Le code également indiqué ci-dessous: -

    Alamofire.request(.GET,"http://superrandomdomainnamethatisnotused.com/superrandompath").responseString {
        (request, response, stringData, error) in
    
        if let networkError = error {
            if (networkError.code == -1009) {
                println("No Internet \(error)")
            }
        }
    }
    

Mais cela ne prend pas beaucoup de temps d'essayer de vous connecter à un hôte, d'attendre la réponse et de savoir s'il est en ligne/hors ligne. 

OPTION 3: Utilisez la version de Tony Million de Accessibilité . Mais l'auteur a prévenu que l'application serait rejetée lors de son utilisation. Je peux l'utiliser comme code indiqué ci-dessous: -

// 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(@"There in internet connection");
        });
    };

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

Mais dans cette option, ma question est de savoir si cette approche est appropriée pour tester Internet en connectant http://google.com . Est-ce que cela garantit des résultats à 100%? Et si Google est en panne? Si l'application est utilisée dans un pays où google.com n'est pas autorisé, quel est le résultat? 

J'ai donc été confronté à un grand dilemme: quelle option choisir, si ces options sont la bonne ou s'il existe un meilleur moyen de vérifier Internet qui garantit des résultats à 100% et fonctionne à la fois en réseau IPv4 et IPv6. Quelqu'un peut-il me suggérer quelle option est la meilleure ou devrais-je opter pour une autre approche, quel est le meilleur moyen d'y parvenir? 

Votre réponse sera très appréciée.

8
skJosh

Pour Swift 3, Xcode 8 ......

func isInternetAvailable() -> Bool {

    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
    zeroAddress.sin_family = sa_family_t(AF_INET)

    guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
            SCNetworkReachabilityCreateWithAddress(nil, $0)
        }
    }) else {
        return false
    }

    var flags: SCNetworkReachabilityFlags = []
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
        return false
    }

    let isReachable = flags.contains(.reachable)
    let needsConnection = flags.contains(.connectionRequired)

    return (isReachable && !needsConnection)
}
13
emraz

Je pense que vous trouverez ce lien utile: La vérification de la connexion réseau se bloque sur les réseaux IPv6 dans Swift

import SystemConfiguration

class Reachability {

    class func isConnectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
            SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0))
        }

        var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }

        let isReachable = flags == .Reachable
        let needsConnection = flags == .ConnectionRequired

        return isReachable && !needsConnection

    }
}

//cas d'utilisation

if Reachability.isConnectedToNetwork() {
    //do something
}

Voici quelques autres liens pour la recherche:

https://developer.Apple.com/reference/systemconfiguration/1514904-scnetworkreachabilitycreatewithn

https://developer.Apple.com/library/prerelease/content/documentation/Networking/Conceptual/SystemConfigFrameworks/SC_Intro/SC_Intro.html#//Apple_ref/doc/uid/TP40001065

6
Asdrubal

Alamofire

Si vous utilisez déjà Alamofire pour tous les Api RESTful, voici ce que vous pouvez en tirer.

Vous pouvez ajouter la classe suivante à votre application et appeler MNNetworkUtils.main.isConnected() pour obtenir un booléen indiquant si elle est connectée ou non.

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

Ceci est une classe singleton. Chaque fois que l'utilisateur connecte ou déconnecte le réseau, il remplace self.reachable par true/false correctement, car nous commençons à écouter NetworkReachabilityManager lors de l'initialisation du singleton.

Aussi, afin de contrôler l'accessibilité, vous devez fournir un hôte. Actuellement, j'utilise google.com. N'hésitez pas à changer pour tout autre hôte ou l'un des vôtres si nécessaire.

Pour une meilleure approche, je pense que si vous utilisez déjà Alamofire cela peut être la meilleure approche. Je ne pense pas que surveiller google.com soit une mauvaise conception. N'hésitez pas à me corriger si je me trompe.

1
nuynait
  1. Téléchargez le dossier .Zip à partir de Github

  2. Décompressez le dossier attaché et faites glisser les fichiers dans votre projet. 

  3. Créez un fichier bridge.h et importez-le avec #import "Reachability.h".

  4. Avant d'appeler l'API, vous pouvez vérifier la connexion Internet avec le code suivant: 

    if kNetworkController.checkNetworkStatus() { 
        // call your api 
    }
    

C'est tout.

0
Arshad Shaik