10

NEHotspotConfiguration works well, but the error is nil both when the SSID I am trying to connect to is not available (out of range or off) or when the password I've submitted is incorrect.

What am I doing wrong? I want to be able to distinguish between these two scenarios so I can inform the user accordingly.

Code snippet:

func connect(ssid: String, password: String, completionHandler: @escaping(Bool?, String?) -> Void) {
    activityIndicatorView?.startAnimating()

    guard !isAlreadyConnected(ssid: ssid) else {
        activityIndicatorView?.stopAnimating()
        completionHandler(true, nil)
        return;
    }

    let hotspotConfig = NEHotspotConfiguration(ssid: ssid, passphrase: password, isWEP: false)//Secured connections
    hotspotConfig.joinOnce = true

    NEHotspotConfigurationManager.shared.apply(hotspotConfig) {[weak self] (error) in
        guard let self = self else { return; }

        self.activityIndicatorView?.stopAnimating()
        if let error = error {
            completionHandler(false, error.localizedDescription)
        }
        else {
            let ssids = self.currentSSIDs()
            if ssids.count > 0 && ssids.first == ssid {
                completionHandler(true, nil)
            } else {
                completionHandler(false, error?.localizedDescription ?? "An error occured")
            }
        }
    }
}
ericosg
  • 4,926
  • 4
  • 37
  • 59
  • 2
    Could you please provide the code how you use `NEHotspotConfiguration` and how you are trying to get the error? – Eugene Dudnyk Jun 11 '19 at 08:32
  • @DisableR, your NEHotspotConfigurationError was nil? So you aren't able to access the enum NEHotspotConfigurationError.Code? Could you try a different SSID? – Saamer Jun 11 '19 at 18:33
  • @DisableR added code, however it's quite standard usage. – ericosg Jun 15 '19 at 15:55

1 Answers1

6

Quickly tried it and it is perfectly reproducible it seems. Further research revealed that it is an Apple error. So the answer is: You are nothing doing wrong, it's a bug.

Reasons seems to be:

...the errors that you see via the completion handler are those errors related to the framework itself. Once the request has made it past the Network Extension framework, down to the Wi-Fi subsystem, errors are displayed to the user rather than delivered to your completion handler. Whether that’s a bug is up for debate.

Later down one can read:

So my 2 bugs (46628017 and 46579891) regarding the NEHotspot marked as duplicated of 42919071

see the whole discussion here: https://forums.developer.apple.com/thread/96834

Some Experiment

There is this nice SO answer: https://stackoverflow.com/a/5198968/2331445

It shows how to access information about the currently connected WIFI.

As the author explains, you need to add the Access WiFi Information capability for iOS > 12. A test using the getConnectedWifiInfo method from the above SO answer for an experiment might look like this:

import UIKit
import NetworkExtension
import SystemConfiguration.CaptiveNetwork

class ViewController: UIViewController {

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

    @IBAction func onConnect(_ sender: Any) {
        let configuration = NEHotspotConfiguration.init(ssid: "somessid", passphrase: "somepassphrase", isWEP: false)
        configuration.joinOnce = true

        NEHotspotConfigurationManager.shared.apply(configuration) { [weak self] (error) in
            print("error is \(String(describing: error))")
            if let error = error {
                let nsError = error as NSError
                if nsError.domain == "NEHotspotConfigurationErrorDomain" {
                    if let configError = NEHotspotConfigurationError(rawValue: nsError.code) {
                        switch configError {
                        case .invalidWPAPassphrase:
                            print("password error: \(error.localizedDescription)")
                        case .invalid, .invalidSSID, .invalidWEPPassphrase,
                             .invalidEAPSettings, .invalidHS20Settings, .invalidHS20DomainName, .userDenied, .pending, .systemConfiguration, .unknown, .joinOnceNotSupported, .alreadyAssociated, .applicationIsNotInForeground, .internal:
                            print("other error: \(error.localizedDescription)")
                        @unknown default:
                            print("later added error: \(error.localizedDescription)")
                        }
                    }
                } else {
                    print("some other error: \(error.localizedDescription)")
                }
            } else {
                print("perhaps connected")

                self?.printWifiInfo()
            }
        }

    }

    @IBAction func onInfo(_ sender: Any) {
        self.printWifiInfo()
    }

    private func printWifiInfo() {
        print("printWifiInfo:")
        if let wifi = self.getConnectedWifiInfo() {
            if let connectedSSID = wifi["SSID"] {
                print("we are currently connected with \(connectedSSID)")
            }
            print("further info:")
            for (k, v) in wifi {
                print(".  \(k) \(v)")
            }
        }
        print()
    }

    private func getConnectedWifiInfo() -> [AnyHashable: Any]? {
        if let ifs = CFBridgingRetain( CNCopySupportedInterfaces()) as? [String],
            let ifName = ifs.first as CFString?,
            let info = CFBridgingRetain( CNCopyCurrentNetworkInfo((ifName))) as? [AnyHashable: Any] {            
                return info
            }
        return nil
    }

}

And indeed if I run this code I get as result:

error is nil
perhaps connected
printWifiInfo:
we are currently connected with somessid
further info:
.  SSIDDATA <11111111 22222222 333331333 44444444 55>
.  BSSID 70:33:ab:cd:ef:22
.  SSID somessid

The author of this SO answer also shows methods for older iOS versions.

Stephan Schlecht
  • 26,556
  • 1
  • 33
  • 47
  • Indeed, looks like it is a bug. I wonder if anyone has hacked around it. – ericosg Jun 15 '19 at 15:51
  • 1
    Maybe you want to play around with this SO-answer https://stackoverflow.com/a/5198968/2331445:, I did a short experiment and it worked for me. I added the complete, self-contained experimental test code to my answer. Is this what you are looking for? – Stephan Schlecht Jun 16 '19 at 13:58
  • Not really, I need info on the WiFi I *cannot* connect to. However, the fact that you showed me that its a bug is useful, as I no longer will try and "fix" it. – ericosg Jun 27 '19 at 07:29