Получить SSID в Swift 2

Я пытаюсь использовать этот код для получения SSID

import Foundation
import SystemConfiguration.CaptiveNetwork

public class SSID {
    class func getSSID() -> String{
        var currentSSID = ""
        let interfaces = CNCopySupportedInterfaces()
        if interfaces != nil {
            let interfacesArray = interfaces.takeRetainedValue() as [String : AnyObject]
            if interfacesArray.count > 0 {
                let interfaceName = interfacesArray[0] as String
                let unsafeInterfaceData = CNCopyCurrentNetworkInfo(interfaceName)
                if unsafeInterfaceData != nil {
                    let interfaceData = unsafeInterfaceData.takeRetainedValue() as Dictionary!
                    currentSSID = interfaceData[kCNNetworkInfoKeySSID] as! String
                    let ssiddata = NSString(data:interfaceData[kCNNetworkInfoKeySSIDData]! as! NSData, encoding:NSUTF8StringEncoding) as! String
                    // ssid data from hex
                    print(ssiddata)
                }
            }
        }
        return currentSSID
    }
}

Но при получении ошибки в этой строкеlet interfacesArray = interfaces.takeRetainedValue() as [String : AnyObject]

Ошибка

Value of type 'CFArray?' has no member 'takeRetainedValue'

Спасибо за вашу помощь

9 ответов

Это может вам помочь (проверено на Swift 2):

import Foundation
import SystemConfiguration.CaptiveNetwork

public class SSID {
    class func fetchSSIDInfo() -> String {
        var currentSSID = ""
        if let interfaces = 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
                }
            }
        }
        return currentSSID
    }
}

Я взял и адаптировал код с сайта Рэя Вендерлиха (когда-то был здесь: восстановить SSID в iOS9, но теперь конкретный поток был удален с сайта)

Это мое решение Swift 3 iOS 10 и оно хорошо работает с Xcode 8

import Foundation

import SystemConfiguration.CaptiveNetwork

class network : NSObject {

    func getSSID() -> String? {

        let interfaces = CNCopySupportedInterfaces()
        if interfaces == nil {
            return nil
        }

        let interfacesArray = interfaces as! [String]
        if interfacesArray.count <= 0 {
            return nil
        }

        let interfaceName = interfacesArray[0] as String
        let unsafeInterfaceData =     CNCopyCurrentNetworkInfo(interfaceName as CFString)
        if unsafeInterfaceData == nil {
            return nil
        }

        let interfaceData = unsafeInterfaceData as! Dictionary <String,AnyObject>

        return interfaceData["SSID"] as? String
    }

}

Чтобы использовать это:

let wifiName = network().getSSID()

    guard wifiName != nil else {

        //// TODO: Alert -----
        print("no wifi name")

        return
    }


    print("my network name is: \(wifiName!)")

PS: Внимание это не работает на симуляторе

Все представленные на данный момент решения кажутся довольно сложными, с некрасивыми небезопасными забросками.

Я смог выработать такое краткое решение (без черной магии):

import Foundation
import SystemConfiguration.CaptiveNetwork

func getSSID() -> 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
}

В Swift 3 (работает в реальном устройстве и симуляторе):

import SystemConfiguration.CaptiveNetwork

internal class SSID {
    class func fetchSSIDInfo() ->  String {
        var currentSSID = ""
        if let interfaces:CFArray = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
                let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces, i)
                let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
                let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString)
                if unsafeInterfaceData != nil {

                    let interfaceData = unsafeInterfaceData! as Dictionary!
                    currentSSID = ((interfaceData as? [String : AnyObject])?["SSID"])! as! String

                }
            }
        }
        return currentSSID
    }
}

Использование:

SSID.fetchSSIDInfo()

//will return "" if no connected wifi or running in simulator 

Версия Swift 4

import SystemConfiguration.CaptiveNetwork


func getSSID() -> String? {
    guard let interface = (CNCopySupportedInterfaces() as? [String])?.first,
        let unsafeInterfaceData = CNCopyCurrentNetworkInfo(interface as CFString) as? [String: Any],
        let ssid = unsafeInterfaceData["SSID"] as? String else{
            return nil
    }
    return ssid
}

В Swift 2 вам не нужно звонить takeRetainedValue,

Заменить код interfaces.takeRetainedValue() as [String : AnyObject] с Array(arrayLiteral: interfaces),

Также не забудьте изменить код interfacesArray[0] as String в String(interfacesArray[0]),

Полный код :

public class SSID {
class func getSSID() -> String{
    var currentSSID = ""
    let interfaces = CNCopySupportedInterfaces()
    if interfaces != nil {
        let interfacesArray = Array(arrayLiteral: interfaces)
        if interfacesArray.count > 0 {
            let interfaceName =  String(interfacesArray[0])
            let unsafeInterfaceData = CNCopyCurrentNetworkInfo(interfaceName)
            if unsafeInterfaceData != nil {
                let interfaceData = unsafeInterfaceData.takeRetainedValue() as Dictionary!
                currentSSID = interfaceData[kCNNetworkInfoKeySSID] as! String
                let ssiddata = NSString(data:interfaceData[kCNNetworkInfoKeySSIDData]! as! NSData, encoding:NSUTF8StringEncoding) as! String
                // ssid data from hex
                print(ssiddata)
            }
        }
    }
    return currentSSID
}

}

Получение SSID и BSSID сети Wi-Fi в Swift

Я видел множество вариантов этого очень популярного вопроса с использованием SystemConfigurationфреймворк. Читая этот список ответов, я обнаружил, что они повсюду. Небезопасный битовый кастинг, волшебные струны, странное принуждение. Каждый раз, когда API возвращается CFArray или же CFDictionary используйте бесплатный мост, чтобы получить NS{Array,Dictionary}. Это позволяет избежать некоторых уродливых аспектов (в контексте Swift) CoreFoundation. Также вы должны использовать константы, определенные в заголовке, для значений словаря SSID и BSSID. Здесь нет необходимости в небезопасных типах, все типы данных четко определены. Тем не менее, версия этого кода CaptiveNetwork устарела в iOS 14, и рекомендуется использовать NetworkExtension framework вместо этого.

NEHotspotNetwork

import NetworkExtension

NEHotspotNetwork.fetchCurrent { hotspotNetwork in
    if let ssid = hotspotNetwork?.ssid {
        print(ssid)
    }
}

Не рекомендуется - метод CaptiveNetwork

import SystemConfiguration.CaptiveNetwork

func getWiFiNetwork() -> (ssid: String, bssid: String)?
{
    var wifiNetwork: (ssid: String, bssid: String)?
    if let interfaces = CNCopySupportedInterfaces() as NSArray? {
        for interface in interfaces {
            let name = interface as! CFString
            if let interfaceData = CNCopyCurrentNetworkInfo(name) as NSDictionary? {
                if let ssid = interfaceData[kCNNetworkInfoKeySSID] as? String,
                    let bssid = interfaceData[kCNNetworkInfoKeyBSSID] as? String {
                    wifiNetwork = (ssid: ssid, bssid: bssid)
                }
            }
        }
    }
    
    return wifiNetwork
}

Разрешения - CoreLocation

Что касается прав пользователей, у вас есть возможности, но вам нужен один из четырех, определенных в документации для CNCopyCurrentNetworkInfo или fetchCurrent - в большинстве случаев я предполагаю, что вам нужно будет добавить CoreLocation и запросить разрешение на использование местоположения пользователя. Например, Privacy - Location When In Use Usage Description в Info.plist нужна причина, по которой вам требуется местоположение пользователя, а затем вы должны сделать вызов, чтобы запросить диалоговое окно авторизации пользователя.

    import CoreLocation

    CLLocationManager().requestWhenInUseAuthorization()

Права

Ваше приложение также нуждается в разрешении - com.apple.developer.networking.wifi-infoкоторый добавлен в раздел проекта " Подпись и возможности " и называется " Информация о доступе к Wi-Fi". Когда используешь NEHotspotNetworkметода требуется дополнительное разрешение Network Extensions.

Следующая функция возвращает имя Wi-Fi и адрес Mac

    func getNetworkInfo()->(success:Bool,ssid:String,mac:String){
      var currentSSID:String = ""
      var macAdrees:String = ""
      var succes:Bool = false
      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
            macAdrees = interfaceData["BSSID"] as! String
            succes = true
        } else {
            currentSSID = ""
        }
    }

    return (succes, currentSSID, macAdrees)
}

Этот код работает нормально. Вы заметите некоторое предупреждение в своей цели разработки>= iOS9

Rob ответ - более короткая версия

func getSSID() -> String? {
        if let interface = (CNCopySupportedInterfaces() as? [String])?.first,
            let unsafeInterfaceData = CNCopyCurrentNetworkInfo(interface as CFString) as? [String: Any],
            let ssid = unsafeInterfaceData["SSID"] as? String {
            return ssid
        }
        return nil
    }

Вы можете найти другой ответ с обновленными стандартами Swift @japes answer, который поддерживает Swift 3 и Swift 4. Вернуться пусто "" на тренажерах.

import SystemConfiguration.CaptiveNetwork

internal class SSID {

    class func fetchSSIDInfo() -> String {
        var currentSSID = ""
        if let interfaces = CNCopySupportedInterfaces() {
            for i in 0..<CFArrayGetCount(interfaces){
                let interfaceName = CFArrayGetValueAtIndex(interfaces, i)
                let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
                guard let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString) else {
                    return currentSSID
                }
                guard let interfaceData = unsafeInterfaceData as? [String: Any] else {
                    return currentSSID
                }
                guard let SSID = interfaceData["SSID"] as? String else {
                    return currentSSID
                }
                currentSSID = SSID
            }
        }
        return currentSSID
    }

}
Другие вопросы по тегам