Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check for internet connection with Swift

When I try to check for an internet connection on my iPhone I get a bunch of errors. Can anyone help me to fix this?

The code:

import Foundation import SystemConfiguration  public class Reachability {  class func isConnectedToNetwork() -> Bool {      var zeroAddress = sockaddr_in()     zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))     zeroAddress.sin_family = sa_family_t(AF_INET)      let defaultRouteReachability = withUnsafePointer(&zeroAddress) {         SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))     }      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) ? true : false }  } 

The errors with the code:

Errors

If it is unreadable, error 1 says:

'Int' is not convertible to 'SCNetworkReachabilityFlags'

Error 2 & 3:

Could not find an overload for 'init' that accepts the supplied arguments

like image 639
b3rge Avatar asked Jun 09 '15 21:06

b3rge


People also ask

How do I check my Internet connection in Swift?

In the viewWillAppear method, add an observer to the Notification Center, so every time the network state changes, like from Wifi goes to Cellular, this will be detected instantly and call the reachabilityChanged method. And in the viewDidDisappear method, remove the stop the notifier and remove the observer.

How do I check my internet connection status?

Select the Start button, then type settings. Select Settings > Network & internet. The status of your network connection will appear at the top.

How do I check my Ethernet status?

Open Settings > Network & Internet > Status. Check your Ethernet connection status there. It should display You're connected to the Internet underneath the Ethernet network connection. If one Ethernet cable doesn't work and you have another one nearby, try the other Ethernet cable to see if that works.


1 Answers

To solve the 4G issue mentioned in the comments I have used @AshleyMills reachability implementation as a reference and rewritten Reachability for Swift 3.1:

updated: Xcode 10.1 • Swift 4 or later


Reachability.swift file

import Foundation import SystemConfiguration  class Reachability {     var hostname: String?     var isRunning = false     var isReachableOnWWAN: Bool     var reachability: SCNetworkReachability?     var reachabilityFlags = SCNetworkReachabilityFlags()     let reachabilitySerialQueue = DispatchQueue(label: "ReachabilityQueue")     init(hostname: String) throws {         guard let reachability = SCNetworkReachabilityCreateWithName(nil, hostname) else {             throw Network.Error.failedToCreateWith(hostname)         }         self.reachability = reachability         self.hostname = hostname         isReachableOnWWAN = true         try start()     }     init() throws {         var zeroAddress = sockaddr_in()         zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)         zeroAddress.sin_family = sa_family_t(AF_INET)         guard let reachability = withUnsafePointer(to: &zeroAddress, {             $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {                 SCNetworkReachabilityCreateWithAddress(nil, $0)             }         }) else {             throw Network.Error.failedToInitializeWith(zeroAddress)         }         self.reachability = reachability         isReachableOnWWAN = true         try start()     }     var status: Network.Status {         return  !isConnectedToNetwork ? .unreachable :                 isReachableViaWiFi    ? .wifi :                 isRunningOnDevice     ? .wwan : .unreachable     }     var isRunningOnDevice: Bool = {         #if targetEnvironment(simulator)             return false         #else             return true         #endif     }()     deinit { stop() } } 

extension Reachability {      func start() throws {         guard let reachability = reachability, !isRunning else { return }         var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)         context.info = Unmanaged<Reachability>.passUnretained(self).toOpaque()         guard SCNetworkReachabilitySetCallback(reachability, callout, &context) else { stop()             throw Network.Error.failedToSetCallout         }         guard SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue) else { stop()             throw Network.Error.failedToSetDispatchQueue         }         reachabilitySerialQueue.async { self.flagsChanged() }         isRunning = true     }      func stop() {         defer { isRunning = false }         guard let reachability = reachability else { return }         SCNetworkReachabilitySetCallback(reachability, nil, nil)         SCNetworkReachabilitySetDispatchQueue(reachability, nil)         self.reachability = nil     }      var isConnectedToNetwork: Bool {         return isReachable &&                !isConnectionRequiredAndTransientConnection &&                !(isRunningOnDevice && isWWAN && !isReachableOnWWAN)     }      var isReachableViaWiFi: Bool {         return isReachable && isRunningOnDevice && !isWWAN     }      /// Flags that indicate the reachability of a network node name or address, including whether a connection is required, and whether some user intervention might be required when establishing a connection.     var flags: SCNetworkReachabilityFlags? {         guard let reachability = reachability else { return nil }         var flags = SCNetworkReachabilityFlags()         return withUnsafeMutablePointer(to: &flags) {             SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0))             } ? flags : nil     }      /// compares the current flags with the previous flags and if changed posts a flagsChanged notification     func flagsChanged() {         guard let flags = flags, flags != reachabilityFlags else { return }         reachabilityFlags = flags         NotificationCenter.default.post(name: .flagsChanged, object: self)     }      /// The specified node name or address can be reached via a transient connection, such as PPP.     var transientConnection: Bool { return flags?.contains(.transientConnection) == true }      /// The specified node name or address can be reached using the current network configuration.     var isReachable: Bool { return flags?.contains(.reachable) == true }      /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set, the kSCNetworkReachabilityFlagsConnectionOnTraffic flag, kSCNetworkReachabilityFlagsConnectionOnDemand flag, or kSCNetworkReachabilityFlagsIsWWAN flag is also typically set to indicate the type of connection required. If the user must manually make the connection, the kSCNetworkReachabilityFlagsInterventionRequired flag is also set.     var connectionRequired: Bool { return flags?.contains(.connectionRequired) == true }      /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. Any traffic directed to the specified name or address will initiate the connection.     var connectionOnTraffic: Bool { return flags?.contains(.connectionOnTraffic) == true }      /// The specified node name or address can be reached using the current network configuration, but a connection must first be established.     var interventionRequired: Bool { return flags?.contains(.interventionRequired) == true }      /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. The connection will be established "On Demand" by the CFSocketStream programming interface (see CFStream Socket Additions for information on this). Other functions will not establish the connection.     var connectionOnDemand: Bool { return flags?.contains(.connectionOnDemand) == true }      /// The specified node name or address is one that is associated with a network interface on the current system.     var isLocalAddress: Bool { return flags?.contains(.isLocalAddress) == true }      /// Network traffic to the specified node name or address will not go through a gateway, but is routed directly to one of the interfaces in the system.     var isDirect: Bool { return flags?.contains(.isDirect) == true }      /// The specified node name or address can be reached via a cellular connection, such as EDGE or GPRS.     var isWWAN: Bool { return flags?.contains(.isWWAN) == true }      /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set     /// The specified node name or address can be reached via a transient connection, such as PPP.     var isConnectionRequiredAndTransientConnection: Bool {         return (flags?.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]) == true     } } 

func callout(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {     guard let info = info else { return }     DispatchQueue.main.async {         Unmanaged<Reachability>             .fromOpaque(info)             .takeUnretainedValue()             .flagsChanged()     } } 

extension Notification.Name {     static let flagsChanged = Notification.Name("FlagsChanged") } 

struct Network {     static var reachability: Reachability!     enum Status: String {         case unreachable, wifi, wwan     }     enum Error: Swift.Error {         case failedToSetCallout         case failedToSetDispatchQueue         case failedToCreateWith(String)         case failedToInitializeWith(sockaddr_in)     } } 

Usage

Initialize it in your AppDelegate.swift didFinishLaunchingWithOptions method and handle any errors that might occur:

import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {     var window: UIWindow?     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {         do {             try Network.reachability = Reachability(hostname: "www.google.com")         }         catch {             switch error as? Network.Error {             case let .failedToCreateWith(hostname)?:                 print("Network error:\nFailed to create reachability object With host named:", hostname)             case let .failedToInitializeWith(address)?:                 print("Network error:\nFailed to initialize reachability object With address:", address)             case .failedToSetCallout?:                 print("Network error:\nFailed to set callout")             case .failedToSetDispatchQueue?:                 print("Network error:\nFailed to set DispatchQueue")             case .none:                 print(error)             }         }         return true     } } 

And a view controller sample:

import UIKit class ViewController: UIViewController {     override func viewDidLoad() {         super.viewDidLoad()         NotificationCenter.default             .addObserver(self,                          selector: #selector(statusManager),                          name: .flagsChanged,                          object: nil)         updateUserInterface()     }     func updateUserInterface() {         switch Network.reachability.status {         case .unreachable:             view.backgroundColor = .red         case .wwan:             view.backgroundColor = .yellow         case .wifi:             view.backgroundColor = .green         }         print("Reachability Summary")         print("Status:", Network.reachability.status)         print("HostName:", Network.reachability.hostname ?? "nil")         print("Reachable:", Network.reachability.isReachable)         print("Wifi:", Network.reachability.isReachableViaWiFi)     }     @objc func statusManager(_ notification: Notification) {         updateUserInterface()     } } 

Sample Project

like image 124
Leo Dabus Avatar answered Sep 23 '22 13:09

Leo Dabus