53

For iOS 9 I was using Reachability public class to check wether the device is connected to the internet or not. I converted my Swift 2 code to Swift 3, and the Reachability doesn't work anymore. Can someone tell me how to check the internet connection on iOS 10? Thanks! Here's the code snippet:

open class Reachability {
    class func isConnectedToNetwork() -> Bool {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }
        var flags = SCNetworkReachabilityFlags()
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
            return false
        }
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        return (isReachable && !needsConnection)
    }
}
ddb
  • 2,423
  • 7
  • 28
  • 38
LOLXDXPLOL
  • 611
  • 1
  • 6
  • 9
  • 1
    see http://stackoverflow.com/questions/39046377/swift-3-unsafepointer0-no-longer-compile-in-xcode-8-beta-6 – MartinMcB Sep 18 '16 at 15:18
  • 2
    Please note that http://stackoverflow.com/questions/25623272/how-to-use-scnetworkreachability-in-swift/25623647#25623647 has been updated for Swift 3. – Martin R Sep 18 '16 at 15:20
  • I think this will help you with your Q: http://stackoverflow.com/a/39783037/4301118 – sharon Oct 18 '16 at 06:51
  • See alamofire answer - https://stackoverflow.com/a/46562290/7576100 – Jack Oct 04 '17 at 11:04

12 Answers12

112
import Foundation
import SystemConfiguration

func isInternetAvailable() -> Bool
    {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }

        var flags = SCNetworkReachabilityFlags()
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
            return false
        }
        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        return (isReachable && !needsConnection)
    }

This works in iOS 10

Alexander Vasenin
  • 11,437
  • 4
  • 42
  • 70
Adnan T.
  • 1,166
  • 1
  • 8
  • 8
  • 2
    this answer is good but not enough. if you will use this function, you must import SystemConfiguration – Phd. Burak Öztürk Jan 07 '17 at 21:45
  • 7
    If you are connected to a wi-fi but not able to connect to the internet (open a google page) still it returns true for reachable. It's wrong. – Arildo Junior Feb 02 '17 at 18:56
  • 4
    This returns "true" when connected to the WiFi without the Internet, which is a problem for my case. – Pavle Mijatovic Mar 10 '17 at 09:14
  • 1
    @PavleMijatovic so what is the solution to this problem ( returns "true" when connected to the WiFi without the Internet)? If you found out, please let me know as well. – Tejas Jun 27 '17 at 10:48
  • @Tejas, here is how I implemented inside my code, I just pinged a site if I am on WiFi. You have down below my implementation. – Pavle Mijatovic Jul 26 '17 at 10:03
  • @PavleMijatovic : Ok, Thank You! :) – Tejas Jul 26 '17 at 10:14
  • But Apple says that Reachability API MUST only be used for diagnostic purposes. Proactive network check using Reachability is ill advised. Instead Apple wants you to handle it through exception Handling mechanism. – Anjan Biswas Nov 06 '17 at 01:13
63

SWIFT 3.0: Here's very simple way to do it:

import SystemConfiguration


protocol Utilities {
}

extension NSObject:Utilities{


    enum ReachabilityStatus {
        case notReachable
        case reachableViaWWAN
        case reachableViaWiFi
    }

    var currentReachabilityStatus: ReachabilityStatus {

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

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

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

        if flags.contains(.reachable) == false {
            // The target host is not reachable.
            return .notReachable
        }
        else if flags.contains(.isWWAN) == true {
            // WWAN connections are OK if the calling application is using the CFNetwork APIs.
            return .reachableViaWWAN
        }
        else if flags.contains(.connectionRequired) == false {
            // If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi...
            return .reachableViaWiFi
        }
        else if (flags.contains(.connectionOnDemand) == true || flags.contains(.connectionOnTraffic) == true) && flags.contains(.interventionRequired) == false {
            // The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed
            return .reachableViaWiFi
        } 
        else {
            return .notReachable
        }
    }

}

and then simply you can use it anywhere in your project for example:

  func viewDidLoad(){
      print(currentReachabilityStatus != .notReachable) //true connected
    }
Jad
  • 2,139
  • 1
  • 16
  • 28
11

Try this, it works for me first import the SystemConfiguration to your class.

import SystemConfiguration

And now implement bellow function.

func isConnectedToNetwork() -> Bool {

    var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)
    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }

    var flags = SCNetworkReachabilityFlags()
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
        return false
    }
    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0

    return (isReachable && !needsConnection)

}
Patel Jigar
  • 2,141
  • 1
  • 23
  • 30
  • It appears there is a flaw in this code. Checking for flags with == doesn't work properly. – ryantxr Dec 27 '16 at 15:34
  • dear @ryantxr this code works properly for me, i hope u are using swift 3.0, and if you find the better solution for this, then you can put it here, please dont downmark the answer – Patel Jigar Dec 28 '16 at 05:10
  • 1
    You can fix it with `flags.contains(.reachable)` and `flags.contains(.connectionRequired)`. Yes I am using Swift 3. – ryantxr Dec 29 '16 at 01:24
  • 3
    If you are connected to a wi-fi but not able to connect to the internet (open a google page) still it returns true for reachable. It's wrong. – Arildo Junior Feb 02 '17 at 18:54
  • This code is giving me a problem. Its works properly for WiFi but if I connect using cellular data and check, it says no internet even though the internet is available. – miOS May 03 '17 at 06:55
  • @ArildoJunior Make a response data check. Like if the response data is nil, then you're offline. – Codetard Sep 14 '17 at 12:23
8

step 1 : create a swift file in your project. i created "ConnectionCheck.swift"

step 2 : add this code in your "ConnectionCheck.swift" file and "import SystemConfiguration" file to your "ConnectionCheck.swift" and "ViewController.swift"

import Foundation
import SystemConfiguration
public class ConnectionCheck {

class func isConnectedToNetwork() -> Bool {

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

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

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

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

    return (isReachable && !needsConnection)
}

}

step 3 : Now in "ViewController.swift" use this code to check Network Reachability

if ConnectionCheck.isConnectedToNetwork() {
        print("Connected")
    }
    else{
        print("disConnected")
    }
Krutagn Patel
  • 99
  • 1
  • 4
  • If I submit my app to apple, do I need to change any code in order to pass apple verification? – Eric Chong Aug 08 '17 at 01:22
  • 1
    @LOLXDXPLOL yes, we can see... But SO work with multiple answer so others can see different version and maybe, just maybe, a better solution shows up... I'm trying to remain polite. – Byron Coetsee Oct 20 '17 at 11:57
  • @ByronCoetsee sorry, I didn’t want to sound impolite, I just didn’t think of it that way. Thanks! – LOLXDXPLOL Oct 20 '17 at 12:01
4

This code would be helpful for you. it worked for me in Swift 4 and Xcode 9

Go to https://github.com/ashleymills/Reachability.swift/tree/master/Reachability and copy Reachability.swift file to your project

Vasil Nunev clearly explain this Reachability https://www.youtube.com/watch?v=wDZmz9IsB-8

class ViewController: UIViewController {

   let reachability = Reachability();
    override func viewDidLoad() {
        super.viewDidLoad()

        reachability?.whenReachable = { _ in

            DispatchQueue.main.async {
                self.view.backgroundColor = UIColor.green
            }
        }

        reachability?.whenUnreachable = { _ in
            DispatchQueue.main.async {
                self.view.backgroundColor = UIColor.red
            }
        }
        NotificationCenter.default.addObserver(self, selector: #selector(internetChanged), name: Notification.Name.reachabilityChanged , object: reachability)
        do{

            try reachability?.startNotifier()
        }catch{
            print("Could not start notifier:\(error)")
        }

    }

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

        if reachability.connection != .none {

            if reachability.connection == .wifi{
                DispatchQueue.main.async {
                    self.view.backgroundColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1)
                }
            }else if reachability.connection == .cellular{
                DispatchQueue.main.async {
                    self.view.backgroundColor = #colorLiteral(red: 0.3647058904, green: 0.06666667014, blue: 0.9686274529, alpha: 1)
                }
            }
        }else{
            DispatchQueue.main.async {
                self.view.backgroundColor = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)
            }
        }
    }
}
Junaid Ali
  • 175
  • 1
  • 2
  • 14
  • Thanks but I’ve had a working answer a long time ago – LOLXDXPLOL Oct 18 '17 at 06:22
  • Does this method work for cellular data as well as wifi? And does it distinguish between simply being connected to wifi and being connect to wifi *with* internet connection? – Runeaway3 Nov 01 '17 at 01:53
  • This code is not working for me. I dont know what am I doing wrong. It return true and then false when you get in network. – iOS_Developer Nov 02 '17 at 16:07
3

Here is Swift 3 solution via callback function, isConnectedToNetwork() is taken from the solution by Yasin Ugurlu from above.

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
    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()
  }
Pavle Mijatovic
  • 773
  • 10
  • 6
  • your answer looks good and your comment above about the accepted answer connecting to wifi but no internet is correct. How do you call your function and use it inside a view controller? Please show an example – Lance Samaria Feb 23 '18 at 06:08
1

Swift 4 / Xcode 10:

I would combine two functions ( with a bit changes) are taken from the solutions by @Pavle Mijatovic and @Krutagn Patel (with thanks) to answer @Lance Samaria question. :)

I almost checked all the possibilities. (the code can be enhanced, but it works fine)

have a class as below:

import Foundation
import SystemConfiguration

public class ConnectionCheck {

    class func isConnectedToNetwork() -> Bool {

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

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

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

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

        return (isReachable && !needsConnection)
    }


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

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

        // 2. Check the Internet Connection
        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()
    }
}

use the below code where you need to check the Internet connection: for example, in appDelegate -> applicationDidBecomeActive function.

explanation: whenever completionHandler function (above) is called, the result (true or false) is passed to the below code as b. so if b is true you have the Internet connection.

let web : String? = "https://www.google.com"
ConnectionCheck.isInternetAvailable(webSiteToPing: web) { (b)  in
 print(b)
if b {
print("connected") // or do something here
    } else {
print("disconnected") // or do something here
}
}
FRIDDAY
  • 3,781
  • 1
  • 29
  • 43
0

You can use in swift 3

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(sizeofValue(zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

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

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

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

        return isReachable && !needsConnection

    }
}
Yasin Ugurlu
  • 691
  • 5
  • 11
0

1) Create a new Swift file within your project, name it “Reachability.swift”.

2) Cut & paste the following code into it to create your class.

import Foundation
import SystemConfiguration

public class Reachability {

class func isConnectedToNetwork() -> Bool {

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

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

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

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

    return isReachable && !needsConnection

     }
}

3) You can check internet connection anywhere in your project using this code:

 if Reachability.isConnectedToNetwork() == true {
println("Internet connection OK")
} else {
println("Internet connection FAILED")
}

4)If the user is not connected to the internet, you may want to show them an alert dialog to notify them.

if Reachability.isConnectedToNetwork() == true {
println("Internet connection OK")
} else {
println("Internet connection FAILED")
var alert = UIAlertView(title: "No Internet Connection", message: "Make sure your 
 device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
Sahil Omer
  • 163
  • 9
0

Swift 4/Xcode 9+ (make Reachability.swift file):

public class Reachability {

    class func isConnectedToNetwork() -> Bool {

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

        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }

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

        // Working for Cellular and WIFI
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        let ret = (isReachable && !needsConnection)

        return ret

    }
}

usage:

if Reachability.isConnectedToNetwork() {
// connected, do something
}
itsmcgh
  • 783
  • 1
  • 9
  • 12
0
  1. Create a Swift file within your project, name it: Reachability.swift". then paste below code in this Reachability.swift file:-

    import Foundation
    
    import SystemConfiguration
    
    public class Reachability {
    
        class func isConnectedToNetwork() -> Bool {
    
            var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
            zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
            zeroAddress.sin_family = sa_family_t(AF_INET)
    
            let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
                SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0))
            }
    
            var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
            if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
                return false
            }
    
            let isReachable = flags == .Reachable
            let needsConnection = flags == .ConnectionRequired
    
            return isReachable && !needsConnection
    
        }
    }
    

Then you can check the internet anywhere in the project using below code

  if Reachability.isConnectedToNetwork() == true {
        println("Internet connection OK")
    } else {
        println("Internet connection FAILED")
    }
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Harshit
  • 107
  • 1
  • 6
0

Another solution for Swift 4.0. Not a big fan o IUO rather use a guard

 func isConnectedToNetwork() -> Bool {
    var zeroAddress = sockaddr_in()
    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 == .reachable
    let needsConnection = flags == .connectionRequired
    return isReachable && !needsConnection
}
apinho
  • 2,235
  • 3
  • 25
  • 39