iOS Swift以编程方式连接WiFi并区分密码错误和范围内没有WiFi

时间:2019-06-03 13:56:03

标签: ios swift wifi

NEHotspotConfiguration运作良好,但是当我尝试连接的SSID不可用(超出范围或关闭)或者我提交的密码不正确时,错误均为nil

我在做什么错?我希望能够区分这两种情况,以便相应地通知用户。

代码段:

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")
            }
        }
    }
}

1 个答案:

答案 0 :(得分:3)

快速尝试它,看起来完全可重复。 进一步的研究表明,这是一个Apple错误。 因此答案是:您没有做错任何事情,这是一个错误。

原因似乎是:

  

...通过完成处理程序看到的错误是与框架本身相关的那些错误。一旦请求通过网络扩展框架,直到Wi-Fi子系统,错误就会显示给用户,而不是传递给完成处理程序。这是否是一个错误尚待争论。

以后的人可以阅读:

  

因此,我关于NEHotspot的2个错误(46628017和46579891)被标记为重复的42919071

在此处查看整个讨论: https://forums.developer.apple.com/thread/96834

一些实验

有一个很好的答案:https://stackoverflow.com/a/5198968/2331445

它显示了如何访问有关当前连接的WIFI的信息。

正如作者所解释的,您需要为iOS> 12添加访问WiFi信息功能。使用上述SO答案中的getConnectedWifiInfo方法进行的测试可能如下所示:

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
    }

}

实际上,如果我运行此代码,我将得到结果:

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

该SO答案的作者还显示了适用于旧版iOS的方法。