iosswiftnsnotificationcenterreachability

Detecting Network Connectivity Changes using Reachability, NSNotification and Network Link Conditioner in Swift


From iOS 12 you simply use NWPathMonitor which is a line of code (example).

For historic purposes:


I'm trying to integrate network connectivity detection into my app, however it seems that somewhere along the line I have made a mistake as my network changes are not being detected/printed out into the console.

As mentioned in the post, I'm currently using these following classes and tools for the job:

  1. Reachability {.h, .m}
  2. NSNotificationCenter
  3. Network Link Conditioner

Code

In the AppDelegate.Swift, I've set up the NSNotificationCenter to detect changes:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // ... 
    // A: Checks if the device is connected to the internet

    var defaultCenter: Void = NSNotificationCenter().addObserver(self, selector:"checkForReachability", name: kReachabilityChangedNotification, object: nil)
} 

In the same class AppDelegate, I've also created this function to be triggered whenever there is a change:

func checkForReachability () {        
    var networkReachability = Reachability.reachabilityForInternetConnection()
    networkReachability.startNotifier()
    
    var remoteHostStatus = networkReachability.currentReachabilityStatus()
    if (remoteHostStatus.value == NotReachable.value) {
        println("Not Reachable")
    } else if (remoteHostStatus.value == ReachableViaWiFi.value) {
        println("Reachable via Wifi")
    } else {
        println("Reachable")
    }
}

However, when using the Network Link Conditioner to manipulate and simulate changes in conditions, I haven't been able to see any of those changes reflected in the console.


Solution

  • You must create a Reachability object before you can receive notifications from it. Also, be sure to call the startNotifier() method on the Reachability object you create. This would be an example of how to do so inside of your application delegate:

    class AppDelegate: UIResponder, UIApplicationDelegate
    {
        private var reachability:Reachability!;
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
        {
            NSNotificationCenter.defaultCenter().addObserver(self, selector:"checkForReachability:", name: kReachabilityChangedNotification, object: nil);
    
            self.reachability = Reachability.reachabilityForInternetConnection();
            self.reachability.startNotifier();
        }
    
        @objc func checkForReachability(notification:NSNotification)
        {
            // Remove the next two lines of code. You cannot instantiate the object
            // you want to receive notifications from inside of the notification
            // handler that is meant for the notifications it emits.
    
            //var networkReachability = Reachability.reachabilityForInternetConnection()
            //networkReachability.startNotifier()
    
            let networkReachability = notification.object as Reachability;
            var remoteHostStatus = networkReachability.currentReachabilityStatus()
    
            if (remoteHostStatus.value == NotReachable.value)
            {
                println("Not Reachable")
            }
            else if (remoteHostStatus.value == ReachableViaWiFi.value)
            {
                println("Reachable via Wifi")
            }
            else
            {
                println("Reachable")
            }
        }
    }
    

    I recommend you take a look at the documentation for NSNotificationCenter and NSNotification. That way you'll be more familiar with how to work with notifications next time something like this comes up.

    Swift 3

    NotificationCenter.default.addObserver(self, selector:Selector(("checkForReachability:")), name: NSNotification.Name.reachabilityChanged, object: nil)
    let reachability: Reachability = Reachability.forInternetConnection()
    reachability.startNotifier()