Almost every mobile app needs to connect to the Internet at some point to retrieve data from a host or service or upload new data to it. However, the Internet connection is not always available, and its availability can change at any time. To know the state of the system's current network and if a host or service is reachable through that network, we can use the SCNetworkReachability API.

This API is part of Core Foundation, so it written in C. If you are using Swift this API is not really straightforward to use for many people. Apple provides some sample code containing a class called Reachability, which is an Objective-C wrapper around the SCNetworkReachability API. This class encapsulates how to access the network, along with some convenience methods for asking if we are connected or not to the Internet. It also allows to register your objects to NSNotificationCenter to be notified through a NSNotification object when the network status changes. You can find this wrapper class in a sample code project available at:

https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html

If you are already familiar with the Reachability class, you should only update your code with the latest version (4.2 from November 11th, 2015) that fixes a couple of bugs that could potentially leak some memory.

The sample code provided by Apple is written in Objective-C, and since we get a lot of petitions from developers requesting the Swift version, we are going to address that in this post. We will write our own Reachability class in Swift 3.0 and explain how it works, step by step.

The SCNetworkReachability API

The SCNetworkReachability API provides a synchronous method to determine the reachability. The synchronous method allows us to request the current status of the reachability by calling the SCNetworkReachabilityGetFlags function. The second parameter of this function is a pointer to memory that will be filled with flags that describe the reachability status and will provide extra information such as whether a connection is required and whether some user intervention might be required when establishing a connection.

In addition to the synchronous method, the SCNetworkReachability API provides an asynchronous method. To implement this approach we need to schedule the SCNetworkReachability object in a run loop. Providing a callback function we can then post a notification whenever the reachability of the remote host changes.

Let’s do it in Swift

Launch Xcode 8 and create a new Swift Single View Application project. Name it ReachabilityExample. Let's immediately add a new swift file to our project. Name it Reachability.swift. Let's add to this file the following import statement:

We want to inform our App when the network status changes in three possible scenarios.

  1. when the app is not connected,
  2. when the app is connected via Wifi,
  3. when the app is connected via WWAN.

We will do so by sending a notification containing the status of the connection. So, let's define the notification name and the three possible states:

Let's now implement the Reachability class.

Let's add to this class a property to store the SCNetworkReachability object:

For cases where we want to monitor the reachability of the target host, we create an initializer that takes the node name of the desired host as parameter, and creates a SCNetworkReachability object with the SCNetworkReachabilityCreateWithName function. This function can return nil, if it's not able to create a valid SCNetworkReachability object. So, our initializer will be a failable initializer:

We need to create an additional initializer for cases where we want to create a reachability reference to the network address. In this case we will use the SCNetworkReachabilityCreateWithAddress function. As this function expects a pointer to a network address, we will call it inside a withUnsafePointer function. Also in this case, we need to make the init failable, as there is also the possibility of returning a nil value as explained before:

For convenience, we create a couple of class methods. The first method creates a reachability instance to control if we are connected to internet. The second method allows to check if we are connected to a local WiFi. Both methods use the initializers that we have just created with a network address. In case of the local WiFi, the address will point to 169.254.0.0 as defined in for IN_LINKLOCALNETNUM.

Now we need a couple of methods to start and stop notifying and a property to save a state if we are notifying changes or not:

To start notifying, we first check that we are not already doing so. Then, we get a SCNetworkReachabilityContext and we assign self to its info parameter. After that we set the callback function, passing also the context (when the callback function is called, the info parameter that contains a reference to self will be passed as pointer to a data block as third parameter). If setting the callback function is successful, we can then schedule the network reachability reference in a run loop.

To stop notifying, we just unschedule the network reachability reference from the run loop:

We should also make sure that we stop notifying before the Reachability object is deallocated:

To know the state of the network reachability, we can define a computed property that will get the current flags of the SCNetworkReachability object:

I create now a method that is able to return the reachability status for the set of flags passed to it (the logic used to determine which flag means which type of connection is explained in the comments of the method):

If you want to know more about the different flags that are available and the meaning of each one, you can read the official documentation for the flags.

Finally, we can create a method to determine the reachability status of the current flags of our network reachability reference, and a computed property to verify if we are connected or not:

How to use the Reachability?

Using your new Reachability class is really straightforward: you create a new instance, and start the notifier. Then, if want to control the state of the UI depending on the reachability, you can register your view controller to the reachability notification and make it react to reachability changes.

Let's build a very simple example to test our Reachability class. I will change the color of the viewcontroller's view to green when there is connection to the Internet. Instead, the color of the view will change to red if there is no Internet connected.

Open the ViewController.swift file and add a new property to this class:

In the viewDidLoad() method we add the view controller as an observer of the reachability notification.

In the deinit we stop the notifier:

Whenever the view of this view controller appears on the screen, we check for the reachability:

When we receive a notification, the view controller executes the following method:

Of course you can also use it with a domain address. Just use the corresponding initializer, for example:

Conclusion

I hope that now you have a better understanding of how the SystemConfiguration framework works.

Enjoy learning!!!

Geppy Parziale (@geppy) is cofounder of InvasiveCode. He has developed many iOS applications and taught iOS development to many engineers around the world since 2008. He worked at Apple as iOS and OS X Engineer in the Core Recognition team. He has developed several iOS and OS X apps and frameworks for Apple, and many of his development projects are top-grossing iOS apps that are featured in the App Store. Geppy is an expert in computer vision and machine learning.

iOS Consulting | INVASIVECODE

iOS Training | INVASIVECODE