I want to get notified when my WiFi Router color changes from Green to Red
I am making an app which will tell you whether you are online or offline from menu bar in Swift which is open source & can be found at https://github.com/deadcoder0904/net-alert
I want to know if its possible to get notified when WiFi color changes in Swift.
I can't constantly ping my server to know that the color changed as this would be wasting internet resources.
So is it possible to know this in Swift?
First of all, I'm going to answer this from iOS perspective. But your GitHub demo is for macOS. I think the basics are the same.
I'll go to solve this in protocol oriented approach.
After quite a lot of searching I've come across the magnificent implementation of Connectivity wrapper. There is even a descriptive blogpost Solving the Captive Portal Problem on iOS if you want to know more about it. This implementation is capable of dealing with actual internet available / not-available states.
Note: Don't like to read further? Here is the working version that I'm going to illustrate briefly. Navigation bar will reflect with Green & Red color for different connection status.
This protocol will help any interested object to be notified when any change in connectivity occurs.
protocol ConnectivityNotifiable {
var connectivity: Connectivity { get }
func startNotifyingConnectivityChangeStatus()
func stopNotifyingConnectivityChangeStatus()
func connectivityChanged(toStatus: ConnectivityStatus)
}
// Provide some default implementation through protocol extension
extension ConnectivityNotifiable {
func startNotifyingConnectivityChangeStatus() {
connectivity.isPollingEnabled = true
connectivity.startNotifier()
connectivity.whenConnected = { connectivity in
self.connectivityChanged(toStatus: connectivity.status)
}
connectivity.whenDisconnected = { connectivity in
self.connectivityChanged(toStatus: connectivity.status)
}
}
func stopNotifyingConnectivityChangeStatus() {
connectivity.stopNotifier()
}
}
Conforming to the ConnectivityNotifiable
protocol will add the functionality to any interested object to be notified when Connectivity status changes. Something like monitoring.
class ViewController: UIViewController, ConnectivityNotifiable {
// ConnectivityNotifiable protocol requirement
let connectivity = Connectivity()
override func viewDidLoad() {
super.viewDidLoad()
// Invoke the default implementation of the ConnectivityNotifiable protocol
// requirement to be able to be notified
startNotifyingConnectivityChangeStatus()
// Reminder:
// Don't forget to invoke stopNotifyingConnectivityChangeStatus() when
// you are done or when the lifecycle of your controller ends
}
// ConnectivityNotifiable protocol requirement
func connectivityChanged(toStatus: ConnectivityStatus) {
// Everytime any change happens in the network connectivity
// this method will be invoked with appropriate connection status
switch toStatus {
case .connected,
.connectedViaWiFi,
.connectedViaCellular:
// Connected/Internet available. Update any UI component
case .notConnected,
.connectedViaWiFiWithoutInternet,
.connectedViaCellularWithoutInternet:
// Disconnected/Internet not available. Update any UI component
}
}
}
Note: If you are using the latest release of the Reachability, you won't need the NotificationCenter
based solution to get reachability change notification. It works completely fine with closure based approach.
Don't like to know how to achieve this? Here is a working version made for iOS platform. Clone the repo and check yourself. Navigation bar will reflect with Green, Orange & Red color for different connection status.
Define a protocol:
This protocol will help any interested object to be notified when any change in reachability occurs.
protocol Reachable {
var reachability: Reachability { get }
func startMonitoringReachabilityChangeStatus()
func reachabilityChanged(to: Reachability.Connection)
}
extension Reachable {
func startMonitoringReachabilityChangeStatus() {
do {
try reachability.startNotifier()
} catch {
print(error.localizedDescription)
}
reachability.whenReachable = { reachability in
self.reachabilityChanged(to: reachability.connection)
}
reachability.whenUnreachable = { reachability in
self.reachabilityChanged(to: reachability.connection)
}
}
}
Conform to the protocol:
Conforming to the Reachable
protocol will add the functionality to any interested object to be notified when reachability status changes. Something like monitoring.
class ViewController: UIViewController, Reachable {
// Reachable protocol requirement
let reachability: Reachability = Reachability()!
override func viewDidLoad() {
super.viewDidLoad()
// initial reachability checkup
reachabilityChanged(to: reachability.connection)
// Invoke the default implementation of the Reachable protocol requirement
// to be able to be notified
startMonitoringReachabilityChangeStatus()
}
// Reachable protocol requirement
func reachabilityChanged(to: Reachability.Connection) {
// Everytime any change happens in the network connectivity
// this method will be invoked with appropriate connection status
switch to {
case .wifi:
DispatchQueue.main.async {
// Update any UI component
}
case .cellular:
DispatchQueue.main.async {
// Update any UI component
}
case .none:
DispatchQueue.main.async {
// Update any UI component
}
}
}
}