【问题标题】:Get SSID in Swift 2在 Swift 2 中获取 SSID
【发布时间】:2015-12-08 05:04:38
【问题描述】:

我正在尝试使用此代码获取 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'

感谢您的帮助

【问题讨论】:

  • 很可能,您可以删除 take(Un)RetainedValue() 调用,因为该函数在 Swift 2 中不再返回非托管对象。请参阅 stackoverflow.com/questions/30740000/… 以获取类似的问答。
  • 我删除了 .takeRetainedValue() 但现在我在尝试测试代码时得到一个 EXC_BREAKPOINT (EXC_ARM_BREAKPOINT, subcode=0xe7ffdefe)
  • 很遗憾,我无法为您提供帮助。我没有强制网络来测试代码。
  • 别担心,谢谢
  • 欢迎来到 StackOverflow!我已经格式化了您的代码,使其适合普通窗口;但你可能想再给它一次通过那里很长的线路。祝你好运!

标签: ios iphone swift ssid


【解决方案1】:

这可能对您有所帮助(在 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
    }
}

我从 Ray Wenderlich 的网站(曾经在这里: Retrieve SSID in iOS9 但现在该特定线程已从站点中删除)

iOS 12

您必须启用从功能访问 WiFi 信息。

重要 要在 iOS 12 及更高版本中使用此功能,请在 Xcode 中为您的应用启用访问 WiFi 信息功能。当您启用此功能时,Xcode 会自动将 Access WiFi Information 权利添加到您的权利文件和 App ID 中。 Documentation link

Swift4.2

public class SSID {
    class func fetchSSIDInfo() -> String {
        var currentSSID = ""
        if let interfaces = 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 let interfaceData = unsafeInterfaceData as? [String: AnyObject] {
                    currentSSID = interfaceData["SSID"] as! String
                    let BSSID = interfaceData["BSSID"] as! String
                    let SSIDDATA = interfaceData["SSIDDATA"] as! String
                    debugPrint("ssid=\(currentSSID), BSSID=\(BSSID), SSIDDATA=\(SSIDDATA)")
                }
            }
        }
        return currentSSID
    }
}

【讨论】:

  • 请记住,CNCopySupportedInterfaces 在模拟器上返回 nil。因此,您应该检查 interfaces 是否不为零。
  • 是的,其实我没有考虑过这种可能性。也许更好地检查应用程序是否在模拟器中运行,并在这种情况下返回“假”SSID(参见宏#if TARGET_IPHONE_SIMULATOR)
  • 简单的说就是:if let interfaces:CFArray! = CNCopySupportedInterfaces()
  • 请注意,CaptiveNetwork 在 iOS 9.0 中已被弃用。所以我建议使用替代解决方案。
  • iOS 10 中不再弃用 stackoverflow.com/a/33132529/2865234@MattLeFleur
【解决方案2】:

这是我的解决方案 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:注意它在模拟器上不起作用

【讨论】:

  • 这在 iOS 10 中完美运行,使用 Swift 3。谢谢!!
【解决方案3】:

目前提出的所有解决方案似乎都相当复杂,带有丑陋的不安全演员表。

我能够设计出如此简洁的解决方案(完全没有黑魔法):

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
}

【讨论】:

  • "CNCopySupportedInterfaces" 在 iOS 9.0 中已弃用。
  • 但我们没有其他选择(讨论了here 并多次在 SO)。
【解决方案4】:

在 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 

【讨论】:

    【解决方案5】:

    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
    }
    

    【讨论】:

    【解决方案6】:

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

    }

    【讨论】:

    • 此代码在 iOS 9.2 下无法编译。它仍然使用不再可用的 takeRetainedValue() 版本。
    【解决方案7】:

    以下函数返回wifi名称和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

    【讨论】:

      【解决方案8】:

      https://stackoverflow.com/users/3108877/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
          }
      

      【讨论】:

        【解决方案9】:

        您可以通过更新的 Swift 标准 @japes 答案找到另一个答案,该答案同时支持 Swift 3Swift 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
            }
        
        }
        

        【讨论】:

          【解决方案10】:

          在 Swift 中获取 WiFi 网络 SSID 和 BSSID

          我已经使用SystemConfiguration 框架看到了这个非常流行的问题的很多版本。通读这个答案列表,我发现它们无处不在。不安全的位转换,魔术字符串,奇怪的强制。每当 API 返回 CFArrayCFDictionary 时,使用免费桥接获取 NS{Array,Dictionary}。它允许您避免CoreFoundation 的一些更丑陋的方面(在 Swift 的上下文中)。此外,您应该使用在标题中定义的常量作为 SSID 和 BSSID 字典值。这里绝对不需要 Unsafe 类型,所有的数据类型都是定义良好的。也就是说,此代码的 CaptiveNetwork 版本在 iOS 14 中已弃用,建议您改用 NetworkExtension 框架。

          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

          就用户权限而言,您有可能,但您需要在文档中为 CNCopyCurrentNetworkInfofetchCurrent 定义的四个之一 - 对于大多数情况,我假设您需要添加 CoreLocation 并请求使用用户的权限地点。例如,Info.plist 中的Privacy - Location When In Use Usage Description 需要说明您需要用户位置的原因,然后您必须拨打电话以请求用户授权对话框。

              import CoreLocation
          
              CLLocationManager().requestWhenInUseAuthorization()
          

          权利

          您的应用还需要在项目的Signing and Capabilities部分添加的权利-com.apple.developer.networking.wifi-info,称为Access WiFi Information。使用NEHotspotNetwork 方法时,需要额外的网络扩展权利。

          【讨论】:

            猜你喜欢
            • 2015-09-28
            • 2021-02-05
            • 2019-04-10
            • 1970-01-01
            • 2020-06-14
            • 2019-03-31
            • 1970-01-01
            • 2023-02-22
            相关资源
            最近更新 更多