Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if WiFi is on or off in iOS Swift 2?

Tags:

ios

swift

I want to check if the wifi is off then show alert to the user to check his/her connectivity.

I find code like this but it checks if there is an internet connection, not checking if the wifi is on or off:

func isConnectionAvailble()->Bool{

  var rechability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, "www.apple.com").takeRetainedValue()

  var flags : SCNetworkReachabilityFlags = 0

  if SCNetworkReachabilityGetFlags(rechability, &flags) == 0
  {
     return false
  }

  let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
  let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
  return (isReachable && !needsConnection)
}
like image 475
Mohammed Saleh Avatar asked Oct 04 '16 10:10

Mohammed Saleh


4 Answers

You can't.

With Apple's reachability class, you can distinguish three things according to the NetworkStatus struct:

typedef enum : NSInteger {
  NotReachable = 0,         // 1
  ReachableViaWiFi,         // 2
  ReachableViaWWAN          // 3
} NetworkStatus;
  1. You have neither WiFi nor mobile data connection.
  2. You have a WiFi connection, but you may or may not have a mobile data connection.
  3. You have a mobile data connection, but no WiFi connection.

You can't check whether WiFi is turned off, or whether WiFi is turned on but there is no WiFi network nearby, or whether Airplane mode has been turned on.

For mobile data, you can use the telephony class to find whether your device is capable of mobile data connections (iPhone and not iPad, and SIM card plugged in), and you can detect whether mobile data is disabled in the preferences of your application.

like image 159
gnasher729 Avatar answered Oct 12 '22 05:10

gnasher729


Found the following, which was really helpful for me (found on the Apple Developer Forums). The below code works with Swift 4.

func fetchSSIDInfo() ->  String {  
    var currentSSID = ""  
    if let interfaces:CFArray = 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 unsafeInterfaceData != nil {  
                let interfaceData = unsafeInterfaceData! as Dictionary!  
                for dictData in interfaceData! {  
                    if dictData.key as! String == "SSID" {  
                        currentSSID = dictData.value as! String  
                    }  
                }  
            }  
        }  
    }  
    return currentSSID  
}  

You can then check if a device is connected to Wi-Fi by the following:

if fetchSSIDInfo() != nil { 
    /* Wi-Fi is Connected */ 
}

Not perfect, but if the device is not connected to a Wi-Fi Network, you could then ask the user to connect to a Wi-Fi Network:

let wifiNotifcation = UIAlertController(title: "Please Connect to Wi-Fi", message: "Please connect to your standard Wi-Fi Network", preferredStyle: .alert)
wifiNotifcation.addAction(UIAlertAction(title: "Open Wi-Fi", style: .default, handler: { (nil) in
     let url = URL(string: "App-Prefs:root=WIFI")

     if UIApplication.shared.canOpenURL(url!){
           UIApplication.shared.openURL(url!)
           self.navigationController?.popViewController(animated: false)
     }
}))
self.present(wifiNotifcation, animated: true, completion: nil)
like image 38
abba_de_bo Avatar answered Oct 12 '22 06:10

abba_de_bo


Tested with swift 4 and swift 5

let nwPathMonitor = NWPathMonitor()
nwPathMonitor.pathUpdateHandler = { path in

    if path.usesInterfaceType(.wifi) {
        print("Path is Wi-Fi")
    } else if path.usesInterfaceType(.cellular) {
            print("Path is Cellular")
    } else if path.usesInterfaceType(.wiredEthernet) {
            print("Path is Wired Ethernet")
    } else if path.usesInterfaceType(.loopback) {
            print("Path is Loopback")
    } else if path.usesInterfaceType(.other) {
            print("Path is other")
    }
}

nwPathMonitor.start(queue: .main)
like image 28
Benjamin RD Avatar answered Oct 12 '22 04:10

Benjamin RD


As already @abba_de_bo mentioned: you could fetch the current SSID and check if it's set or nil.

This is the answer Apple's Eskimo gave to this question:

The trick with using CF-based APIs from Swift is to get the data into ‘Swift space’ as quickly as possible.

func currentSSIDs() -> [String] {  
  guard let interfaceNames = CNCopySupportedInterfaces() as? [String] else {  
    return []  
  } 

  return interfaceNames.flatMap { name in  

    guard let info = CNCopyCurrentNetworkInfo(name as CFString) as? [String:AnyObject] else {  
      return nil  
    }  
    guard let ssid = info[kCNNetworkInfoKeySSID as String] as? String else {  
      return nil  
    }  

    return ssid  
  }  
}

Note that this returns an array of names; how you handle the non-standard cases (no elements, more than one element) is up to you.

Make sure you import SystemConfiguration.CaptiveNetwork. Otherwise the build will fail with on of those error messages:

  • Use of unresolved identifier 'CNCopySupportedInterfaces'
  • Use of unresolved identifier 'CNCopyCurrentNetworkInfo'
  • Use of unresolved identifier 'kCNNetworkInfoKeySSID'
like image 34
winklerrr Avatar answered Oct 12 '22 06:10

winklerrr