Swift CNCopySupportedInterfaces недействителен

Попытка получить SSID текущего устройства. Я нашел много примеров о том, как это сделать, однако я боюсь, что CNCopySupportedInterfaces будет автозаполнен. У меня есть "import SystemConfiguration" в верхней части моего быстрого файла, но без успеха. Кажется, я не могу понять, что я делаю неправильно.

Ответ 1

iOS 12

Вы должны включить Access WiFi Information из возможностей.

Важно. Чтобы использовать эту функцию в iOS 12 и более поздних версиях, включите возможность доступа к информации о WiFi для вашего приложения в Xcode. Когда вы включаете эту возможность, Xcode автоматически добавляет право доступа к информации о WiFi для вашего файла прав и идентификатора приложения. Ссылка на документацию

Вам необходимо: import SystemConfiguration.CaptiveNetwork

Под обложками CaptiveNetwork является файлом заголовка C. (.h), который находится в рамках SystemConfiguration:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SystemConfiguration.framework/Headers/CaptiveNetwork.h

Если вы знаете Objective-C, это углубляется:

iPhone получает SSID без частной библиотеки

Вы должны использовать неловкий синтаксис для перехода от любого чистого C API, поэтому требуется следующее:

for interface in CNCopySupportedInterfaces().takeRetainedValue() as! [String] {
    println("Looking up SSID info for \(interface)") // en0
    let SSIDDict = CNCopyCurrentNetworkInfo(interface).takeRetainedValue() as! [String : AnyObject]
    for d in SSIDDict.keys {
        println("\(d): \(SSIDDict[d]!)")
    }
}

ДОБАВЛЕНИЕ ДЛЯ SWIFT 2.2 и 3.0

CFxxx данных CFxxx теперь CFxxx к встроенной среде выполнения Objective-C, устраняя вызовы с retain головы. Тем не менее, указатели с нулевым значением приводят к появлению Опций, поэтому все не становится короче. По крайней мере, это довольно ясно, что происходит, плюс nil помогает нам идентифицировать симулятор. Другой ответ использует очень много бит-кастинг и небезопасные операции, которые кажутся не-Swiftian, поэтому я предлагаю это.

func getInterfaces() -> Bool {
    guard let unwrappedCFArrayInterfaces = CNCopySupportedInterfaces() else {
        print("this must be a simulator, no interfaces found")
            return false
        }
        guard let swiftInterfaces = (unwrappedCFArrayInterfaces as NSArray) as? [String] else {
        print("System error: did not come back as array of Strings")
        return false
    }
    for interface in swiftInterfaces {
        print("Looking up SSID info for \(interface)") // en0
        guard let unwrappedCFDictionaryForInterface = CNCopyCurrentNetworkInfo(interface) else {
            print("System error: \(interface) has no information")
            return false
        }
        guard let SSIDDict = (unwrappedCFDictionaryForInterface as NSDictionary) as? [String: AnyObject] else {
        print("System error: interface information is not a string-keyed dictionary")
            return false
        }
        for d in SSIDDict.keys {
            print("\(d): \(SSIDDict[d]!)")
        }
    }
    return true
}

Результат успеха:

SSIDDATA: <57696c6d 79>

BSSID: 12: 34: 56: 78: 9a: bc

SSID: YourSSIDHere

Ответ 2

В Swift 2.0/iOS 9 API CaptiveNetwork (почти) ушла или обесценилась. Я связался с Apple по поводу этой проблемы, и я подумал, что мы можем (или должны) использовать NEHotspotHelper. Я получил ответ от Apple сегодня: нужно продолжать использовать CaptiveNetwork и два соответствующих API (даже жесткие там отмечены обесцененными):

 CNCopySupportedInterfaces
 CNCopyCurrentNetworkInfo

Пользователь braime опубликовал обновленный фрагмент кода для этой проблемы на форумах Ray Wenderlich:

 let interfaces:CFArray! = CNCopySupportedInterfaces()
    for i in 0..<CFArrayGetCount(interfaces){
        let interfaceName: UnsafePointer<Void> 
          =  CFArrayGetValueAtIndex(interfaces, i)
        let rec = unsafeBitCast(interfaceName, AnyObject.self)
        let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)")
        if unsafeInterfaceData != nil {
            let interfaceData = unsafeInterfaceData! as Dictionary!
            currentSSID = interfaceData["SSID"] as! String
        } else {
            currentSSID = ""
        }
    }

Прекрасно подходит для меня.

Ответ 3

Swift:

import SystemConfiguration.CaptiveNetwork

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

Затем print(currentSSIDs()), не работающий на симуляторе, только реальные устройства.

Взято из https://forums.developer.apple.com/thread/50302

Ответ 4

func getInterfaces() -> String?  {
    var ssid: String?
    if let interfaces = CNCopySupportedInterfaces() as NSArray? {
        for interface in interfaces {
            if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? {
                ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
                break
            }
        }
    }
    return ssid
}

В iOS 12 и выше вам нужно будет включить доступ к информации Wi-Fi для вашего приложения, чтобы получить ssid