search by tags

for the user

adventures into the land of the command line

swift network reachability monitoring

i followed this one

nowadays most apps require internet access, so we need to consider how an app should behave when there is no available internet connection. the first step to implementing this functionality is to monitor the internet connectivity. so how do we do this?

first include the ReachabilitySwift cocoa pod

$ cat Podfile

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

target 'myapp' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for myapp
  pod ‘ReachabilitySwift’

  target 'myappTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'myappUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end

implement a class to make use of the ReachabilitySwift library. note the reachabilityChanged function which will do some global thing (valid across all views in your app) when the network reachability status has changed. in this implementation, it displays a message on the ui with some function implemented elsewhere in the app.

//
//  ReachabilityManager.swift
//  myapp
//

import ReachabilitySwift

// App wide protocol for listening to network status changes
public protocol NetworkStatusListener: class {
    func networkStatusDidChange(status: Reachability.NetworkStatus)
}

class ReachabilityManager: NSObject {

    // Shared instance
    static  let shared = ReachabilityManager()

    // Boolean to track network reachability
    var isNetworkAvailable: Bool {
        return reachabilityStatus != .notReachable
    }

    // Tracks current NetworkStatus (notReachable, reachableViaWiFi, reachableViaWWAN)
    var reachabilityStatus: Reachability.NetworkStatus = .notReachable

    // Reachability instance for Network status monitoring
    let reachability = Reachability()!

    // Array of delegates which are interested in listening to network status changes
    var listeners = [NetworkStatusListener]()

    // Called whenever there is a change in NetworkReachibility Status
    @objc func reachabilityChanged(notification: Notification) {
        let reachability = notification.object as! Reachability
        switch reachability.currentReachabilityStatus {
        case .notReachable:
            DispatchQueue.main.async {
                MessageDialog.showNotification(type: "bad", title: "No Internet Connection", message: "Turn on Mobile Data or Wifi to use the app.", dismissDelay: 0)
            }
        case .reachableViaWiFi:
            DispatchQueue.main.async {
                // Don't do anything here
            }
        case .reachableViaWWAN:
            DispatchQueue.main.async {
                // Don't do anything here
            }
        }

        // Sending messages to each of the listening delegates
        for listener in listeners {
            listener.networkStatusDidChange(status: reachability.currentReachabilityStatus)
        }
    }

    // Starts monitoring the network availability status
    func startMonitoring() {
        NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: ReachabilityChangedNotification, object: reachability)
        do {
            try reachability.startNotifier()
        } catch {
            print("Could not start reachability notifier")
        }
    }

    // Stops monitoring the network availability status
    func stopMonitoring() {
        reachability.stopNotifier()
        NotificationCenter.default.removeObserver(self, name: ReachabilityChangedNotification, object: reachability)
    }

    // Adds a new listener to the listeners array
    func addListener(listener: NetworkStatusListener) {
        listeners.append(listener)
    }

    // Removes a listener from listeners array
    func removeListener(listener: NetworkStatusListener) {
        listeners = listeners.filter{ $0 !== listener}
    }
}

then in your view controller, you'll want to call this class. the extension is for getting something to happen in this view controller, which is specific to this view controller, when the network reachability status changes. in viewWillAppear and viewDidDisappear, the network monitoring is enabled or disabled when the view is added onto the stack or removed from the stack.

//
//  MyViewController.swift
//  myapp
//

import Foundation
import UIKit
import ReachabilitySwift

extension MyViewController: NetworkStatusListener {
    func networkStatusDidChange(status: Reachability.NetworkStatus) {
        switch status {
        case .notReachable:
            DispatchQueue.main.async {
                self.disableInteractiveElements()
            }
        case .reachableViaWiFi:
            DispatchQueue.main.async {
                self.enableInteractiveElements()
            }
        case .reachableViaWWAN:
            DispatchQueue.main.async {
                self.enableInteractiveElements()
            }
        }
    }
}

class MyViewController: UIViewController {

	.
	.
	.

	override func viewDidLoad() {
		super.viewDidLoad()
	}

	override func viewWillAppear(_ animated: Bool) {
		super.viewWillAppear(animated)
		ReachabilityManager.shared.addListener(listener: self as NetworkStatusListener)
	}

	override func viewDidDisappear(_ animated: Bool) {
		super.viewDidDisappear(animated)
		ReachabilityManager.shared.removeListener(listener: self as NetworkStatusListener)
	}

	.
	.
	.

}

lastly we want to stop the network reachability monitoring when the app is closed or running in the background, and restart it when the user opens the app again

//
//  AppDelegate.swift
//  myapp
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

	.
	.
	.

	func applicationWillEnterForeground(_ application: UIApplication) {
		// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.

		// Stops monitoring network reachability status changes
		ReachabilityManager.shared.stopMonitoring()
	}

	func applicationDidBecomeActive(_ application: UIApplication) {
		// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

		// Starts monitoring network reachability status changes
		ReachabilityManager.shared.startMonitoring()
		}
	}

	.
	.
	.

}