2017-05-02 1 views
1

Je travaille sur une application complexe et je veux tester les deux hôtes dans l'accessibilité d'Internet sur chaque ViewController qui reçoit des données du serveur que j'utilise actuellement cette bibliothèque pour joignabilitéCréation d'une extension/fonction facile à utiliser pour l'accessibilité (hôte/internet WIFI, cellulaire)

https://github.com/ashleymills/Reachability.swift

et je veux créer une méthode ou une extension facile de vérifier les joignabilité pour Internet et l'hôte de cette je l'ai déjà utiliser l'exemple de code de la bibliothèque qui est ci-dessous: `import UIKit

import Reachability 

class VC22: UIViewController { 

@IBOutlet weak var networkStatus: UILabel! 
@IBOutlet weak var hostNameLabel: UILabel! 

var reachability: Reachability? 

override func viewDidLoad() { 
    super.viewDidLoad() 

    // Start reachability without a hostname intially 
    setupReachability(nil, useClosures: true) 
    startNotifier() 

    // After 5 seconds, stop and re-start reachability, this time using a hostname 
    let dispatchTime = DispatchTime.now() + DispatchTimeInterval.seconds(5) 
    DispatchQueue.main.asyncAfter(deadline: dispatchTime) { 
     self.stopNotifier() 
     self.setupReachability("http://81.28.42.42:4242/", useClosures: true) 
     self.startNotifier() 

     let dispatchTime = DispatchTime.now() + DispatchTimeInterval.seconds(5) 
     DispatchQueue.main.asyncAfter(deadline: dispatchTime) { 
      self.stopNotifier() 
      self.setupReachability("invalidhost", useClosures: true) 
      self.startNotifier()   } 

    } 
} 

func setupReachability(_ hostName: String?, useClosures: Bool) { 
    hostNameLabel.text = hostName != nil ? hostName : "No host name" 

    print("--- set up with host name: \(hostNameLabel.text!)") 

    let reachability = hostName == nil ? Reachability() : Reachability(hostname: hostName!) 
    self.reachability = reachability 

    if useClosures { 
     reachability?.whenReachable = { reachability in 
      DispatchQueue.main.async { 
       self.updateLabelColourWhenReachable(reachability) 
      } 
     } 
     reachability?.whenUnreachable = { reachability in 
      DispatchQueue.main.async { 
       self.updateLabelColourWhenNotReachable(reachability) 
      } 
     } 
    } else { 
     NotificationCenter.default.addObserver(self, selector: #selector(VC22.reachabilityChanged(_:)), name: ReachabilityChangedNotification, object: reachability) 
    } 
} 

func startNotifier() { 
    print("--- start notifier") 
    do { 
     try reachability?.startNotifier() 
    } catch { 
     networkStatus.textColor = .red 
     networkStatus.text = "Unable to start\nnotifier" 
     return 
    } 
} 

func stopNotifier() { 
    print("--- stop notifier") 
    reachability?.stopNotifier() 
    NotificationCenter.default.removeObserver(self, name: ReachabilityChangedNotification, object: nil) 
    reachability = nil 
} 

func updateLabelColourWhenReachable(_ reachability: Reachability) { 
    print("\(reachability.description) - \(reachability.currentReachabilityString)") 
    if reachability.isReachableViaWiFi { 
     self.networkStatus.textColor = .green 
    } else { 
     self.networkStatus.textColor = .blue 
    } 

    self.networkStatus.text = reachability.currentReachabilityString 
} 

func updateLabelColourWhenNotReachable(_ reachability: Reachability) { 
    print("\(reachability.description) - \(reachability.currentReachabilityString)") 

    self.networkStatus.textColor = .red 

    self.networkStatus.text = reachability.currentReachabilityString 
} 


func reachabilityChanged(_ note: Notification) { 
    let reachability = note.object as! Reachability 

    if reachability.isReachable { 
     updateLabelColourWhenReachable(reachability) 
    } else { 
     updateLabelColourWhenNotReachable(reachability) 
    } 
} 

deinit { 
    stopNotifier() 
} 

} 

cela fonctionne bien, mais je dois juste un booléen pour me dire s'il est connecté ou non qui pourrait être réutilisable par l'application

MISE À JOUR actuellement J'utilise ci-dessous classe:

import Foundation 
import SystemConfiguration 

public 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(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 = SCNetworkReachabilityFlags(rawValue: 0) 
     if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false { 
      return false 
     } 

     let isReachable = flags == .reachable 
     let needsConnection = flags == .connectionRequired 

     return isReachable && !needsConnection 

    } 
} 

et l'utilisation dans viewControllers comme ci-dessous:

if Reachability.isConnectedToNetwork() == true { 
     print("Internet connection OK") 

     JSONParseFunction() 

} else { 
    print("Internet connection FAILED") 
    let alert = UIAlertView(title: "You are not connect to internet", message: "please check you connectivity", delegate: nil, cancelButtonTitle: "OK") 
    alert.show() 
} 

De cette façon, je vérifie juste pour Internet J'ai besoin de vérifier à la fois Host et Internet

Répondre

1

Y at-il une raison pour ne pas simplement laisser tomber dans votre AppDelegate et vous abonner à l'observateur là-bas au lieu de le faire sur un vc spécifique?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
     prepareReachabilityObserver() 
     return true 
    } 

    private func prepareReachabilityObserver() { 
     AppDelegate.reachability.whenUnreachable = { reachability in 
      DispatchQueue.main.async { 
       print("Not reachable") 
      } 
     } 

     do { 
      try AppDelegate.reachability.startNotifier() 
     } catch { 
      print("Unable to start notifier") 
     } 
    } 

Sur la partie host verification extension, je serais probablement aller avec quelque chose comme:

extension UIViewController { 
    internal func isReachable() -> Bool { 
      //this is the function you already have. 
    } 
} 

que vous pouvez ensuite utiliser dans tous les viewcontroller en faisant

self.isReachable() //'self' is a UIViewController in this case. 

Autre que cela, je J'ai de la difficulté à comprendre votre question, puisque vous semblez avoir déjà résolu cela.

EDIT: Je pense avoir compris votre question maintenant. Vous voulez vérifier à la fois si vous êtes joignable et si le nom d'hôte que vous passez est également accessible. Je ne pense pas que ce soit la meilleure idée pour gérer les deux en même temps, puisque l'un est un problème d'accessibilité ('Puis-je avoir une connexion sortante?') Et l'autre est un problème de connexion ('Puis-je avoir une réponse? à partir de cet endroit distant? 'ou' Est-ce que cette demande expire? ').

La façon dont je le gère actuellement est l'accessibilité dans quelque chose comme AppDelegate, puis la gestion du délai d'attente sur demande (que vous pouvez ensuite généraliser dans la portée réseau-stuff). Pour plus de précision: AppDelegate définit l'accessibilité. Ensuite, j'ai un RequestsManager qui gère les appels de service avec un timeout configuré.

Ensuite, vous pouvez faire quelque chose comme:

RequestManager.makeRequest("https://an.endpoint.of.yours", 
     onSuccess: {}, 
     onFailure: { //Here goes your timeout behaviour. 
}) 

Où dois-je passer le nom d'hôte? Je pense que c'est un comportement inutile, pour être honnête.Vous n'avez pas try to open doorpuis vous open door. Vous essayez juste de voir si vous avez réussi. Voici la même chose. Vous essayez de faire une demande, y a-t-il du succès? Impressionnant. N'est-ce pas? Manipuler en conséquence. Que retenez-vous (l'application) si l'échec était dû au fait que le point de terminaison était en panne ou parce que vous n'avez pas de plan de travail ou de réseau en panne? La demande expire dans les deux cas, et c'est ce qui vous intéresse. Encore une fois, tout cela suppose que je vous ai compris, ce dont je ne suis pas sûr à 100%.

+0

Vous devez importer Reachability dans votre fichier AppDelegate. 'import Reachability' comme vous l'avez déjà fait dans votre exemple. Aussi, j'ai fortement mis à jour la réponse parce que je n'étais pas sûr d'avoir bien compris la question. Veuillez confirmer. –

+0

Merci pour votre réponse détaillée – UncleJunior