Получить 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
}
}