iosswiftwifinetworkextensionnehotspothelper

NEHotspotConfigurationManager no error for invalid password/SSID


When I use NEHotspotConfigurationManager to connect to a WiFi access point, and I intentionally use an invalid password or SSID, I don't get the programmatic feedback I expect. The user receives feedback that the connection failed via an alert, but in the completion block supplied to the apply function, error is nil, the same as the success case. This makes it impossible for me to differentiate the success and failure cases. The NEHotspotConfigurationError has both .invalidSSID and .invalidWPAPassphrase. I would expect these to be returned instead. This feels like a radar to me, but I wanted to get some feedback on here first.

NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: "test")
let configuration = NEHotspotConfiguration(ssid: "test", passphrase: "testasdasd", isWEP: false)
configuration.joinOnce = true
NEHotspotConfigurationManager.shared.apply(configuration) { (error) in
    // error is nil
}

Solution

  • After filing a radar with Apple, it appears this API is working as designed. The success/failure case only applies to the application of the hotspot configuration.

    The good news is, I have found a suitable work around for this in using CNCopySupportedInterfaces to verify if the app has indeed connected to the SSID it said it did.

    let ssid = "test"
    NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: said)
    let configuration = NEHotspotConfiguration(ssid: ssid, passphrase: "testasdasd", isWEP: false)
    configuration.joinOnce = true
    NEHotspotConfigurationManager.shared.apply(configuration) { (error) in
        if let error = error as NSError? {
                // failure
            } else {
                if self.currentSSIDs().first == ssid {
                    // Real success
                } else {
                    // Failure
                }
            }
    }
    

    Using this function as defined below:

    func currentSSIDs() -> [String] {
        guard let interfaceNames = CNCopySupportedInterfaces() as? [String] else {
            return []
        }
        return interfaceNames.flatMap { name in
            guard let info = CNCopyCurrentNetworkInfo(name as CFString) as? [String:AnyObject] else {
                return nil
            }
            guard let ssid = info[kCNNetworkInfoKeySSID as String] as? String else {
                return nil
            }
            return ssid
        }
    }