2015-07-31 8 views
8

Der Versuch, die SSID des aktuellen Geräts zu erhalten. Ich habe viele Beispiele dafür gefunden, aber ich habe Probleme mit der automatischen Vervollständigung der CNCopySupportedInterfaces. Ich habe 'Systemkonfiguration importieren' oben in meiner schnellen Datei, aber keinen Erfolg. Ich kann nicht herausfinden, was ich falsch mache.Swift CNCopySupportedInterfaces nicht gültig

Antwort

15

Sie benötigen import SystemConfiguration.CaptiveNetwork

Unter den Abdeckungen ist CaptiveNetwork eine C-Header-Datei (.h), die im Rahmen Systemconfiguration ist:

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

Wenn Sie Objective-C wissen, das geht mehr in die Tiefe:

iPhone get SSID without private library

auch die automatische Vervollständigung ist nicht glücklich mit Legacy Globals; es will nur Klassen auf oberster Ebene. Wahrscheinlich, weil es einfach zu viele @ # $ @ # Globals gibt.

Oh, und Sie haben diese wunderbare Schnipsel zu schreiben, um es Arbeit zu bekommen:

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]!)") 
     } 
    } 

NACHTRAG für SWIFT 2.2 und 3.0

Bridging vereinfacht wurde noch erneut kompliziert für CFxxx Datatypes und jetzt Auspacken und eine Menge Überfahrt ist erforderlich, aber keine Retain-Anrufe. Ich weiß nicht, dass Swift 2 die Dinge einfacher gemacht hat, aber es ist ziemlich klar, was passiert, und die nil hilft uns, den Simulator zu identifizieren. Die andere Antwort verwendet eine Menge Bit-Casting und unsichere Operationen, die nicht-Swiftian scheint, also biete ich dies an.

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 
    } 

[Auch nach 10 Minuten begann die automatische Vervollständigung für CNxxx zu arbeiten. Eindeutig ein Hintergrund-Thread beschäftigt ist Tausende von globalen Variablen in SourceKit Verdauen]

Output auf Erfolg.

SSIDDATA: < 57696c6d 79>

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

SSID: YourSSIDHere

+0

was takeRetainedValue ist()? – Nilesh

+0

Es ist für die Kompatibilität mit alten C-APIs, die keine von ARC verwalteten Objekte verwenden. Es bringt das Objekt unter ARC in die Verwaltung, so dass es automatisch freigegeben wird, wenn Sie es nicht mehr benötigen. http://stackoverflow.com/questions/29048826/when-to-use-takeunreatedvalue-or-tainerevalue-to-retrieve-unmanaged-o – BaseZen

+0

Bearbeitet für Swift 2.2 – BaseZen

8

in Swift 2.0/iOS 9 die API CaptiveNetwork ist (fast) weg oder abgeschrieben. Ich kontaktierte Apple bezüglich dieses Problems und ich dachte, wir könnten stattdessen den NEHotspotHelper verwenden (oder sollten). Ich habe eine Reaktion von Apple heute:

CNCopySupportedInterfaces 
CNCopyCurrentNetworkInfo 

Der Benutzer Braime veröffentlicht einen aktualisierten Code-Schnipsel für dieses Problem auf Ray Wenderlich forums:

Man sollte CaptiveNetwork und die beiden relevanten APIs (auch hart dort markiert abgeschriebenen) weiterverwenden
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 = "" 
     } 
    } 

Funktioniert perfekt für mich.

+0

Swift 2 + Xcode 7.2.1 Targeting-Konfiguration 'Debug' für Architektur 'x86_64' mit 'OS X 10.11' sdk beschwert sich über "Fehler: 'CNCopyCurrentNetworkInfo' ist nicht verfügbar", obwohl SystemConfiguration.CaptiveNetwork als Framework importiert wird. Irgendwelche Vorschläge, wie man aktuelle SSID bekommt? –

+0

Benötigen wir auch das Provisioning-Profil von Member Center, um auf diese Frameworks zuzugreifen? Können wir mit diesen auch ein Gerät wieder mit dem Netzwerk verbinden? –

0

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

Dann print(currentSSIDs()), nicht auf Simulator arbeiten, nur reale Geräte.

von https://forums.developer.apple.com/thread/50302 Genommen

Verwandte Themen