Connect to Wifi network from code – Swift

With the NetworkExtension framework, you can customize and extend the core networking features of iOS and macOS. Specifically, you can:

  • Change the system’s Wi-Fi configuration
  • Integrate your app with the hotspot network subsystem (Hotspot Helper)
  • Create and manage VPN configurations, using the built-in VPN protocols (Personal VPN) or a custom VPN protocol
  • Implement an on-device content filter
  • Implement an on-device DNS proxy

The NetworkExtension framework is available in macOS and iOS, but not all features are available on both platforms and some features have specific restrictions (for example, some features only work on supervised iOS devices). The documentation for each feature describes these restrictions.

Apple reference: https://developer.apple.com/documentation/networkextension


Starting from iOS11 is possible to connect to the Wifi network directly without leaving the app and browsing from Wifi networks.

It’s a very simple logic (the hard part was made by Apple of course and is hidden to the developers).

The owner of this configuration is the NEHotspotConfigurationManager.

Prerequisites

  1. Add the “Hotspot Configuration” capabilities on your project.

2. Import “NetworkExtension” framework in your code.


Show me the code!

The NEHotspotConfigurationManager is a singleton class. You cannot instantiate as new() but you can use the .shared method.

To easily connect to a Wifi network you need to create a new configuration and next, apply this configuration.

let hotspotConfig = NEHotspotConfiguration( ssid: wifiName, passphrase: wifiPassword, isWEP: wep)

Well, configuration is created. Now we need to apply it:

NEHotspotConfigurationManager.shared.apply(hotspotConfig)

The connection between your app and the wifi network is now complete.

Handle errors

You can manage the connection errors in the completion callback of the .apply method. Errors are an enum of NEHotspotConfigurationError.

Common case are:

Handle connected networks

You can read connected networks using the .getConfiguredSSIDs method:

NEHotspotConfigurationManager.shared.getConfiguredSSIDs { (wifiList) in
    wifiList.forEach {
        // have fun
    }
}

Important note about error handling on iOS < 13!

Running the code with error handling on iOS less than 13 you receive this error:

dyld: Symbol not found: _NEHotspotConfigurationErrorDomain  

This error is due to an invalid declaration of availability of the error enum in Swift SDK (reference: https://forums.developer.apple.com/thread/122836)

You can avoid this using a custom enum to manage this error, like this:

    enum NEHotspotConfigurationErrorWorkaround: Int {
        case alreadyAssociated = 13
    }

And use it in the apply callback:

NEHotspotConfigurationManager.shared.apply(hotspotConfig) { (hotSpotError) in
    if let error = hotSpotError {
        switch error {
            case is NEHotspotConfigurationErrorWorkaround:
                completion(false)
            default:
                completion(true)
        }
    }
}

In this way, you ignore the unavailability of the enum.

Full code snippet here: https://gist.github.com/elpsk/2165edb7d040ada6fe525d5adc031904#file-hotspothelper-swift

Have fun.
 

Alberto Pasca

Software engineer @ Pirelli & C. S.p.A. with a strong passion for mobile  development, security, and connected things.