iOS Swift подключает Wi-Fi программно и различает плохой пароль и отсутствие WiFi в зоне действия - PullRequest
7 голосов
/ 03 июня 2019

NEHotspotConfiguration работает хорошо, но ошибка nil, когда SSID, к которому я пытаюсь подключиться, недоступен (вне диапазона или отключен) или когда введенный пароль неверен.

Что я делаю не так? Я хочу уметь различать эти два сценария, чтобы соответственно информировать пользователя.

Фрагмент кода:

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 Ответ

3 голосов
/ 14 июня 2019

Быстро попробовал, и это, кажется, прекрасно воспроизводимо. Дальнейшие исследования показали, что это ошибка Apple. Поэтому ответ таков: вы ничего не делаете неправильно, это ошибка.

Причины, по-видимому:

... ошибки, которые вы видите через обработчик завершения, это ошибки, связанные с самой платформой. Как только запрос прошел через инфраструктуру расширения сети, вплоть до подсистемы Wi-Fi, ошибки отображаются пользователю, а не доставляются вашему обработчику завершения. Является ли это ошибкой, подлежит обсуждению.

Позже можно прочитать:

Итак, мои 2 ошибки (46628017 и 46579891), касающиеся NEHotspot, помечены как дубликаты 42919071

смотрите всю дискуссию здесь: https://forums.developer.apple.com/thread/96834

Некоторые эксперименты

Есть хороший ответ: https://stackoverflow.com/a/5198968/2331445

Показывает, как получить доступ к информации о подключенном в данный момент WIFI.

Как объясняет автор, вам нужно добавить возможность Access WiFi Information для iOS> 12. Тест с использованием метода getConnectedWifiInfo из приведенного выше SO-ответа для эксперимента может выглядеть следующим образом:

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.

...