Swift iOS- What to do when there is a wifi connection but no internet connection?












2















I'm using Alamofire in my iOS app. I use bool values in viewWillAppear and in AppDelegate with NSNotifications to check if there is an internet connection. If there is no wifi connection a pop up appears to inform the user. If there is a wifi connection the pop up disappears and everything works fine again. I've had no problems as long as wifi is clearly not working.



I was at a meetup and someone explained to me that the way it works is it it looks for a wifi connection and not an internet connection. For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet.



I was just in a situation where I connected to an open network, my app initially responded as if I were actually connected to the internet (no pop up) but I couldn't get connect to anything. The wifi signal was on full. In terminal I ran a ping and it turns out the connection was dead. My app couldn't tell the difference.



enter image description hereenter image description here



How do I make a pop up appear in a sitaution like this?



Also what is .case unknown for?



Alamofire.Swift:



import Foundation
import Alamofire

open class NetworkManager {

open static var sharedManager: NetworkReachabilityManager = {

let reachabilityManager = NetworkReachabilityManager()

reachabilityManager?.listener = { (status) in

switch status {

case .notReachable:
print("The network is not reachable")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "unsuccessful"), object: nil)

case .unknown : //???????
print("It is unknown wether the network is reachable")
//I'm not sure whether to put a Notification for successful or unsuccessful???

case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)

case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)
}
}

reachabilityManager?.startListening()
return reachabilityManager!
}()
}


AppDelegate:



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

NetworkManager.sharedManager.startListening()


SomeVC:



override func viewWillAppear() {
super.viewWillAppear()

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(successful), name: "successful", object: nil)

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(unsuccessful), name: "unsuccessful", object: nil)

if NetworkManager.sharedManager.isReachable == true{
self.successful()
}else{
self.unsuccessful()
}

if NetworkManager.sharedManager.isReachableOnWWAN == true{
self.successful()
}else{
self.unsuccessful()
}

if NetworkManager.sharedManager.isReachableOnEthernetOrWiFi == true{
self.successful()
}else{
self.unsuccessful()
}
}

func successful(){
//dismiss pop up
}

func unsuccessful(){
//show pop up
}

deinit{
NSNotificationCenter.defaultCenter().removeObserver(self, name: "successful", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "unsuccessful", object: nil)
}
}









share|improve this question





























    2















    I'm using Alamofire in my iOS app. I use bool values in viewWillAppear and in AppDelegate with NSNotifications to check if there is an internet connection. If there is no wifi connection a pop up appears to inform the user. If there is a wifi connection the pop up disappears and everything works fine again. I've had no problems as long as wifi is clearly not working.



    I was at a meetup and someone explained to me that the way it works is it it looks for a wifi connection and not an internet connection. For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet.



    I was just in a situation where I connected to an open network, my app initially responded as if I were actually connected to the internet (no pop up) but I couldn't get connect to anything. The wifi signal was on full. In terminal I ran a ping and it turns out the connection was dead. My app couldn't tell the difference.



    enter image description hereenter image description here



    How do I make a pop up appear in a sitaution like this?



    Also what is .case unknown for?



    Alamofire.Swift:



    import Foundation
    import Alamofire

    open class NetworkManager {

    open static var sharedManager: NetworkReachabilityManager = {

    let reachabilityManager = NetworkReachabilityManager()

    reachabilityManager?.listener = { (status) in

    switch status {

    case .notReachable:
    print("The network is not reachable")
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "unsuccessful"), object: nil)

    case .unknown : //???????
    print("It is unknown wether the network is reachable")
    //I'm not sure whether to put a Notification for successful or unsuccessful???

    case .reachable(.ethernetOrWiFi):
    print("The network is reachable over the WiFi connection")
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)

    case .reachable(.wwan):
    print("The network is reachable over the WWAN connection")
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)
    }
    }

    reachabilityManager?.startListening()
    return reachabilityManager!
    }()
    }


    AppDelegate:



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

    NetworkManager.sharedManager.startListening()


    SomeVC:



    override func viewWillAppear() {
    super.viewWillAppear()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(successful), name: "successful", object: nil)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(unsuccessful), name: "unsuccessful", object: nil)

    if NetworkManager.sharedManager.isReachable == true{
    self.successful()
    }else{
    self.unsuccessful()
    }

    if NetworkManager.sharedManager.isReachableOnWWAN == true{
    self.successful()
    }else{
    self.unsuccessful()
    }

    if NetworkManager.sharedManager.isReachableOnEthernetOrWiFi == true{
    self.successful()
    }else{
    self.unsuccessful()
    }
    }

    func successful(){
    //dismiss pop up
    }

    func unsuccessful(){
    //show pop up
    }

    deinit{
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "successful", object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "unsuccessful", object: nil)
    }
    }









    share|improve this question



























      2












      2








      2


      1






      I'm using Alamofire in my iOS app. I use bool values in viewWillAppear and in AppDelegate with NSNotifications to check if there is an internet connection. If there is no wifi connection a pop up appears to inform the user. If there is a wifi connection the pop up disappears and everything works fine again. I've had no problems as long as wifi is clearly not working.



      I was at a meetup and someone explained to me that the way it works is it it looks for a wifi connection and not an internet connection. For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet.



      I was just in a situation where I connected to an open network, my app initially responded as if I were actually connected to the internet (no pop up) but I couldn't get connect to anything. The wifi signal was on full. In terminal I ran a ping and it turns out the connection was dead. My app couldn't tell the difference.



      enter image description hereenter image description here



      How do I make a pop up appear in a sitaution like this?



      Also what is .case unknown for?



      Alamofire.Swift:



      import Foundation
      import Alamofire

      open class NetworkManager {

      open static var sharedManager: NetworkReachabilityManager = {

      let reachabilityManager = NetworkReachabilityManager()

      reachabilityManager?.listener = { (status) in

      switch status {

      case .notReachable:
      print("The network is not reachable")
      NotificationCenter.default.post(name: NSNotification.Name(rawValue: "unsuccessful"), object: nil)

      case .unknown : //???????
      print("It is unknown wether the network is reachable")
      //I'm not sure whether to put a Notification for successful or unsuccessful???

      case .reachable(.ethernetOrWiFi):
      print("The network is reachable over the WiFi connection")
      NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)

      case .reachable(.wwan):
      print("The network is reachable over the WWAN connection")
      NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)
      }
      }

      reachabilityManager?.startListening()
      return reachabilityManager!
      }()
      }


      AppDelegate:



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

      NetworkManager.sharedManager.startListening()


      SomeVC:



      override func viewWillAppear() {
      super.viewWillAppear()

      NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(successful), name: "successful", object: nil)

      NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(unsuccessful), name: "unsuccessful", object: nil)

      if NetworkManager.sharedManager.isReachable == true{
      self.successful()
      }else{
      self.unsuccessful()
      }

      if NetworkManager.sharedManager.isReachableOnWWAN == true{
      self.successful()
      }else{
      self.unsuccessful()
      }

      if NetworkManager.sharedManager.isReachableOnEthernetOrWiFi == true{
      self.successful()
      }else{
      self.unsuccessful()
      }
      }

      func successful(){
      //dismiss pop up
      }

      func unsuccessful(){
      //show pop up
      }

      deinit{
      NSNotificationCenter.defaultCenter().removeObserver(self, name: "successful", object: nil)
      NSNotificationCenter.defaultCenter().removeObserver(self, name: "unsuccessful", object: nil)
      }
      }









      share|improve this question
















      I'm using Alamofire in my iOS app. I use bool values in viewWillAppear and in AppDelegate with NSNotifications to check if there is an internet connection. If there is no wifi connection a pop up appears to inform the user. If there is a wifi connection the pop up disappears and everything works fine again. I've had no problems as long as wifi is clearly not working.



      I was at a meetup and someone explained to me that the way it works is it it looks for a wifi connection and not an internet connection. For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet.



      I was just in a situation where I connected to an open network, my app initially responded as if I were actually connected to the internet (no pop up) but I couldn't get connect to anything. The wifi signal was on full. In terminal I ran a ping and it turns out the connection was dead. My app couldn't tell the difference.



      enter image description hereenter image description here



      How do I make a pop up appear in a sitaution like this?



      Also what is .case unknown for?



      Alamofire.Swift:



      import Foundation
      import Alamofire

      open class NetworkManager {

      open static var sharedManager: NetworkReachabilityManager = {

      let reachabilityManager = NetworkReachabilityManager()

      reachabilityManager?.listener = { (status) in

      switch status {

      case .notReachable:
      print("The network is not reachable")
      NotificationCenter.default.post(name: NSNotification.Name(rawValue: "unsuccessful"), object: nil)

      case .unknown : //???????
      print("It is unknown wether the network is reachable")
      //I'm not sure whether to put a Notification for successful or unsuccessful???

      case .reachable(.ethernetOrWiFi):
      print("The network is reachable over the WiFi connection")
      NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)

      case .reachable(.wwan):
      print("The network is reachable over the WWAN connection")
      NotificationCenter.default.post(name: NSNotification.Name(rawValue: "successful"), object: nil)
      }
      }

      reachabilityManager?.startListening()
      return reachabilityManager!
      }()
      }


      AppDelegate:



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

      NetworkManager.sharedManager.startListening()


      SomeVC:



      override func viewWillAppear() {
      super.viewWillAppear()

      NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(successful), name: "successful", object: nil)

      NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(unsuccessful), name: "unsuccessful", object: nil)

      if NetworkManager.sharedManager.isReachable == true{
      self.successful()
      }else{
      self.unsuccessful()
      }

      if NetworkManager.sharedManager.isReachableOnWWAN == true{
      self.successful()
      }else{
      self.unsuccessful()
      }

      if NetworkManager.sharedManager.isReachableOnEthernetOrWiFi == true{
      self.successful()
      }else{
      self.unsuccessful()
      }
      }

      func successful(){
      //dismiss pop up
      }

      func unsuccessful(){
      //show pop up
      }

      deinit{
      NSNotificationCenter.defaultCenter().removeObserver(self, name: "successful", object: nil)
      NSNotificationCenter.defaultCenter().removeObserver(self, name: "unsuccessful", object: nil)
      }
      }






      ios networking alamofire reachability nsnotifications






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 9 '18 at 12:08







      Lance Samaria

















      asked Mar 28 '17 at 10:58









      Lance SamariaLance Samaria

      2,52921451




      2,52921451
























          4 Answers
          4






          active

          oldest

          votes


















          1














          You can init NetworkReachabilityManagerwith host, for example, google host, because default is 0.0.0.0



          let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")


          When you start listening reachability manager doing ping to host. If network is available you can cache SSID and ping again when SSID changed.



          For case .unknown better put a Notification for unsuccessful.



          Example get SSID (it doesn't work in Simulator):



          func fetchSSIDInfo() ->  String? {  
          if let interfaces = CNCopySupportedInterfaces() {
          for i in 0..<CFArrayGetCount(interfaces){
          let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces, i)
          let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
          let unsafeInterfaceData = CNCopyCurrentNetworkInfo("(rec)" as CFString)

          if let unsafeInterfaceData = unsafeInterfaceData as? Dictionary<AnyHashable, Any> {
          return unsafeInterfaceData["SSID"] as? String
          }
          }
          }
          return nil
          }





          share|improve this answer


























          • thanks I'll try it. How do I cache SSID?

            – Lance Samaria
            Mar 28 '17 at 12:09











          • added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

            – Dialogue
            Mar 28 '17 at 12:21











          • thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

            – Lance Samaria
            Mar 28 '17 at 12:34













          • add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

            – Dialogue
            Mar 28 '17 at 16:29













          • you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

            – Dialogue
            Mar 29 '17 at 6:15



















          0














          Here's an answer composed of these 2 solutions:Pavle Mijatovic and Yasin Ugurlu



          Make a new class and name it Connection and copy and paste the code below inside of it:



          import Foundation
          import SystemConfiguration

          class Connection {

          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)

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

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

          let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
          let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

          return isReachable && !needsConnection

          }

          class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) {

          // 1. Check the WiFi Connection
          guard isConnectedToNetwork() else {
          completionHandler(false)
          return
          }

          // 2. Check the Internet Connection but possibly use www.apple.com or www.alibaba.com instead of google.com because it's not available in China
          var webAddress = "https://www.google.com" // Default Web Site
          if let _ = webSiteToPing {
          webAddress = webSiteToPing!
          }

          guard let url = URL(string: webAddress) else {
          completionHandler(false)
          print("could not create url from: (webAddress)")
          return
          }

          let urlRequest = URLRequest(url: url)
          let session = URLSession.shared
          let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
          if error != nil || response == nil {
          completionHandler(false)
          } else {
          completionHandler(true)
          }
          })
          task.resume()
          }
          }


          In whatever view controller your using it in inside viewDidLoad call it like this:



          override func viewDidLoad() {
          super.viewDidLoad()

          // if in china usewww.apple.com or www.alibaba.com instead
          Connection.isInternetAvailable(webSiteToPing: "https://www.google.com", completionHandler: {
          (bool) in

          if bool{
          print("Internet connection is good")
          }else{
          print("No internet connection can be found")
          }
          })
          }


          A couple of things I've found out is this only seems to work once because if a connection is available "Internet connection is good" prints but if I go to airplane mode "No internet connection can be found" doesn't print. It's not actively listening which makes me think I have to hook up to a Notification? The other thing is if your in China then this will not work because google isn't available in China. Maybe a better website to check would be www.apple.com or www.alibaba.com as it seems they're available everywhere.



          Connection.isInternetAvailable(webSiteToPing: "https://www.apple.com"...


          or



          Connection.isInternetAvailable(webSiteToPing: "https://www.alibaba.com"...





          share|improve this answer

































            0














            I followed this AshleyMills Reachability file and it uses google.com to test for a connection. You can just copy and paste the below inside a new file to test to see how it works. If your using this in China then use alibaba.com because google isn't available in China.



            // everywhere outside China
            let hostNames = [nil, "google.com", "invalidhost"]

            // everywhere including China
            let hostNames = [nil, "alibaba.com", "invalidhost"]


            When you first launch the app you will see the labels change every 5 seconds because there is an async timer inside: func startHost(at index: Int)



            If you want to stop it and take control of everything yourself then comment out this code:



            // comment this out to stop the connection from changing
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            //self.startHost(at: (index + 1) % 3)
            }


            Once you comment that out then you should toggle your phones connection between Wifi, Cellular Connection, and Airplane Mode. The label colors will change from green to blue to red depending on the connection.



            Create a new project and add this to the ViewController file:



            import UIKit

            class ViewController: UIViewController {

            let networkStatus: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.font = UIFont.systemFont(ofSize: 21)
            label.textColor = .black
            label.numberOfLines = 0
            label.sizeToFit()
            label.text = "Status"
            label.textAlignment = .center
            return label
            }()

            let hostNameLabel: UILabel = {
            let label = UILabel()
            label.translatesAutoresizingMaskIntoConstraints = false
            label.font = UIFont.systemFont(ofSize: 21)
            label.textColor = .black
            label.numberOfLines = 0
            label.sizeToFit()
            label.text = "Host"
            label.textAlignment = .center
            return label
            }()

            var reachability: Reachability?
            let hostNames = [nil, "google.com", "invalidhost"]
            var hostIndex = 0

            override func viewDidLoad() {
            super.viewDidLoad()

            setConstraints()
            startHost(at: 1)
            }

            func startHost(at index: Int) {
            stopNotifier()
            setupReachability(hostNames[index], useClosures: true)
            startNotifier()

            // this loops the connection every 5 seconds
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            self.startHost(at: (index + 1) % 3)
            }
            }

            func setupReachability(_ hostName: String?, useClosures: Bool) {
            let reachability: Reachability?
            if let hostName = hostName {
            reachability = Reachability(hostname: hostName)
            hostNameLabel.text = hostName
            } else {
            reachability = Reachability()
            hostNameLabel.text = "No host name"
            }
            self.reachability = reachability
            print("--- set up with host name: (hostNameLabel.text!)")

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

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

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

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

            self.networkStatus.text = "(reachability.connection)"
            }

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

            self.networkStatus.textColor = .red

            self.networkStatus.text = "(reachability.connection)"
            }

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

            if reachability.connection != .none {
            updateLabelColourWhenReachable(reachability)
            } else {
            updateLabelColourWhenNotReachable(reachability)
            }
            }

            func setConstraints(){
            view.addSubview(networkStatus)
            view.addSubview(hostNameLabel)

            networkStatus.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
            networkStatus.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
            networkStatus.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

            hostNameLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
            hostNameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
            hostNameLabel.topAnchor.constraint(equalTo: networkStatus.bottomAnchor, constant: 20).isActive = true
            }

            deinit {
            stopNotifier()
            }
            }


            Create a File named Reachability and add this to it:



            import SystemConfiguration
            import Foundation

            public enum ReachabilityError: Error {
            case FailedToCreateWithAddress(sockaddr_in)
            case FailedToCreateWithHostname(String)
            case UnableToSetCallback
            case UnableToSetDispatchQueue
            }

            @available(*, unavailable, renamed: "Notification.Name.reachabilityChanged")
            public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification")

            extension Notification.Name {
            public static let reachabilityChanged = Notification.Name("reachabilityChanged")
            }

            func callback(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
            guard let info = info else { return }

            let reachability = Unmanaged<Reachability>.fromOpaque(info).takeUnretainedValue()
            reachability.reachabilityChanged()
            }

            public class Reachability {

            public typealias NetworkReachable = (Reachability) -> ()
            public typealias NetworkUnreachable = (Reachability) -> ()

            @available(*, unavailable, renamed: "Connection")
            public enum NetworkStatus: CustomStringConvertible {
            case notReachable, reachableViaWiFi, reachableViaWWAN
            public var description: String {
            switch self {
            case .reachableViaWWAN: return "Cellular"
            case .reachableViaWiFi: return "WiFi"
            case .notReachable: return "No Connection"
            }
            }
            }

            public enum Connection: CustomStringConvertible {
            case none, wifi, cellular
            public var description: String {
            switch self {
            case .cellular: return "Cellular"
            case .wifi: return "WiFi"
            case .none: return "No Connection"
            }
            }
            }

            public var whenReachable: NetworkReachable?
            public var whenUnreachable: NetworkUnreachable?

            @available(*, deprecated: 4.0, renamed: "allowsCellularConnection")
            public let reachableOnWWAN: Bool = true

            /// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`)
            public var allowsCellularConnection: Bool

            // The notification center on which "reachability changed" events are being posted
            public var notificationCenter: NotificationCenter = NotificationCenter.default

            @available(*, deprecated: 4.0, renamed: "connection.description")
            public var currentReachabilityString: String {
            return "(connection)"
            }

            @available(*, unavailable, renamed: "connection")
            public var currentReachabilityStatus: Connection {
            return connection
            }

            public var connection: Connection {
            guard isReachableFlagSet else { return .none }

            // If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
            guard isRunningOnDevice else { return .wifi }

            var connection = Connection.none

            if !isConnectionRequiredFlagSet {
            connection = .wifi
            }

            if isConnectionOnTrafficOrDemandFlagSet {
            if !isInterventionRequiredFlagSet {
            connection = .wifi
            }
            }

            if isOnWWANFlagSet {
            if !allowsCellularConnection {
            connection = .none
            } else {
            connection = .cellular
            }
            }

            return connection
            }

            fileprivate var previousFlags: SCNetworkReachabilityFlags?

            fileprivate var isRunningOnDevice: Bool = {
            #if targetEnvironment(simulator)
            return false
            #else
            return true
            #endif
            }()

            fileprivate var notifierRunning = false
            fileprivate let reachabilityRef: SCNetworkReachability

            fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")

            fileprivate var usingHostname = false

            required public init(reachabilityRef: SCNetworkReachability, usingHostname: Bool = false) {
            allowsCellularConnection = true
            self.reachabilityRef = reachabilityRef
            self.usingHostname = usingHostname
            }

            public convenience init?(hostname: String) {
            guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil }
            self.init(reachabilityRef: ref, usingHostname: true)
            }

            public convenience init?() {
            var zeroAddress = sockaddr()
            zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
            zeroAddress.sa_family = sa_family_t(AF_INET)

            guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return nil }

            self.init(reachabilityRef: ref)
            }

            deinit {
            stopNotifier()
            }
            }

            public extension Reachability {

            // MARK: - *** Notifier methods ***
            func startNotifier() throws {
            guard !notifierRunning else { return }

            var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
            context.info = UnsafeMutableRawPointer(Unmanaged<Reachability>.passUnretained(self).toOpaque())
            if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) {
            stopNotifier()
            throw ReachabilityError.UnableToSetCallback
            }

            if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
            stopNotifier()
            throw ReachabilityError.UnableToSetDispatchQueue
            }

            // Perform an initial check
            reachabilitySerialQueue.async {
            self.reachabilityChanged()
            }

            notifierRunning = true
            }

            func stopNotifier() {
            defer { notifierRunning = false }

            SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
            SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
            }

            // MARK: - *** Connection test methods ***
            @available(*, deprecated: 4.0, message: "Please use `connection != .none`")
            var isReachable: Bool {
            guard isReachableFlagSet else { return false }

            if isConnectionRequiredAndTransientFlagSet {
            return false
            }

            if isRunningOnDevice {
            if isOnWWANFlagSet && !reachableOnWWAN {
            // We don't want to connect when on cellular connection
            return false
            }
            }

            return true
            }

            @available(*, deprecated: 4.0, message: "Please use `connection == .cellular`")
            var isReachableViaWWAN: Bool {
            // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
            return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet
            }

            @available(*, deprecated: 4.0, message: "Please use `connection == .wifi`")
            var isReachableViaWiFi: Bool {
            // Check we're reachable
            guard isReachableFlagSet else { return false }

            // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
            guard isRunningOnDevice else { return true }

            // Check we're NOT on WWAN
            return !isOnWWANFlagSet
            }

            var description: String {
            let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X"
            let R = isReachableFlagSet ? "R" : "-"
            let c = isConnectionRequiredFlagSet ? "c" : "-"
            let t = isTransientConnectionFlagSet ? "t" : "-"
            let i = isInterventionRequiredFlagSet ? "i" : "-"
            let C = isConnectionOnTrafficFlagSet ? "C" : "-"
            let D = isConnectionOnDemandFlagSet ? "D" : "-"
            let l = isLocalAddressFlagSet ? "l" : "-"
            let d = isDirectFlagSet ? "d" : "-"

            return "(W)(R) (c)(t)(i)(C)(D)(l)(d)"
            }
            }

            fileprivate extension Reachability {
            func reachabilityChanged() {
            guard previousFlags != flags else { return }

            let block = connection != .none ? whenReachable : whenUnreachable

            DispatchQueue.main.async {
            if self.usingHostname {
            print("USING HOSTNAME ABOUT TO CALL BLOCK")
            }
            block?(self)
            self.notificationCenter.post(name: .reachabilityChanged, object:self)
            }

            previousFlags = flags
            }

            var isOnWWANFlagSet: Bool {
            #if os(iOS)
            return flags.contains(.isWWAN)
            #else
            return false
            #endif
            }
            var isReachableFlagSet: Bool {
            return flags.contains(.reachable)
            }
            var isConnectionRequiredFlagSet: Bool {
            return flags.contains(.connectionRequired)
            }
            var isInterventionRequiredFlagSet: Bool {
            return flags.contains(.interventionRequired)
            }
            var isConnectionOnTrafficFlagSet: Bool {
            return flags.contains(.connectionOnTraffic)
            }
            var isConnectionOnDemandFlagSet: Bool {
            return flags.contains(.connectionOnDemand)
            }
            var isConnectionOnTrafficOrDemandFlagSet: Bool {
            return !flags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
            }
            var isTransientConnectionFlagSet: Bool {
            return flags.contains(.transientConnection)
            }
            var isLocalAddressFlagSet: Bool {
            return flags.contains(.isLocalAddress)
            }
            var isDirectFlagSet: Bool {
            return flags.contains(.isDirect)
            }
            var isConnectionRequiredAndTransientFlagSet: Bool {
            return flags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]
            }

            var flags: SCNetworkReachabilityFlags {
            var flags = SCNetworkReachabilityFlags()
            if SCNetworkReachabilityGetFlags(reachabilityRef, &flags) {
            print("Returning flags (flags)")
            return flags
            } else {
            return SCNetworkReachabilityFlags()
            }
            }
            }


            If you want to use this inside your actual project then change the array of hostNames to:



            let hostNames = ["google.com"] // or alibaba.com

            // move it to viewWillAppear because the reachability class property gets set to nil in stopNotifier when it runs inside deinit
            override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)

            startHost(at: 0)
            }

            // remove the dispatch async timer
            func startHost(at index: Int) {
            setupReachability(hostNames[index], useClosures: true)
            startNotifier()
            }

            // add everything else that's inside the ViewController File above





            share|improve this answer


























            • Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

              – IvanMih
              Oct 12 '17 at 8:15











            • @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

              – Lance Samaria
              Oct 12 '17 at 10:56













            • @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

              – Lance Samaria
              Oct 12 '17 at 11:13











            • one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

              – IvanMih
              Oct 12 '17 at 13:01






            • 1





              @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

              – Lance Samaria
              Oct 12 '17 at 20:32



















            0














            I was facing the same issue so with the help of some answers on stackoverflow i created a code that simply hit google.com asynchronously and return true in completion handler if response status is 200.



            Code in Swift 4:



            class func checkInternet(showLoader: Bool = true, completionHandler:@escaping (_ internet:Bool) -> Void)
            {
            UIApplication.shared.isNetworkActivityIndicatorVisible = true

            let url = URL(string: "http://www.google.com/")
            var req = URLRequest.init(url: url!)
            req.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData
            req.timeoutInterval = 10.0

            if showLoader {
            Loader.startLoading()
            }
            let task = URLSession.shared.dataTask(with: req) { (data, response, error) in

            if showLoader {
            Loader.stopLoading()
            }

            if error != nil {
            completionHandler(false)
            } else {
            if let httpResponse = response as? HTTPURLResponse {
            if httpResponse.statusCode == 200 {
            completionHandler(true)
            } else {
            completionHandler(false)
            }
            } else {
            completionHandler(false)
            }
            }
            }
            task.resume()
            }


            Now you can use it like:



                 InternetCheck.checkInternet(completionHandler: { (available) in
            if available {
            print("Net available")
            } else {
            print("Net not available")
            }





            share|improve this answer


























            • you should post an example on how to use it

              – Lance Samaria
              Jan 4 at 20:13











            • added usage example code.

              – Ammar Mujeeb
              Jan 9 at 7:36













            • cool thanks for adding it 😊

              – Lance Samaria
              Jan 9 at 7:37











            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43067753%2fswift-ios-what-to-do-when-there-is-a-wifi-connection-but-no-internet-connection%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            4 Answers
            4






            active

            oldest

            votes








            4 Answers
            4






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            You can init NetworkReachabilityManagerwith host, for example, google host, because default is 0.0.0.0



            let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")


            When you start listening reachability manager doing ping to host. If network is available you can cache SSID and ping again when SSID changed.



            For case .unknown better put a Notification for unsuccessful.



            Example get SSID (it doesn't work in Simulator):



            func fetchSSIDInfo() ->  String? {  
            if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
            let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces, i)
            let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
            let unsafeInterfaceData = CNCopyCurrentNetworkInfo("(rec)" as CFString)

            if let unsafeInterfaceData = unsafeInterfaceData as? Dictionary<AnyHashable, Any> {
            return unsafeInterfaceData["SSID"] as? String
            }
            }
            }
            return nil
            }





            share|improve this answer


























            • thanks I'll try it. How do I cache SSID?

              – Lance Samaria
              Mar 28 '17 at 12:09











            • added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

              – Dialogue
              Mar 28 '17 at 12:21











            • thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

              – Lance Samaria
              Mar 28 '17 at 12:34













            • add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

              – Dialogue
              Mar 28 '17 at 16:29













            • you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

              – Dialogue
              Mar 29 '17 at 6:15
















            1














            You can init NetworkReachabilityManagerwith host, for example, google host, because default is 0.0.0.0



            let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")


            When you start listening reachability manager doing ping to host. If network is available you can cache SSID and ping again when SSID changed.



            For case .unknown better put a Notification for unsuccessful.



            Example get SSID (it doesn't work in Simulator):



            func fetchSSIDInfo() ->  String? {  
            if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
            let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces, i)
            let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
            let unsafeInterfaceData = CNCopyCurrentNetworkInfo("(rec)" as CFString)

            if let unsafeInterfaceData = unsafeInterfaceData as? Dictionary<AnyHashable, Any> {
            return unsafeInterfaceData["SSID"] as? String
            }
            }
            }
            return nil
            }





            share|improve this answer


























            • thanks I'll try it. How do I cache SSID?

              – Lance Samaria
              Mar 28 '17 at 12:09











            • added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

              – Dialogue
              Mar 28 '17 at 12:21











            • thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

              – Lance Samaria
              Mar 28 '17 at 12:34













            • add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

              – Dialogue
              Mar 28 '17 at 16:29













            • you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

              – Dialogue
              Mar 29 '17 at 6:15














            1












            1








            1







            You can init NetworkReachabilityManagerwith host, for example, google host, because default is 0.0.0.0



            let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")


            When you start listening reachability manager doing ping to host. If network is available you can cache SSID and ping again when SSID changed.



            For case .unknown better put a Notification for unsuccessful.



            Example get SSID (it doesn't work in Simulator):



            func fetchSSIDInfo() ->  String? {  
            if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
            let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces, i)
            let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
            let unsafeInterfaceData = CNCopyCurrentNetworkInfo("(rec)" as CFString)

            if let unsafeInterfaceData = unsafeInterfaceData as? Dictionary<AnyHashable, Any> {
            return unsafeInterfaceData["SSID"] as? String
            }
            }
            }
            return nil
            }





            share|improve this answer















            You can init NetworkReachabilityManagerwith host, for example, google host, because default is 0.0.0.0



            let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")


            When you start listening reachability manager doing ping to host. If network is available you can cache SSID and ping again when SSID changed.



            For case .unknown better put a Notification for unsuccessful.



            Example get SSID (it doesn't work in Simulator):



            func fetchSSIDInfo() ->  String? {  
            if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
            let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces, i)
            let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
            let unsafeInterfaceData = CNCopyCurrentNetworkInfo("(rec)" as CFString)

            if let unsafeInterfaceData = unsafeInterfaceData as? Dictionary<AnyHashable, Any> {
            return unsafeInterfaceData["SSID"] as? String
            }
            }
            }
            return nil
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Mar 28 '17 at 12:17

























            answered Mar 28 '17 at 11:51









            DialogueDialogue

            263




            263













            • thanks I'll try it. How do I cache SSID?

              – Lance Samaria
              Mar 28 '17 at 12:09











            • added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

              – Dialogue
              Mar 28 '17 at 12:21











            • thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

              – Lance Samaria
              Mar 28 '17 at 12:34













            • add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

              – Dialogue
              Mar 28 '17 at 16:29













            • you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

              – Dialogue
              Mar 29 '17 at 6:15



















            • thanks I'll try it. How do I cache SSID?

              – Lance Samaria
              Mar 28 '17 at 12:09











            • added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

              – Dialogue
              Mar 28 '17 at 12:21











            • thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

              – Lance Samaria
              Mar 28 '17 at 12:34













            • add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

              – Dialogue
              Mar 28 '17 at 16:29













            • you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

              – Dialogue
              Mar 29 '17 at 6:15

















            thanks I'll try it. How do I cache SSID?

            – Lance Samaria
            Mar 28 '17 at 12:09





            thanks I'll try it. How do I cache SSID?

            – Lance Samaria
            Mar 28 '17 at 12:09













            added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

            – Dialogue
            Mar 28 '17 at 12:21





            added get ssid to answer, for save ssid you can use User​Defaults or your DB or other methods

            – Dialogue
            Mar 28 '17 at 12:21













            thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

            – Lance Samaria
            Mar 28 '17 at 12:34







            thanks for the help. Do I add that function to the Reachability class or SomeVC? How do you call it and test with bool? I see it returns an Optional of type String

            – Lance Samaria
            Mar 28 '17 at 12:34















            add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

            – Dialogue
            Mar 28 '17 at 16:29







            add fetchSSIDInfo() to NetworkManager guard let ssid = fetchSSIDInfo() else {return} //save ssid

            – Dialogue
            Mar 28 '17 at 16:29















            you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

            – Dialogue
            Mar 29 '17 at 6:15





            you can check SSID changed before send some request type or by timer if let currentSSID = fetchSSIDInfo(), currentSSID != //saved SSID { //do ping}

            – Dialogue
            Mar 29 '17 at 6:15













            0














            Here's an answer composed of these 2 solutions:Pavle Mijatovic and Yasin Ugurlu



            Make a new class and name it Connection and copy and paste the code below inside of it:



            import Foundation
            import SystemConfiguration

            class Connection {

            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)

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

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

            let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
            let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

            return isReachable && !needsConnection

            }

            class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) {

            // 1. Check the WiFi Connection
            guard isConnectedToNetwork() else {
            completionHandler(false)
            return
            }

            // 2. Check the Internet Connection but possibly use www.apple.com or www.alibaba.com instead of google.com because it's not available in China
            var webAddress = "https://www.google.com" // Default Web Site
            if let _ = webSiteToPing {
            webAddress = webSiteToPing!
            }

            guard let url = URL(string: webAddress) else {
            completionHandler(false)
            print("could not create url from: (webAddress)")
            return
            }

            let urlRequest = URLRequest(url: url)
            let session = URLSession.shared
            let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
            if error != nil || response == nil {
            completionHandler(false)
            } else {
            completionHandler(true)
            }
            })
            task.resume()
            }
            }


            In whatever view controller your using it in inside viewDidLoad call it like this:



            override func viewDidLoad() {
            super.viewDidLoad()

            // if in china usewww.apple.com or www.alibaba.com instead
            Connection.isInternetAvailable(webSiteToPing: "https://www.google.com", completionHandler: {
            (bool) in

            if bool{
            print("Internet connection is good")
            }else{
            print("No internet connection can be found")
            }
            })
            }


            A couple of things I've found out is this only seems to work once because if a connection is available "Internet connection is good" prints but if I go to airplane mode "No internet connection can be found" doesn't print. It's not actively listening which makes me think I have to hook up to a Notification? The other thing is if your in China then this will not work because google isn't available in China. Maybe a better website to check would be www.apple.com or www.alibaba.com as it seems they're available everywhere.



            Connection.isInternetAvailable(webSiteToPing: "https://www.apple.com"...


            or



            Connection.isInternetAvailable(webSiteToPing: "https://www.alibaba.com"...





            share|improve this answer






























              0














              Here's an answer composed of these 2 solutions:Pavle Mijatovic and Yasin Ugurlu



              Make a new class and name it Connection and copy and paste the code below inside of it:



              import Foundation
              import SystemConfiguration

              class Connection {

              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)

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

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

              let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
              let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

              return isReachable && !needsConnection

              }

              class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) {

              // 1. Check the WiFi Connection
              guard isConnectedToNetwork() else {
              completionHandler(false)
              return
              }

              // 2. Check the Internet Connection but possibly use www.apple.com or www.alibaba.com instead of google.com because it's not available in China
              var webAddress = "https://www.google.com" // Default Web Site
              if let _ = webSiteToPing {
              webAddress = webSiteToPing!
              }

              guard let url = URL(string: webAddress) else {
              completionHandler(false)
              print("could not create url from: (webAddress)")
              return
              }

              let urlRequest = URLRequest(url: url)
              let session = URLSession.shared
              let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
              if error != nil || response == nil {
              completionHandler(false)
              } else {
              completionHandler(true)
              }
              })
              task.resume()
              }
              }


              In whatever view controller your using it in inside viewDidLoad call it like this:



              override func viewDidLoad() {
              super.viewDidLoad()

              // if in china usewww.apple.com or www.alibaba.com instead
              Connection.isInternetAvailable(webSiteToPing: "https://www.google.com", completionHandler: {
              (bool) in

              if bool{
              print("Internet connection is good")
              }else{
              print("No internet connection can be found")
              }
              })
              }


              A couple of things I've found out is this only seems to work once because if a connection is available "Internet connection is good" prints but if I go to airplane mode "No internet connection can be found" doesn't print. It's not actively listening which makes me think I have to hook up to a Notification? The other thing is if your in China then this will not work because google isn't available in China. Maybe a better website to check would be www.apple.com or www.alibaba.com as it seems they're available everywhere.



              Connection.isInternetAvailable(webSiteToPing: "https://www.apple.com"...


              or



              Connection.isInternetAvailable(webSiteToPing: "https://www.alibaba.com"...





              share|improve this answer




























                0












                0








                0







                Here's an answer composed of these 2 solutions:Pavle Mijatovic and Yasin Ugurlu



                Make a new class and name it Connection and copy and paste the code below inside of it:



                import Foundation
                import SystemConfiguration

                class Connection {

                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)

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

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

                let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
                let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

                return isReachable && !needsConnection

                }

                class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) {

                // 1. Check the WiFi Connection
                guard isConnectedToNetwork() else {
                completionHandler(false)
                return
                }

                // 2. Check the Internet Connection but possibly use www.apple.com or www.alibaba.com instead of google.com because it's not available in China
                var webAddress = "https://www.google.com" // Default Web Site
                if let _ = webSiteToPing {
                webAddress = webSiteToPing!
                }

                guard let url = URL(string: webAddress) else {
                completionHandler(false)
                print("could not create url from: (webAddress)")
                return
                }

                let urlRequest = URLRequest(url: url)
                let session = URLSession.shared
                let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
                if error != nil || response == nil {
                completionHandler(false)
                } else {
                completionHandler(true)
                }
                })
                task.resume()
                }
                }


                In whatever view controller your using it in inside viewDidLoad call it like this:



                override func viewDidLoad() {
                super.viewDidLoad()

                // if in china usewww.apple.com or www.alibaba.com instead
                Connection.isInternetAvailable(webSiteToPing: "https://www.google.com", completionHandler: {
                (bool) in

                if bool{
                print("Internet connection is good")
                }else{
                print("No internet connection can be found")
                }
                })
                }


                A couple of things I've found out is this only seems to work once because if a connection is available "Internet connection is good" prints but if I go to airplane mode "No internet connection can be found" doesn't print. It's not actively listening which makes me think I have to hook up to a Notification? The other thing is if your in China then this will not work because google isn't available in China. Maybe a better website to check would be www.apple.com or www.alibaba.com as it seems they're available everywhere.



                Connection.isInternetAvailable(webSiteToPing: "https://www.apple.com"...


                or



                Connection.isInternetAvailable(webSiteToPing: "https://www.alibaba.com"...





                share|improve this answer















                Here's an answer composed of these 2 solutions:Pavle Mijatovic and Yasin Ugurlu



                Make a new class and name it Connection and copy and paste the code below inside of it:



                import Foundation
                import SystemConfiguration

                class Connection {

                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)

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

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

                let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
                let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

                return isReachable && !needsConnection

                }

                class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) {

                // 1. Check the WiFi Connection
                guard isConnectedToNetwork() else {
                completionHandler(false)
                return
                }

                // 2. Check the Internet Connection but possibly use www.apple.com or www.alibaba.com instead of google.com because it's not available in China
                var webAddress = "https://www.google.com" // Default Web Site
                if let _ = webSiteToPing {
                webAddress = webSiteToPing!
                }

                guard let url = URL(string: webAddress) else {
                completionHandler(false)
                print("could not create url from: (webAddress)")
                return
                }

                let urlRequest = URLRequest(url: url)
                let session = URLSession.shared
                let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
                if error != nil || response == nil {
                completionHandler(false)
                } else {
                completionHandler(true)
                }
                })
                task.resume()
                }
                }


                In whatever view controller your using it in inside viewDidLoad call it like this:



                override func viewDidLoad() {
                super.viewDidLoad()

                // if in china usewww.apple.com or www.alibaba.com instead
                Connection.isInternetAvailable(webSiteToPing: "https://www.google.com", completionHandler: {
                (bool) in

                if bool{
                print("Internet connection is good")
                }else{
                print("No internet connection can be found")
                }
                })
                }


                A couple of things I've found out is this only seems to work once because if a connection is available "Internet connection is good" prints but if I go to airplane mode "No internet connection can be found" doesn't print. It's not actively listening which makes me think I have to hook up to a Notification? The other thing is if your in China then this will not work because google isn't available in China. Maybe a better website to check would be www.apple.com or www.alibaba.com as it seems they're available everywhere.



                Connection.isInternetAvailable(webSiteToPing: "https://www.apple.com"...


                or



                Connection.isInternetAvailable(webSiteToPing: "https://www.alibaba.com"...






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Feb 23 '18 at 17:24

























                answered Feb 23 '18 at 15:29









                Lance SamariaLance Samaria

                2,52921451




                2,52921451























                    0














                    I followed this AshleyMills Reachability file and it uses google.com to test for a connection. You can just copy and paste the below inside a new file to test to see how it works. If your using this in China then use alibaba.com because google isn't available in China.



                    // everywhere outside China
                    let hostNames = [nil, "google.com", "invalidhost"]

                    // everywhere including China
                    let hostNames = [nil, "alibaba.com", "invalidhost"]


                    When you first launch the app you will see the labels change every 5 seconds because there is an async timer inside: func startHost(at index: Int)



                    If you want to stop it and take control of everything yourself then comment out this code:



                    // comment this out to stop the connection from changing
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    //self.startHost(at: (index + 1) % 3)
                    }


                    Once you comment that out then you should toggle your phones connection between Wifi, Cellular Connection, and Airplane Mode. The label colors will change from green to blue to red depending on the connection.



                    Create a new project and add this to the ViewController file:



                    import UIKit

                    class ViewController: UIViewController {

                    let networkStatus: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Status"
                    label.textAlignment = .center
                    return label
                    }()

                    let hostNameLabel: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Host"
                    label.textAlignment = .center
                    return label
                    }()

                    var reachability: Reachability?
                    let hostNames = [nil, "google.com", "invalidhost"]
                    var hostIndex = 0

                    override func viewDidLoad() {
                    super.viewDidLoad()

                    setConstraints()
                    startHost(at: 1)
                    }

                    func startHost(at index: Int) {
                    stopNotifier()
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()

                    // this loops the connection every 5 seconds
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    self.startHost(at: (index + 1) % 3)
                    }
                    }

                    func setupReachability(_ hostName: String?, useClosures: Bool) {
                    let reachability: Reachability?
                    if let hostName = hostName {
                    reachability = Reachability(hostname: hostName)
                    hostNameLabel.text = hostName
                    } else {
                    reachability = Reachability()
                    hostNameLabel.text = "No host name"
                    }
                    self.reachability = reachability
                    print("--- set up with host name: (hostNameLabel.text!)")

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

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

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

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

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    self.networkStatus.textColor = .red

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    if reachability.connection != .none {
                    updateLabelColourWhenReachable(reachability)
                    } else {
                    updateLabelColourWhenNotReachable(reachability)
                    }
                    }

                    func setConstraints(){
                    view.addSubview(networkStatus)
                    view.addSubview(hostNameLabel)

                    networkStatus.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    networkStatus.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    networkStatus.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

                    hostNameLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    hostNameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    hostNameLabel.topAnchor.constraint(equalTo: networkStatus.bottomAnchor, constant: 20).isActive = true
                    }

                    deinit {
                    stopNotifier()
                    }
                    }


                    Create a File named Reachability and add this to it:



                    import SystemConfiguration
                    import Foundation

                    public enum ReachabilityError: Error {
                    case FailedToCreateWithAddress(sockaddr_in)
                    case FailedToCreateWithHostname(String)
                    case UnableToSetCallback
                    case UnableToSetDispatchQueue
                    }

                    @available(*, unavailable, renamed: "Notification.Name.reachabilityChanged")
                    public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification")

                    extension Notification.Name {
                    public static let reachabilityChanged = Notification.Name("reachabilityChanged")
                    }

                    func callback(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
                    guard let info = info else { return }

                    let reachability = Unmanaged<Reachability>.fromOpaque(info).takeUnretainedValue()
                    reachability.reachabilityChanged()
                    }

                    public class Reachability {

                    public typealias NetworkReachable = (Reachability) -> ()
                    public typealias NetworkUnreachable = (Reachability) -> ()

                    @available(*, unavailable, renamed: "Connection")
                    public enum NetworkStatus: CustomStringConvertible {
                    case notReachable, reachableViaWiFi, reachableViaWWAN
                    public var description: String {
                    switch self {
                    case .reachableViaWWAN: return "Cellular"
                    case .reachableViaWiFi: return "WiFi"
                    case .notReachable: return "No Connection"
                    }
                    }
                    }

                    public enum Connection: CustomStringConvertible {
                    case none, wifi, cellular
                    public var description: String {
                    switch self {
                    case .cellular: return "Cellular"
                    case .wifi: return "WiFi"
                    case .none: return "No Connection"
                    }
                    }
                    }

                    public var whenReachable: NetworkReachable?
                    public var whenUnreachable: NetworkUnreachable?

                    @available(*, deprecated: 4.0, renamed: "allowsCellularConnection")
                    public let reachableOnWWAN: Bool = true

                    /// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`)
                    public var allowsCellularConnection: Bool

                    // The notification center on which "reachability changed" events are being posted
                    public var notificationCenter: NotificationCenter = NotificationCenter.default

                    @available(*, deprecated: 4.0, renamed: "connection.description")
                    public var currentReachabilityString: String {
                    return "(connection)"
                    }

                    @available(*, unavailable, renamed: "connection")
                    public var currentReachabilityStatus: Connection {
                    return connection
                    }

                    public var connection: Connection {
                    guard isReachableFlagSet else { return .none }

                    // If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return .wifi }

                    var connection = Connection.none

                    if !isConnectionRequiredFlagSet {
                    connection = .wifi
                    }

                    if isConnectionOnTrafficOrDemandFlagSet {
                    if !isInterventionRequiredFlagSet {
                    connection = .wifi
                    }
                    }

                    if isOnWWANFlagSet {
                    if !allowsCellularConnection {
                    connection = .none
                    } else {
                    connection = .cellular
                    }
                    }

                    return connection
                    }

                    fileprivate var previousFlags: SCNetworkReachabilityFlags?

                    fileprivate var isRunningOnDevice: Bool = {
                    #if targetEnvironment(simulator)
                    return false
                    #else
                    return true
                    #endif
                    }()

                    fileprivate var notifierRunning = false
                    fileprivate let reachabilityRef: SCNetworkReachability

                    fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")

                    fileprivate var usingHostname = false

                    required public init(reachabilityRef: SCNetworkReachability, usingHostname: Bool = false) {
                    allowsCellularConnection = true
                    self.reachabilityRef = reachabilityRef
                    self.usingHostname = usingHostname
                    }

                    public convenience init?(hostname: String) {
                    guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil }
                    self.init(reachabilityRef: ref, usingHostname: true)
                    }

                    public convenience init?() {
                    var zeroAddress = sockaddr()
                    zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
                    zeroAddress.sa_family = sa_family_t(AF_INET)

                    guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return nil }

                    self.init(reachabilityRef: ref)
                    }

                    deinit {
                    stopNotifier()
                    }
                    }

                    public extension Reachability {

                    // MARK: - *** Notifier methods ***
                    func startNotifier() throws {
                    guard !notifierRunning else { return }

                    var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
                    context.info = UnsafeMutableRawPointer(Unmanaged<Reachability>.passUnretained(self).toOpaque())
                    if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetCallback
                    }

                    if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetDispatchQueue
                    }

                    // Perform an initial check
                    reachabilitySerialQueue.async {
                    self.reachabilityChanged()
                    }

                    notifierRunning = true
                    }

                    func stopNotifier() {
                    defer { notifierRunning = false }

                    SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
                    SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
                    }

                    // MARK: - *** Connection test methods ***
                    @available(*, deprecated: 4.0, message: "Please use `connection != .none`")
                    var isReachable: Bool {
                    guard isReachableFlagSet else { return false }

                    if isConnectionRequiredAndTransientFlagSet {
                    return false
                    }

                    if isRunningOnDevice {
                    if isOnWWANFlagSet && !reachableOnWWAN {
                    // We don't want to connect when on cellular connection
                    return false
                    }
                    }

                    return true
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .cellular`")
                    var isReachableViaWWAN: Bool {
                    // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
                    return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .wifi`")
                    var isReachableViaWiFi: Bool {
                    // Check we're reachable
                    guard isReachableFlagSet else { return false }

                    // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return true }

                    // Check we're NOT on WWAN
                    return !isOnWWANFlagSet
                    }

                    var description: String {
                    let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X"
                    let R = isReachableFlagSet ? "R" : "-"
                    let c = isConnectionRequiredFlagSet ? "c" : "-"
                    let t = isTransientConnectionFlagSet ? "t" : "-"
                    let i = isInterventionRequiredFlagSet ? "i" : "-"
                    let C = isConnectionOnTrafficFlagSet ? "C" : "-"
                    let D = isConnectionOnDemandFlagSet ? "D" : "-"
                    let l = isLocalAddressFlagSet ? "l" : "-"
                    let d = isDirectFlagSet ? "d" : "-"

                    return "(W)(R) (c)(t)(i)(C)(D)(l)(d)"
                    }
                    }

                    fileprivate extension Reachability {
                    func reachabilityChanged() {
                    guard previousFlags != flags else { return }

                    let block = connection != .none ? whenReachable : whenUnreachable

                    DispatchQueue.main.async {
                    if self.usingHostname {
                    print("USING HOSTNAME ABOUT TO CALL BLOCK")
                    }
                    block?(self)
                    self.notificationCenter.post(name: .reachabilityChanged, object:self)
                    }

                    previousFlags = flags
                    }

                    var isOnWWANFlagSet: Bool {
                    #if os(iOS)
                    return flags.contains(.isWWAN)
                    #else
                    return false
                    #endif
                    }
                    var isReachableFlagSet: Bool {
                    return flags.contains(.reachable)
                    }
                    var isConnectionRequiredFlagSet: Bool {
                    return flags.contains(.connectionRequired)
                    }
                    var isInterventionRequiredFlagSet: Bool {
                    return flags.contains(.interventionRequired)
                    }
                    var isConnectionOnTrafficFlagSet: Bool {
                    return flags.contains(.connectionOnTraffic)
                    }
                    var isConnectionOnDemandFlagSet: Bool {
                    return flags.contains(.connectionOnDemand)
                    }
                    var isConnectionOnTrafficOrDemandFlagSet: Bool {
                    return !flags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
                    }
                    var isTransientConnectionFlagSet: Bool {
                    return flags.contains(.transientConnection)
                    }
                    var isLocalAddressFlagSet: Bool {
                    return flags.contains(.isLocalAddress)
                    }
                    var isDirectFlagSet: Bool {
                    return flags.contains(.isDirect)
                    }
                    var isConnectionRequiredAndTransientFlagSet: Bool {
                    return flags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]
                    }

                    var flags: SCNetworkReachabilityFlags {
                    var flags = SCNetworkReachabilityFlags()
                    if SCNetworkReachabilityGetFlags(reachabilityRef, &flags) {
                    print("Returning flags (flags)")
                    return flags
                    } else {
                    return SCNetworkReachabilityFlags()
                    }
                    }
                    }


                    If you want to use this inside your actual project then change the array of hostNames to:



                    let hostNames = ["google.com"] // or alibaba.com

                    // move it to viewWillAppear because the reachability class property gets set to nil in stopNotifier when it runs inside deinit
                    override func viewWillAppear(_ animated: Bool) {
                    super.viewWillAppear(animated)

                    startHost(at: 0)
                    }

                    // remove the dispatch async timer
                    func startHost(at index: Int) {
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()
                    }

                    // add everything else that's inside the ViewController File above





                    share|improve this answer


























                    • Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

                      – IvanMih
                      Oct 12 '17 at 8:15











                    • @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

                      – Lance Samaria
                      Oct 12 '17 at 10:56













                    • @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

                      – Lance Samaria
                      Oct 12 '17 at 11:13











                    • one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

                      – IvanMih
                      Oct 12 '17 at 13:01






                    • 1





                      @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

                      – Lance Samaria
                      Oct 12 '17 at 20:32
















                    0














                    I followed this AshleyMills Reachability file and it uses google.com to test for a connection. You can just copy and paste the below inside a new file to test to see how it works. If your using this in China then use alibaba.com because google isn't available in China.



                    // everywhere outside China
                    let hostNames = [nil, "google.com", "invalidhost"]

                    // everywhere including China
                    let hostNames = [nil, "alibaba.com", "invalidhost"]


                    When you first launch the app you will see the labels change every 5 seconds because there is an async timer inside: func startHost(at index: Int)



                    If you want to stop it and take control of everything yourself then comment out this code:



                    // comment this out to stop the connection from changing
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    //self.startHost(at: (index + 1) % 3)
                    }


                    Once you comment that out then you should toggle your phones connection between Wifi, Cellular Connection, and Airplane Mode. The label colors will change from green to blue to red depending on the connection.



                    Create a new project and add this to the ViewController file:



                    import UIKit

                    class ViewController: UIViewController {

                    let networkStatus: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Status"
                    label.textAlignment = .center
                    return label
                    }()

                    let hostNameLabel: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Host"
                    label.textAlignment = .center
                    return label
                    }()

                    var reachability: Reachability?
                    let hostNames = [nil, "google.com", "invalidhost"]
                    var hostIndex = 0

                    override func viewDidLoad() {
                    super.viewDidLoad()

                    setConstraints()
                    startHost(at: 1)
                    }

                    func startHost(at index: Int) {
                    stopNotifier()
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()

                    // this loops the connection every 5 seconds
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    self.startHost(at: (index + 1) % 3)
                    }
                    }

                    func setupReachability(_ hostName: String?, useClosures: Bool) {
                    let reachability: Reachability?
                    if let hostName = hostName {
                    reachability = Reachability(hostname: hostName)
                    hostNameLabel.text = hostName
                    } else {
                    reachability = Reachability()
                    hostNameLabel.text = "No host name"
                    }
                    self.reachability = reachability
                    print("--- set up with host name: (hostNameLabel.text!)")

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

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

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

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

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    self.networkStatus.textColor = .red

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    if reachability.connection != .none {
                    updateLabelColourWhenReachable(reachability)
                    } else {
                    updateLabelColourWhenNotReachable(reachability)
                    }
                    }

                    func setConstraints(){
                    view.addSubview(networkStatus)
                    view.addSubview(hostNameLabel)

                    networkStatus.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    networkStatus.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    networkStatus.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

                    hostNameLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    hostNameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    hostNameLabel.topAnchor.constraint(equalTo: networkStatus.bottomAnchor, constant: 20).isActive = true
                    }

                    deinit {
                    stopNotifier()
                    }
                    }


                    Create a File named Reachability and add this to it:



                    import SystemConfiguration
                    import Foundation

                    public enum ReachabilityError: Error {
                    case FailedToCreateWithAddress(sockaddr_in)
                    case FailedToCreateWithHostname(String)
                    case UnableToSetCallback
                    case UnableToSetDispatchQueue
                    }

                    @available(*, unavailable, renamed: "Notification.Name.reachabilityChanged")
                    public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification")

                    extension Notification.Name {
                    public static let reachabilityChanged = Notification.Name("reachabilityChanged")
                    }

                    func callback(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
                    guard let info = info else { return }

                    let reachability = Unmanaged<Reachability>.fromOpaque(info).takeUnretainedValue()
                    reachability.reachabilityChanged()
                    }

                    public class Reachability {

                    public typealias NetworkReachable = (Reachability) -> ()
                    public typealias NetworkUnreachable = (Reachability) -> ()

                    @available(*, unavailable, renamed: "Connection")
                    public enum NetworkStatus: CustomStringConvertible {
                    case notReachable, reachableViaWiFi, reachableViaWWAN
                    public var description: String {
                    switch self {
                    case .reachableViaWWAN: return "Cellular"
                    case .reachableViaWiFi: return "WiFi"
                    case .notReachable: return "No Connection"
                    }
                    }
                    }

                    public enum Connection: CustomStringConvertible {
                    case none, wifi, cellular
                    public var description: String {
                    switch self {
                    case .cellular: return "Cellular"
                    case .wifi: return "WiFi"
                    case .none: return "No Connection"
                    }
                    }
                    }

                    public var whenReachable: NetworkReachable?
                    public var whenUnreachable: NetworkUnreachable?

                    @available(*, deprecated: 4.0, renamed: "allowsCellularConnection")
                    public let reachableOnWWAN: Bool = true

                    /// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`)
                    public var allowsCellularConnection: Bool

                    // The notification center on which "reachability changed" events are being posted
                    public var notificationCenter: NotificationCenter = NotificationCenter.default

                    @available(*, deprecated: 4.0, renamed: "connection.description")
                    public var currentReachabilityString: String {
                    return "(connection)"
                    }

                    @available(*, unavailable, renamed: "connection")
                    public var currentReachabilityStatus: Connection {
                    return connection
                    }

                    public var connection: Connection {
                    guard isReachableFlagSet else { return .none }

                    // If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return .wifi }

                    var connection = Connection.none

                    if !isConnectionRequiredFlagSet {
                    connection = .wifi
                    }

                    if isConnectionOnTrafficOrDemandFlagSet {
                    if !isInterventionRequiredFlagSet {
                    connection = .wifi
                    }
                    }

                    if isOnWWANFlagSet {
                    if !allowsCellularConnection {
                    connection = .none
                    } else {
                    connection = .cellular
                    }
                    }

                    return connection
                    }

                    fileprivate var previousFlags: SCNetworkReachabilityFlags?

                    fileprivate var isRunningOnDevice: Bool = {
                    #if targetEnvironment(simulator)
                    return false
                    #else
                    return true
                    #endif
                    }()

                    fileprivate var notifierRunning = false
                    fileprivate let reachabilityRef: SCNetworkReachability

                    fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")

                    fileprivate var usingHostname = false

                    required public init(reachabilityRef: SCNetworkReachability, usingHostname: Bool = false) {
                    allowsCellularConnection = true
                    self.reachabilityRef = reachabilityRef
                    self.usingHostname = usingHostname
                    }

                    public convenience init?(hostname: String) {
                    guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil }
                    self.init(reachabilityRef: ref, usingHostname: true)
                    }

                    public convenience init?() {
                    var zeroAddress = sockaddr()
                    zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
                    zeroAddress.sa_family = sa_family_t(AF_INET)

                    guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return nil }

                    self.init(reachabilityRef: ref)
                    }

                    deinit {
                    stopNotifier()
                    }
                    }

                    public extension Reachability {

                    // MARK: - *** Notifier methods ***
                    func startNotifier() throws {
                    guard !notifierRunning else { return }

                    var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
                    context.info = UnsafeMutableRawPointer(Unmanaged<Reachability>.passUnretained(self).toOpaque())
                    if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetCallback
                    }

                    if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetDispatchQueue
                    }

                    // Perform an initial check
                    reachabilitySerialQueue.async {
                    self.reachabilityChanged()
                    }

                    notifierRunning = true
                    }

                    func stopNotifier() {
                    defer { notifierRunning = false }

                    SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
                    SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
                    }

                    // MARK: - *** Connection test methods ***
                    @available(*, deprecated: 4.0, message: "Please use `connection != .none`")
                    var isReachable: Bool {
                    guard isReachableFlagSet else { return false }

                    if isConnectionRequiredAndTransientFlagSet {
                    return false
                    }

                    if isRunningOnDevice {
                    if isOnWWANFlagSet && !reachableOnWWAN {
                    // We don't want to connect when on cellular connection
                    return false
                    }
                    }

                    return true
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .cellular`")
                    var isReachableViaWWAN: Bool {
                    // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
                    return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .wifi`")
                    var isReachableViaWiFi: Bool {
                    // Check we're reachable
                    guard isReachableFlagSet else { return false }

                    // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return true }

                    // Check we're NOT on WWAN
                    return !isOnWWANFlagSet
                    }

                    var description: String {
                    let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X"
                    let R = isReachableFlagSet ? "R" : "-"
                    let c = isConnectionRequiredFlagSet ? "c" : "-"
                    let t = isTransientConnectionFlagSet ? "t" : "-"
                    let i = isInterventionRequiredFlagSet ? "i" : "-"
                    let C = isConnectionOnTrafficFlagSet ? "C" : "-"
                    let D = isConnectionOnDemandFlagSet ? "D" : "-"
                    let l = isLocalAddressFlagSet ? "l" : "-"
                    let d = isDirectFlagSet ? "d" : "-"

                    return "(W)(R) (c)(t)(i)(C)(D)(l)(d)"
                    }
                    }

                    fileprivate extension Reachability {
                    func reachabilityChanged() {
                    guard previousFlags != flags else { return }

                    let block = connection != .none ? whenReachable : whenUnreachable

                    DispatchQueue.main.async {
                    if self.usingHostname {
                    print("USING HOSTNAME ABOUT TO CALL BLOCK")
                    }
                    block?(self)
                    self.notificationCenter.post(name: .reachabilityChanged, object:self)
                    }

                    previousFlags = flags
                    }

                    var isOnWWANFlagSet: Bool {
                    #if os(iOS)
                    return flags.contains(.isWWAN)
                    #else
                    return false
                    #endif
                    }
                    var isReachableFlagSet: Bool {
                    return flags.contains(.reachable)
                    }
                    var isConnectionRequiredFlagSet: Bool {
                    return flags.contains(.connectionRequired)
                    }
                    var isInterventionRequiredFlagSet: Bool {
                    return flags.contains(.interventionRequired)
                    }
                    var isConnectionOnTrafficFlagSet: Bool {
                    return flags.contains(.connectionOnTraffic)
                    }
                    var isConnectionOnDemandFlagSet: Bool {
                    return flags.contains(.connectionOnDemand)
                    }
                    var isConnectionOnTrafficOrDemandFlagSet: Bool {
                    return !flags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
                    }
                    var isTransientConnectionFlagSet: Bool {
                    return flags.contains(.transientConnection)
                    }
                    var isLocalAddressFlagSet: Bool {
                    return flags.contains(.isLocalAddress)
                    }
                    var isDirectFlagSet: Bool {
                    return flags.contains(.isDirect)
                    }
                    var isConnectionRequiredAndTransientFlagSet: Bool {
                    return flags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]
                    }

                    var flags: SCNetworkReachabilityFlags {
                    var flags = SCNetworkReachabilityFlags()
                    if SCNetworkReachabilityGetFlags(reachabilityRef, &flags) {
                    print("Returning flags (flags)")
                    return flags
                    } else {
                    return SCNetworkReachabilityFlags()
                    }
                    }
                    }


                    If you want to use this inside your actual project then change the array of hostNames to:



                    let hostNames = ["google.com"] // or alibaba.com

                    // move it to viewWillAppear because the reachability class property gets set to nil in stopNotifier when it runs inside deinit
                    override func viewWillAppear(_ animated: Bool) {
                    super.viewWillAppear(animated)

                    startHost(at: 0)
                    }

                    // remove the dispatch async timer
                    func startHost(at index: Int) {
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()
                    }

                    // add everything else that's inside the ViewController File above





                    share|improve this answer


























                    • Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

                      – IvanMih
                      Oct 12 '17 at 8:15











                    • @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

                      – Lance Samaria
                      Oct 12 '17 at 10:56













                    • @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

                      – Lance Samaria
                      Oct 12 '17 at 11:13











                    • one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

                      – IvanMih
                      Oct 12 '17 at 13:01






                    • 1





                      @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

                      – Lance Samaria
                      Oct 12 '17 at 20:32














                    0












                    0








                    0







                    I followed this AshleyMills Reachability file and it uses google.com to test for a connection. You can just copy and paste the below inside a new file to test to see how it works. If your using this in China then use alibaba.com because google isn't available in China.



                    // everywhere outside China
                    let hostNames = [nil, "google.com", "invalidhost"]

                    // everywhere including China
                    let hostNames = [nil, "alibaba.com", "invalidhost"]


                    When you first launch the app you will see the labels change every 5 seconds because there is an async timer inside: func startHost(at index: Int)



                    If you want to stop it and take control of everything yourself then comment out this code:



                    // comment this out to stop the connection from changing
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    //self.startHost(at: (index + 1) % 3)
                    }


                    Once you comment that out then you should toggle your phones connection between Wifi, Cellular Connection, and Airplane Mode. The label colors will change from green to blue to red depending on the connection.



                    Create a new project and add this to the ViewController file:



                    import UIKit

                    class ViewController: UIViewController {

                    let networkStatus: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Status"
                    label.textAlignment = .center
                    return label
                    }()

                    let hostNameLabel: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Host"
                    label.textAlignment = .center
                    return label
                    }()

                    var reachability: Reachability?
                    let hostNames = [nil, "google.com", "invalidhost"]
                    var hostIndex = 0

                    override func viewDidLoad() {
                    super.viewDidLoad()

                    setConstraints()
                    startHost(at: 1)
                    }

                    func startHost(at index: Int) {
                    stopNotifier()
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()

                    // this loops the connection every 5 seconds
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    self.startHost(at: (index + 1) % 3)
                    }
                    }

                    func setupReachability(_ hostName: String?, useClosures: Bool) {
                    let reachability: Reachability?
                    if let hostName = hostName {
                    reachability = Reachability(hostname: hostName)
                    hostNameLabel.text = hostName
                    } else {
                    reachability = Reachability()
                    hostNameLabel.text = "No host name"
                    }
                    self.reachability = reachability
                    print("--- set up with host name: (hostNameLabel.text!)")

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

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

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

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

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    self.networkStatus.textColor = .red

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    if reachability.connection != .none {
                    updateLabelColourWhenReachable(reachability)
                    } else {
                    updateLabelColourWhenNotReachable(reachability)
                    }
                    }

                    func setConstraints(){
                    view.addSubview(networkStatus)
                    view.addSubview(hostNameLabel)

                    networkStatus.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    networkStatus.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    networkStatus.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

                    hostNameLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    hostNameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    hostNameLabel.topAnchor.constraint(equalTo: networkStatus.bottomAnchor, constant: 20).isActive = true
                    }

                    deinit {
                    stopNotifier()
                    }
                    }


                    Create a File named Reachability and add this to it:



                    import SystemConfiguration
                    import Foundation

                    public enum ReachabilityError: Error {
                    case FailedToCreateWithAddress(sockaddr_in)
                    case FailedToCreateWithHostname(String)
                    case UnableToSetCallback
                    case UnableToSetDispatchQueue
                    }

                    @available(*, unavailable, renamed: "Notification.Name.reachabilityChanged")
                    public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification")

                    extension Notification.Name {
                    public static let reachabilityChanged = Notification.Name("reachabilityChanged")
                    }

                    func callback(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
                    guard let info = info else { return }

                    let reachability = Unmanaged<Reachability>.fromOpaque(info).takeUnretainedValue()
                    reachability.reachabilityChanged()
                    }

                    public class Reachability {

                    public typealias NetworkReachable = (Reachability) -> ()
                    public typealias NetworkUnreachable = (Reachability) -> ()

                    @available(*, unavailable, renamed: "Connection")
                    public enum NetworkStatus: CustomStringConvertible {
                    case notReachable, reachableViaWiFi, reachableViaWWAN
                    public var description: String {
                    switch self {
                    case .reachableViaWWAN: return "Cellular"
                    case .reachableViaWiFi: return "WiFi"
                    case .notReachable: return "No Connection"
                    }
                    }
                    }

                    public enum Connection: CustomStringConvertible {
                    case none, wifi, cellular
                    public var description: String {
                    switch self {
                    case .cellular: return "Cellular"
                    case .wifi: return "WiFi"
                    case .none: return "No Connection"
                    }
                    }
                    }

                    public var whenReachable: NetworkReachable?
                    public var whenUnreachable: NetworkUnreachable?

                    @available(*, deprecated: 4.0, renamed: "allowsCellularConnection")
                    public let reachableOnWWAN: Bool = true

                    /// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`)
                    public var allowsCellularConnection: Bool

                    // The notification center on which "reachability changed" events are being posted
                    public var notificationCenter: NotificationCenter = NotificationCenter.default

                    @available(*, deprecated: 4.0, renamed: "connection.description")
                    public var currentReachabilityString: String {
                    return "(connection)"
                    }

                    @available(*, unavailable, renamed: "connection")
                    public var currentReachabilityStatus: Connection {
                    return connection
                    }

                    public var connection: Connection {
                    guard isReachableFlagSet else { return .none }

                    // If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return .wifi }

                    var connection = Connection.none

                    if !isConnectionRequiredFlagSet {
                    connection = .wifi
                    }

                    if isConnectionOnTrafficOrDemandFlagSet {
                    if !isInterventionRequiredFlagSet {
                    connection = .wifi
                    }
                    }

                    if isOnWWANFlagSet {
                    if !allowsCellularConnection {
                    connection = .none
                    } else {
                    connection = .cellular
                    }
                    }

                    return connection
                    }

                    fileprivate var previousFlags: SCNetworkReachabilityFlags?

                    fileprivate var isRunningOnDevice: Bool = {
                    #if targetEnvironment(simulator)
                    return false
                    #else
                    return true
                    #endif
                    }()

                    fileprivate var notifierRunning = false
                    fileprivate let reachabilityRef: SCNetworkReachability

                    fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")

                    fileprivate var usingHostname = false

                    required public init(reachabilityRef: SCNetworkReachability, usingHostname: Bool = false) {
                    allowsCellularConnection = true
                    self.reachabilityRef = reachabilityRef
                    self.usingHostname = usingHostname
                    }

                    public convenience init?(hostname: String) {
                    guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil }
                    self.init(reachabilityRef: ref, usingHostname: true)
                    }

                    public convenience init?() {
                    var zeroAddress = sockaddr()
                    zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
                    zeroAddress.sa_family = sa_family_t(AF_INET)

                    guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return nil }

                    self.init(reachabilityRef: ref)
                    }

                    deinit {
                    stopNotifier()
                    }
                    }

                    public extension Reachability {

                    // MARK: - *** Notifier methods ***
                    func startNotifier() throws {
                    guard !notifierRunning else { return }

                    var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
                    context.info = UnsafeMutableRawPointer(Unmanaged<Reachability>.passUnretained(self).toOpaque())
                    if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetCallback
                    }

                    if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetDispatchQueue
                    }

                    // Perform an initial check
                    reachabilitySerialQueue.async {
                    self.reachabilityChanged()
                    }

                    notifierRunning = true
                    }

                    func stopNotifier() {
                    defer { notifierRunning = false }

                    SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
                    SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
                    }

                    // MARK: - *** Connection test methods ***
                    @available(*, deprecated: 4.0, message: "Please use `connection != .none`")
                    var isReachable: Bool {
                    guard isReachableFlagSet else { return false }

                    if isConnectionRequiredAndTransientFlagSet {
                    return false
                    }

                    if isRunningOnDevice {
                    if isOnWWANFlagSet && !reachableOnWWAN {
                    // We don't want to connect when on cellular connection
                    return false
                    }
                    }

                    return true
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .cellular`")
                    var isReachableViaWWAN: Bool {
                    // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
                    return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .wifi`")
                    var isReachableViaWiFi: Bool {
                    // Check we're reachable
                    guard isReachableFlagSet else { return false }

                    // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return true }

                    // Check we're NOT on WWAN
                    return !isOnWWANFlagSet
                    }

                    var description: String {
                    let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X"
                    let R = isReachableFlagSet ? "R" : "-"
                    let c = isConnectionRequiredFlagSet ? "c" : "-"
                    let t = isTransientConnectionFlagSet ? "t" : "-"
                    let i = isInterventionRequiredFlagSet ? "i" : "-"
                    let C = isConnectionOnTrafficFlagSet ? "C" : "-"
                    let D = isConnectionOnDemandFlagSet ? "D" : "-"
                    let l = isLocalAddressFlagSet ? "l" : "-"
                    let d = isDirectFlagSet ? "d" : "-"

                    return "(W)(R) (c)(t)(i)(C)(D)(l)(d)"
                    }
                    }

                    fileprivate extension Reachability {
                    func reachabilityChanged() {
                    guard previousFlags != flags else { return }

                    let block = connection != .none ? whenReachable : whenUnreachable

                    DispatchQueue.main.async {
                    if self.usingHostname {
                    print("USING HOSTNAME ABOUT TO CALL BLOCK")
                    }
                    block?(self)
                    self.notificationCenter.post(name: .reachabilityChanged, object:self)
                    }

                    previousFlags = flags
                    }

                    var isOnWWANFlagSet: Bool {
                    #if os(iOS)
                    return flags.contains(.isWWAN)
                    #else
                    return false
                    #endif
                    }
                    var isReachableFlagSet: Bool {
                    return flags.contains(.reachable)
                    }
                    var isConnectionRequiredFlagSet: Bool {
                    return flags.contains(.connectionRequired)
                    }
                    var isInterventionRequiredFlagSet: Bool {
                    return flags.contains(.interventionRequired)
                    }
                    var isConnectionOnTrafficFlagSet: Bool {
                    return flags.contains(.connectionOnTraffic)
                    }
                    var isConnectionOnDemandFlagSet: Bool {
                    return flags.contains(.connectionOnDemand)
                    }
                    var isConnectionOnTrafficOrDemandFlagSet: Bool {
                    return !flags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
                    }
                    var isTransientConnectionFlagSet: Bool {
                    return flags.contains(.transientConnection)
                    }
                    var isLocalAddressFlagSet: Bool {
                    return flags.contains(.isLocalAddress)
                    }
                    var isDirectFlagSet: Bool {
                    return flags.contains(.isDirect)
                    }
                    var isConnectionRequiredAndTransientFlagSet: Bool {
                    return flags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]
                    }

                    var flags: SCNetworkReachabilityFlags {
                    var flags = SCNetworkReachabilityFlags()
                    if SCNetworkReachabilityGetFlags(reachabilityRef, &flags) {
                    print("Returning flags (flags)")
                    return flags
                    } else {
                    return SCNetworkReachabilityFlags()
                    }
                    }
                    }


                    If you want to use this inside your actual project then change the array of hostNames to:



                    let hostNames = ["google.com"] // or alibaba.com

                    // move it to viewWillAppear because the reachability class property gets set to nil in stopNotifier when it runs inside deinit
                    override func viewWillAppear(_ animated: Bool) {
                    super.viewWillAppear(animated)

                    startHost(at: 0)
                    }

                    // remove the dispatch async timer
                    func startHost(at index: Int) {
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()
                    }

                    // add everything else that's inside the ViewController File above





                    share|improve this answer















                    I followed this AshleyMills Reachability file and it uses google.com to test for a connection. You can just copy and paste the below inside a new file to test to see how it works. If your using this in China then use alibaba.com because google isn't available in China.



                    // everywhere outside China
                    let hostNames = [nil, "google.com", "invalidhost"]

                    // everywhere including China
                    let hostNames = [nil, "alibaba.com", "invalidhost"]


                    When you first launch the app you will see the labels change every 5 seconds because there is an async timer inside: func startHost(at index: Int)



                    If you want to stop it and take control of everything yourself then comment out this code:



                    // comment this out to stop the connection from changing
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    //self.startHost(at: (index + 1) % 3)
                    }


                    Once you comment that out then you should toggle your phones connection between Wifi, Cellular Connection, and Airplane Mode. The label colors will change from green to blue to red depending on the connection.



                    Create a new project and add this to the ViewController file:



                    import UIKit

                    class ViewController: UIViewController {

                    let networkStatus: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Status"
                    label.textAlignment = .center
                    return label
                    }()

                    let hostNameLabel: UILabel = {
                    let label = UILabel()
                    label.translatesAutoresizingMaskIntoConstraints = false
                    label.font = UIFont.systemFont(ofSize: 21)
                    label.textColor = .black
                    label.numberOfLines = 0
                    label.sizeToFit()
                    label.text = "Host"
                    label.textAlignment = .center
                    return label
                    }()

                    var reachability: Reachability?
                    let hostNames = [nil, "google.com", "invalidhost"]
                    var hostIndex = 0

                    override func viewDidLoad() {
                    super.viewDidLoad()

                    setConstraints()
                    startHost(at: 1)
                    }

                    func startHost(at index: Int) {
                    stopNotifier()
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()

                    // this loops the connection every 5 seconds
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                    self.startHost(at: (index + 1) % 3)
                    }
                    }

                    func setupReachability(_ hostName: String?, useClosures: Bool) {
                    let reachability: Reachability?
                    if let hostName = hostName {
                    reachability = Reachability(hostname: hostName)
                    hostNameLabel.text = hostName
                    } else {
                    reachability = Reachability()
                    hostNameLabel.text = "No host name"
                    }
                    self.reachability = reachability
                    print("--- set up with host name: (hostNameLabel.text!)")

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

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

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

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

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    self.networkStatus.textColor = .red

                    self.networkStatus.text = "(reachability.connection)"
                    }

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

                    if reachability.connection != .none {
                    updateLabelColourWhenReachable(reachability)
                    } else {
                    updateLabelColourWhenNotReachable(reachability)
                    }
                    }

                    func setConstraints(){
                    view.addSubview(networkStatus)
                    view.addSubview(hostNameLabel)

                    networkStatus.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    networkStatus.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    networkStatus.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

                    hostNameLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8).isActive = true
                    hostNameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8).isActive = true
                    hostNameLabel.topAnchor.constraint(equalTo: networkStatus.bottomAnchor, constant: 20).isActive = true
                    }

                    deinit {
                    stopNotifier()
                    }
                    }


                    Create a File named Reachability and add this to it:



                    import SystemConfiguration
                    import Foundation

                    public enum ReachabilityError: Error {
                    case FailedToCreateWithAddress(sockaddr_in)
                    case FailedToCreateWithHostname(String)
                    case UnableToSetCallback
                    case UnableToSetDispatchQueue
                    }

                    @available(*, unavailable, renamed: "Notification.Name.reachabilityChanged")
                    public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification")

                    extension Notification.Name {
                    public static let reachabilityChanged = Notification.Name("reachabilityChanged")
                    }

                    func callback(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
                    guard let info = info else { return }

                    let reachability = Unmanaged<Reachability>.fromOpaque(info).takeUnretainedValue()
                    reachability.reachabilityChanged()
                    }

                    public class Reachability {

                    public typealias NetworkReachable = (Reachability) -> ()
                    public typealias NetworkUnreachable = (Reachability) -> ()

                    @available(*, unavailable, renamed: "Connection")
                    public enum NetworkStatus: CustomStringConvertible {
                    case notReachable, reachableViaWiFi, reachableViaWWAN
                    public var description: String {
                    switch self {
                    case .reachableViaWWAN: return "Cellular"
                    case .reachableViaWiFi: return "WiFi"
                    case .notReachable: return "No Connection"
                    }
                    }
                    }

                    public enum Connection: CustomStringConvertible {
                    case none, wifi, cellular
                    public var description: String {
                    switch self {
                    case .cellular: return "Cellular"
                    case .wifi: return "WiFi"
                    case .none: return "No Connection"
                    }
                    }
                    }

                    public var whenReachable: NetworkReachable?
                    public var whenUnreachable: NetworkUnreachable?

                    @available(*, deprecated: 4.0, renamed: "allowsCellularConnection")
                    public let reachableOnWWAN: Bool = true

                    /// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`)
                    public var allowsCellularConnection: Bool

                    // The notification center on which "reachability changed" events are being posted
                    public var notificationCenter: NotificationCenter = NotificationCenter.default

                    @available(*, deprecated: 4.0, renamed: "connection.description")
                    public var currentReachabilityString: String {
                    return "(connection)"
                    }

                    @available(*, unavailable, renamed: "connection")
                    public var currentReachabilityStatus: Connection {
                    return connection
                    }

                    public var connection: Connection {
                    guard isReachableFlagSet else { return .none }

                    // If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return .wifi }

                    var connection = Connection.none

                    if !isConnectionRequiredFlagSet {
                    connection = .wifi
                    }

                    if isConnectionOnTrafficOrDemandFlagSet {
                    if !isInterventionRequiredFlagSet {
                    connection = .wifi
                    }
                    }

                    if isOnWWANFlagSet {
                    if !allowsCellularConnection {
                    connection = .none
                    } else {
                    connection = .cellular
                    }
                    }

                    return connection
                    }

                    fileprivate var previousFlags: SCNetworkReachabilityFlags?

                    fileprivate var isRunningOnDevice: Bool = {
                    #if targetEnvironment(simulator)
                    return false
                    #else
                    return true
                    #endif
                    }()

                    fileprivate var notifierRunning = false
                    fileprivate let reachabilityRef: SCNetworkReachability

                    fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")

                    fileprivate var usingHostname = false

                    required public init(reachabilityRef: SCNetworkReachability, usingHostname: Bool = false) {
                    allowsCellularConnection = true
                    self.reachabilityRef = reachabilityRef
                    self.usingHostname = usingHostname
                    }

                    public convenience init?(hostname: String) {
                    guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil }
                    self.init(reachabilityRef: ref, usingHostname: true)
                    }

                    public convenience init?() {
                    var zeroAddress = sockaddr()
                    zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
                    zeroAddress.sa_family = sa_family_t(AF_INET)

                    guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return nil }

                    self.init(reachabilityRef: ref)
                    }

                    deinit {
                    stopNotifier()
                    }
                    }

                    public extension Reachability {

                    // MARK: - *** Notifier methods ***
                    func startNotifier() throws {
                    guard !notifierRunning else { return }

                    var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
                    context.info = UnsafeMutableRawPointer(Unmanaged<Reachability>.passUnretained(self).toOpaque())
                    if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetCallback
                    }

                    if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
                    stopNotifier()
                    throw ReachabilityError.UnableToSetDispatchQueue
                    }

                    // Perform an initial check
                    reachabilitySerialQueue.async {
                    self.reachabilityChanged()
                    }

                    notifierRunning = true
                    }

                    func stopNotifier() {
                    defer { notifierRunning = false }

                    SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
                    SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
                    }

                    // MARK: - *** Connection test methods ***
                    @available(*, deprecated: 4.0, message: "Please use `connection != .none`")
                    var isReachable: Bool {
                    guard isReachableFlagSet else { return false }

                    if isConnectionRequiredAndTransientFlagSet {
                    return false
                    }

                    if isRunningOnDevice {
                    if isOnWWANFlagSet && !reachableOnWWAN {
                    // We don't want to connect when on cellular connection
                    return false
                    }
                    }

                    return true
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .cellular`")
                    var isReachableViaWWAN: Bool {
                    // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
                    return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet
                    }

                    @available(*, deprecated: 4.0, message: "Please use `connection == .wifi`")
                    var isReachableViaWiFi: Bool {
                    // Check we're reachable
                    guard isReachableFlagSet else { return false }

                    // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
                    guard isRunningOnDevice else { return true }

                    // Check we're NOT on WWAN
                    return !isOnWWANFlagSet
                    }

                    var description: String {
                    let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X"
                    let R = isReachableFlagSet ? "R" : "-"
                    let c = isConnectionRequiredFlagSet ? "c" : "-"
                    let t = isTransientConnectionFlagSet ? "t" : "-"
                    let i = isInterventionRequiredFlagSet ? "i" : "-"
                    let C = isConnectionOnTrafficFlagSet ? "C" : "-"
                    let D = isConnectionOnDemandFlagSet ? "D" : "-"
                    let l = isLocalAddressFlagSet ? "l" : "-"
                    let d = isDirectFlagSet ? "d" : "-"

                    return "(W)(R) (c)(t)(i)(C)(D)(l)(d)"
                    }
                    }

                    fileprivate extension Reachability {
                    func reachabilityChanged() {
                    guard previousFlags != flags else { return }

                    let block = connection != .none ? whenReachable : whenUnreachable

                    DispatchQueue.main.async {
                    if self.usingHostname {
                    print("USING HOSTNAME ABOUT TO CALL BLOCK")
                    }
                    block?(self)
                    self.notificationCenter.post(name: .reachabilityChanged, object:self)
                    }

                    previousFlags = flags
                    }

                    var isOnWWANFlagSet: Bool {
                    #if os(iOS)
                    return flags.contains(.isWWAN)
                    #else
                    return false
                    #endif
                    }
                    var isReachableFlagSet: Bool {
                    return flags.contains(.reachable)
                    }
                    var isConnectionRequiredFlagSet: Bool {
                    return flags.contains(.connectionRequired)
                    }
                    var isInterventionRequiredFlagSet: Bool {
                    return flags.contains(.interventionRequired)
                    }
                    var isConnectionOnTrafficFlagSet: Bool {
                    return flags.contains(.connectionOnTraffic)
                    }
                    var isConnectionOnDemandFlagSet: Bool {
                    return flags.contains(.connectionOnDemand)
                    }
                    var isConnectionOnTrafficOrDemandFlagSet: Bool {
                    return !flags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
                    }
                    var isTransientConnectionFlagSet: Bool {
                    return flags.contains(.transientConnection)
                    }
                    var isLocalAddressFlagSet: Bool {
                    return flags.contains(.isLocalAddress)
                    }
                    var isDirectFlagSet: Bool {
                    return flags.contains(.isDirect)
                    }
                    var isConnectionRequiredAndTransientFlagSet: Bool {
                    return flags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]
                    }

                    var flags: SCNetworkReachabilityFlags {
                    var flags = SCNetworkReachabilityFlags()
                    if SCNetworkReachabilityGetFlags(reachabilityRef, &flags) {
                    print("Returning flags (flags)")
                    return flags
                    } else {
                    return SCNetworkReachabilityFlags()
                    }
                    }
                    }


                    If you want to use this inside your actual project then change the array of hostNames to:



                    let hostNames = ["google.com"] // or alibaba.com

                    // move it to viewWillAppear because the reachability class property gets set to nil in stopNotifier when it runs inside deinit
                    override func viewWillAppear(_ animated: Bool) {
                    super.viewWillAppear(animated)

                    startHost(at: 0)
                    }

                    // remove the dispatch async timer
                    func startHost(at index: Int) {
                    setupReachability(hostNames[index], useClosures: true)
                    startNotifier()
                    }

                    // add everything else that's inside the ViewController File above






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 13 '18 at 15:34

























                    answered Oct 11 '17 at 15:18









                    Lance SamariaLance Samaria

                    2,52921451




                    2,52921451













                    • Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

                      – IvanMih
                      Oct 12 '17 at 8:15











                    • @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

                      – Lance Samaria
                      Oct 12 '17 at 10:56













                    • @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

                      – Lance Samaria
                      Oct 12 '17 at 11:13











                    • one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

                      – IvanMih
                      Oct 12 '17 at 13:01






                    • 1





                      @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

                      – Lance Samaria
                      Oct 12 '17 at 20:32



















                    • Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

                      – IvanMih
                      Oct 12 '17 at 8:15











                    • @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

                      – Lance Samaria
                      Oct 12 '17 at 10:56













                    • @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

                      – Lance Samaria
                      Oct 12 '17 at 11:13











                    • one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

                      – IvanMih
                      Oct 12 '17 at 13:01






                    • 1





                      @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

                      – Lance Samaria
                      Oct 12 '17 at 20:32

















                    Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

                    – IvanMih
                    Oct 12 '17 at 8:15





                    Lance thanks for trying to help. I would like some clarification, especially because i think that none of the answers actually answer your question. Your use case is: "For e.g.. if I have a wifi router and it's plugged in but the router isn't connected to the internet Alamofire will view this as a successful connection because it actually is connecting to wifi although it doesn't know the wifi can't connect to the internet." This is what you've stated, and if you try the code from youtube link and change Alamofire with Reachability, it doesn't answer the question.

                    – IvanMih
                    Oct 12 '17 at 8:15













                    @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

                    – Lance Samaria
                    Oct 12 '17 at 10:56







                    @IvanMih I haven't had any problems with the code from the YouTube video. I've connected to wifi, received no data, and the Ashly Mills reachability showed no connection. Is the YouTube code not working in the way I just described? As for the accepted answer, the reason I picked it was because he was correct in saying connect to a site like google that is guaranteed to always be reachable, if not, then there's a problem. His explanation of how to use it wasn't clear but he was correct.

                    – Lance Samaria
                    Oct 12 '17 at 10:56















                    @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

                    – Lance Samaria
                    Oct 12 '17 at 11:13





                    @IvanMih Ivan I did some googling around, check this answer. I'm in the US and what I didn't realize or think about is if you try to ping google in countries that don't support it like China then it won't work. Also if your on 2G there may be an issue. stackoverflow.com/questions/24516748/… . I'll do more research into the different answers and get back to to you. If you find something more concrete let me know, post the answer, and I'll upvote you. If I find it I'll post it for you

                    – Lance Samaria
                    Oct 12 '17 at 11:13













                    one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

                    – IvanMih
                    Oct 12 '17 at 13:01





                    one thing between our tests could be different: I was using another phone's hotspot and turned mobile data on and off on that other phone. Later i'll try with a router. I really don't think there should be any difference in the outcome, but who knows. I've made a test project with reachability test + simple ping test (another approach in solving this problem). If you'd like to take a look, and correct me if you see some mistakes: github.com/ivanmih/NetworkTest. And i'm in Europe so i have access to google.

                    – IvanMih
                    Oct 12 '17 at 13:01




                    1




                    1





                    @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

                    – Lance Samaria
                    Oct 12 '17 at 20:32





                    @IvanMih I'm going to an iOS meetup next Wed. There are experts there. I'm not sure how fast you need an answer but I should be able to get some on hands help there.

                    – Lance Samaria
                    Oct 12 '17 at 20:32











                    0














                    I was facing the same issue so with the help of some answers on stackoverflow i created a code that simply hit google.com asynchronously and return true in completion handler if response status is 200.



                    Code in Swift 4:



                    class func checkInternet(showLoader: Bool = true, completionHandler:@escaping (_ internet:Bool) -> Void)
                    {
                    UIApplication.shared.isNetworkActivityIndicatorVisible = true

                    let url = URL(string: "http://www.google.com/")
                    var req = URLRequest.init(url: url!)
                    req.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData
                    req.timeoutInterval = 10.0

                    if showLoader {
                    Loader.startLoading()
                    }
                    let task = URLSession.shared.dataTask(with: req) { (data, response, error) in

                    if showLoader {
                    Loader.stopLoading()
                    }

                    if error != nil {
                    completionHandler(false)
                    } else {
                    if let httpResponse = response as? HTTPURLResponse {
                    if httpResponse.statusCode == 200 {
                    completionHandler(true)
                    } else {
                    completionHandler(false)
                    }
                    } else {
                    completionHandler(false)
                    }
                    }
                    }
                    task.resume()
                    }


                    Now you can use it like:



                         InternetCheck.checkInternet(completionHandler: { (available) in
                    if available {
                    print("Net available")
                    } else {
                    print("Net not available")
                    }





                    share|improve this answer


























                    • you should post an example on how to use it

                      – Lance Samaria
                      Jan 4 at 20:13











                    • added usage example code.

                      – Ammar Mujeeb
                      Jan 9 at 7:36













                    • cool thanks for adding it 😊

                      – Lance Samaria
                      Jan 9 at 7:37
















                    0














                    I was facing the same issue so with the help of some answers on stackoverflow i created a code that simply hit google.com asynchronously and return true in completion handler if response status is 200.



                    Code in Swift 4:



                    class func checkInternet(showLoader: Bool = true, completionHandler:@escaping (_ internet:Bool) -> Void)
                    {
                    UIApplication.shared.isNetworkActivityIndicatorVisible = true

                    let url = URL(string: "http://www.google.com/")
                    var req = URLRequest.init(url: url!)
                    req.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData
                    req.timeoutInterval = 10.0

                    if showLoader {
                    Loader.startLoading()
                    }
                    let task = URLSession.shared.dataTask(with: req) { (data, response, error) in

                    if showLoader {
                    Loader.stopLoading()
                    }

                    if error != nil {
                    completionHandler(false)
                    } else {
                    if let httpResponse = response as? HTTPURLResponse {
                    if httpResponse.statusCode == 200 {
                    completionHandler(true)
                    } else {
                    completionHandler(false)
                    }
                    } else {
                    completionHandler(false)
                    }
                    }
                    }
                    task.resume()
                    }


                    Now you can use it like:



                         InternetCheck.checkInternet(completionHandler: { (available) in
                    if available {
                    print("Net available")
                    } else {
                    print("Net not available")
                    }





                    share|improve this answer


























                    • you should post an example on how to use it

                      – Lance Samaria
                      Jan 4 at 20:13











                    • added usage example code.

                      – Ammar Mujeeb
                      Jan 9 at 7:36













                    • cool thanks for adding it 😊

                      – Lance Samaria
                      Jan 9 at 7:37














                    0












                    0








                    0







                    I was facing the same issue so with the help of some answers on stackoverflow i created a code that simply hit google.com asynchronously and return true in completion handler if response status is 200.



                    Code in Swift 4:



                    class func checkInternet(showLoader: Bool = true, completionHandler:@escaping (_ internet:Bool) -> Void)
                    {
                    UIApplication.shared.isNetworkActivityIndicatorVisible = true

                    let url = URL(string: "http://www.google.com/")
                    var req = URLRequest.init(url: url!)
                    req.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData
                    req.timeoutInterval = 10.0

                    if showLoader {
                    Loader.startLoading()
                    }
                    let task = URLSession.shared.dataTask(with: req) { (data, response, error) in

                    if showLoader {
                    Loader.stopLoading()
                    }

                    if error != nil {
                    completionHandler(false)
                    } else {
                    if let httpResponse = response as? HTTPURLResponse {
                    if httpResponse.statusCode == 200 {
                    completionHandler(true)
                    } else {
                    completionHandler(false)
                    }
                    } else {
                    completionHandler(false)
                    }
                    }
                    }
                    task.resume()
                    }


                    Now you can use it like:



                         InternetCheck.checkInternet(completionHandler: { (available) in
                    if available {
                    print("Net available")
                    } else {
                    print("Net not available")
                    }





                    share|improve this answer















                    I was facing the same issue so with the help of some answers on stackoverflow i created a code that simply hit google.com asynchronously and return true in completion handler if response status is 200.



                    Code in Swift 4:



                    class func checkInternet(showLoader: Bool = true, completionHandler:@escaping (_ internet:Bool) -> Void)
                    {
                    UIApplication.shared.isNetworkActivityIndicatorVisible = true

                    let url = URL(string: "http://www.google.com/")
                    var req = URLRequest.init(url: url!)
                    req.cachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData
                    req.timeoutInterval = 10.0

                    if showLoader {
                    Loader.startLoading()
                    }
                    let task = URLSession.shared.dataTask(with: req) { (data, response, error) in

                    if showLoader {
                    Loader.stopLoading()
                    }

                    if error != nil {
                    completionHandler(false)
                    } else {
                    if let httpResponse = response as? HTTPURLResponse {
                    if httpResponse.statusCode == 200 {
                    completionHandler(true)
                    } else {
                    completionHandler(false)
                    }
                    } else {
                    completionHandler(false)
                    }
                    }
                    }
                    task.resume()
                    }


                    Now you can use it like:



                         InternetCheck.checkInternet(completionHandler: { (available) in
                    if available {
                    print("Net available")
                    } else {
                    print("Net not available")
                    }






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 9 at 7:34

























                    answered Jan 1 at 5:10









                    Ammar MujeebAmmar Mujeeb

                    6071017




                    6071017













                    • you should post an example on how to use it

                      – Lance Samaria
                      Jan 4 at 20:13











                    • added usage example code.

                      – Ammar Mujeeb
                      Jan 9 at 7:36













                    • cool thanks for adding it 😊

                      – Lance Samaria
                      Jan 9 at 7:37



















                    • you should post an example on how to use it

                      – Lance Samaria
                      Jan 4 at 20:13











                    • added usage example code.

                      – Ammar Mujeeb
                      Jan 9 at 7:36













                    • cool thanks for adding it 😊

                      – Lance Samaria
                      Jan 9 at 7:37

















                    you should post an example on how to use it

                    – Lance Samaria
                    Jan 4 at 20:13





                    you should post an example on how to use it

                    – Lance Samaria
                    Jan 4 at 20:13













                    added usage example code.

                    – Ammar Mujeeb
                    Jan 9 at 7:36







                    added usage example code.

                    – Ammar Mujeeb
                    Jan 9 at 7:36















                    cool thanks for adding it 😊

                    – Lance Samaria
                    Jan 9 at 7:37





                    cool thanks for adding it 😊

                    – Lance Samaria
                    Jan 9 at 7:37


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f43067753%2fswift-ios-what-to-do-when-there-is-a-wifi-connection-but-no-internet-connection%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith