Check for internet connection availability in Swift

IosSwiftNetwork Connection

Ios Problem Overview


Is there a way to check if the internet connection is available using Swift?

I know there are many third party libraries to do this but they are all written in Objective-C. I'm looking for a Swift alternative.

Ios Solutions


Solution 1 - Ios

As mentioned in the comments, although its possible to use Objective-C libraries in Swift, I wanted a more pure Swift solution. The existing Apple Reachability class and other third party libraries seemed to be too complicated for me to translate to Swift. I Googled some more and I came across this article which shows a simple method to check for network availability. I set out to translate this to Swift. I hit many snags but thanks to Martin R from StackOverflow, I managed to resolve them and finally get a workable solution in Swift. Here is the code.

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(nil, UnsafePointer($0)).takeRetainedValue()
        }
        
        var flags: SCNetworkReachabilityFlags = 0
        if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == 0 {
            return false
        }
        
        let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        
        return isReachable && !needsConnection
    }
    
}

For Swift > 3.0

public class Reachability {
    public 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
        }
        if flags.isEmpty {
            return false
        }

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

        return (isReachable && !needsConnection)
    }
}

This works for both 3G and WiFi connections. I've also uploaded it to my GitHub with a working example.

Solution 2 - Ios

I give you better way...

You must create a class with this code

 import Foundation
 public class Reachability {

class func isConnectedToNetwork()->Bool{

    var Status:Bool = false
    let url = NSURL(string: "http://google.com/")
    let request = NSMutableURLRequest(URL: url!)
    request.HTTPMethod = "HEAD"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
    request.timeoutInterval = 10.0
    
    var response: NSURLResponse?
    
    var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData?
    
    if let httpResponse = response as? NSHTTPURLResponse {
        if httpResponse.statusCode == 200 {
            Status = true
        }
    }
    
    return Status
  }
}

And then 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")
}

Very easy!

*This way is based on Vikram Pote answer!

Solution 3 - Ios

For Swift 3.1 (iOS 10.1)

If you want to make the distinction between the network-type (i.e. WiFi or WWAN):

You can use:

func checkWiFi() -> Bool {
	
	let networkStatus = Reachability().connectionStatus()
	switch networkStatus {
	case .Unknown, .Offline:
		return false
	case .Online(.WWAN):
		print("Connected via WWAN")
		return true
	case .Online(.WiFi):
		print("Connected via WiFi")
		return true
	}
}

Here is the entire Reachability-Class that distinguished between network-types:

import Foundation
import SystemConfiguration

import UIKit
import SystemConfiguration.CaptiveNetwork

public let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"

public enum ReachabilityType: CustomStringConvertible {
    case WWAN
    case WiFi
    
    public var description: String {
        switch self {
        case .WWAN: return "WWAN"
        case .WiFi: return "WiFi"
        }
    }
}

public enum ReachabilityStatus: CustomStringConvertible  {
    case Offline
    case Online(ReachabilityType)
    case Unknown
    
    public var description: String {
        switch self {
        case .Offline: return "Offline"
        case .Online(let type): return "Online (\(type))"
        case .Unknown: return "Unknown"
        }
    }
}

public class Reachability {
    
    func connectionStatus() -> ReachabilityStatus {
        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) { zeroSockAddress in
				SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
			}
		}) else {
		   return .Unknown
		}
		
	    var flags : SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return .Unknown
        }
        
        return ReachabilityStatus(reachabilityFlags: flags)
    }
    
    func monitorReachabilityChanges() {
        let host = "google.com"
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        let reachability = SCNetworkReachabilityCreateWithName(nil, host)!
        
        SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
            let status = ReachabilityStatus(reachabilityFlags: flags)
            
			NotificationCenter.default.post(name: NSNotification.Name(rawValue: ReachabilityStatusChangedNotification), object: nil, userInfo: ["Status": status.description])}, &context)
        
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
    }
}

extension ReachabilityStatus {
	
    public init(reachabilityFlags flags: SCNetworkReachabilityFlags) {
        let connectionRequired = flags.contains(.connectionRequired)
        let isReachable = flags.contains(.reachable)
        let isWWAN = flags.contains(.isWWAN)
        
        if !connectionRequired && isReachable {
            if isWWAN {
                self = .Online(.WWAN)
            } else {
                self = .Online(.WiFi)
            }
        } else {
            self =  .Offline
        }
    }
}

Solution 4 - Ios

SWIFT 3: Checks for wifi and internet connection:

import Foundation
import SystemConfiguration

public class Reachability {
    public 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)
    }
}

USAGE:

if Reachability.isConnectedToNetwork() == true {
    print("Connected to the internet")
    //  Do something
} else {
    print("No internet connection")
    //  Do something
}

Solution 5 - Ios

Since sendSynchronousRequest is deprecated, I tried this but 'return Status' was called before the response had finished.

This answer works well though, https://stackoverflow.com/questions/30743408/check-for-internet-conncetion-in-swift-2-ios-9

Here's what I tried anyway:

import Foundation

public class Reachability {
    
    class func isConnectedToNetwork()->Bool{
        
        var Status:Bool = false
        let url = NSURL(string: "http://google.com/")
        let request = NSMutableURLRequest(URL: url!)
        request.HTTPMethod = "HEAD"
        request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
        request.timeoutInterval = 10.0
        let session = NSURLSession.sharedSession()
        
        session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
            print("data \(data)")
            print("response \(response)")
            print("error \(error)")
            
            if let httpResponse = response as? NSHTTPURLResponse {
                print("httpResponse.statusCode \(httpResponse.statusCode)")
                if httpResponse.statusCode == 200 {
                    Status = true
                }
            }
            
        }).resume()
        
        
        return Status
    }
}

Solution 6 - Ios

You can also use below answer.

    func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
    {
      UIApplication.sharedApplication().networkActivityIndicatorVisible = true

      let url = NSURL(string: "http://www.google.com/")
      let request = NSMutableURLRequest(URL: url!)

      request.HTTPMethod = "HEAD"
      request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
      request.timeoutInterval = 10.0

      NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
      {(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in

        UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        let rsp = response as NSHTTPURLResponse?

        completionHandler(internet:rsp?.statusCode == 200)
    })
    }

     func yourMethod()
    {
    self.checkInternet(false, completionHandler:
    {(internet:Bool) -> Void in

        if (internet)
        {
            // "Internet" mean Google
        }
        else
        {
            // No "Internet" no Google
        }
    })
   }

Solution 7 - Ios

I have found the best of all answers and this keeps on checks the Internet connectivity status every time.

To get started, first add an import for the Network framework:

import Network

Next, create an instance of NWPathMonitor

let monitor = NWPathMonitor()

To try this out,

 monitor.pathUpdateHandler = { path in
    if path.status == .satisfied {
      print("We're connected!")
    } else {
      print("No connection.")
    }
    print(path.isExpensive)
 }

Remember, that closure gets called every time the connection status changes.

 let queue = DispatchQueue(label: "Monitor")
 monitor.start(queue: queue)

Here How I used this in my View controller,

class testViewController: UIViewController {

@IBOutlet weak var status: UILabel!
let monitor = NWPathMonitor()

override func viewDidLoad() {
    super.viewDidLoad()
    
    let queue = DispatchQueue(label: "Monitor")
    monitor.start(queue: queue)
    _ = NWPathMonitor(requiredInterfaceType: .cellular)
    
    monitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            print("We're connected!")
            DispatchQueue.main.async {
                self.status.text = "We're connected!"
            }
            
        } else {
            print("No connection.")
            DispatchQueue.main.async {
                self.status.text = "No connection."
            }  
        }
    }
 }

Solution 8 - Ios

Swift 4

if isInternetAvailable() {
    print("if called Internet Connectivity success \(isInternetAvailable())");
} else {
    print("else called Internet Connectivity success \(isInternetAvailable())");
}

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)
   //   print(isReachable && !needsConnection)
   return (isReachable && !needsConnection)
}

Solution 9 - Ios

For Swift 5:

import Network
let monitor = NWPathMonitor()

func checkInterwebs() -> Bool {
    var status = false
    monitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            status = true  // online
        }
    }
    return status
}

Solution 10 - Ios

If you use Alamofire in your project you can Use this sample func:

import Alamofire

class Network {

    func isConnected(_ complition: @escaping(Bool) -> Void) {
        let retVal = NetworkReachabilityManager()!.isReachable
        complition(retVal)
    }

}

Solution 11 - Ios

SWIFT 3: Check 3G & Wi-Fi connection

DispatchQueue.main.async {
        let url = URL(string: "https://www.google.com")!
        let request = URLRequest(url: url)
        
        let task = URLSession.shared.dataTask(with: request) {data, response, error in
            
            if error != nil {
                // do something here...
                print("Internet Connection not Available!")
            }
            else if let httpResponse = response as? HTTPURLResponse {
                if httpResponse.statusCode == 200 {
                    // do something here...
                    print("Internet Connection OK")
                }
                print("statusCode: \(httpResponse.statusCode)")
            }
            
        }
        task.resume()
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIsuruView Question on Stackoverflow
Solution 1 - IosIsuruView Answer on Stackoverflow
Solution 2 - IosDmitryView Answer on Stackoverflow
Solution 3 - IosiKKView Answer on Stackoverflow
Solution 4 - IosGilad BrunfmanView Answer on Stackoverflow
Solution 5 - IosSarahView Answer on Stackoverflow
Solution 6 - IosVikram PoteView Answer on Stackoverflow
Solution 7 - Iosmirhpe danielleView Answer on Stackoverflow
Solution 8 - IosKeshav GeraView Answer on Stackoverflow
Solution 9 - IosRandallShanePhDView Answer on Stackoverflow
Solution 10 - IosmohsenView Answer on Stackoverflow
Solution 11 - IosWłodzimierz WoźniakView Answer on Stackoverflow