Reputation: 157
I recently upgraded my app from Swift 2.3 to Swift 3.0 and when I did, I got the following error:
Type 'Dictionary<NSObject, AnyObject>?' has no subscript members
The function in which it appears is as follows:
class func getSSIDConnectionName() -> String? {
var currentSSID: String?
let interfaces = CNCopySupportedInterfaces()
if interfaces == nil {
print("Got nil up here")
return nil
}
let interfaces2:CFArray! = interfaces
for i in 0..<CFArrayGetCount(interfaces2) {
let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interfaces2, i)
let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString)
if unsafeInterfaceData != nil {
let interfaceData = unsafeInterfaceData! as Dictionary!
currentSSID = interfaceData["SSID"] as? String
} else {
print("Got nil down here")
return nil
}
}
return currentSSID
}
I'm getting the error on the "current SSID =" line. This code was working fine in Swift 2.3, and unfortunately, I am not strong on things labeled as "unsafe," so if the answer delves into those regions, it be most helpful if you could explain it as simply as possible.
Thanks for reading!
Upvotes: 4
Views: 2497
Reputation: 155
The data type for the key or subscript expects "NSObject". SWIFT 3 seems to force you to cast it to the correct data type. If you have
currentSSID = interfaceData?[String("SSID") as NSObject] as? String
or
currentSSID = interfaceData?["SSID" as NSObject] as? String
the compilation will go away. Just to note that others answers would work as well.
Upvotes: 1
Reputation: 539795
In addition to what @matt said, your code can be simplified considerably,
in particular by casting the return value from CNCopySupportedInterfaces()
to a Swift [String]
array,
and optional binding if let
instead of testing against nil
and forced unwrapping:
func getSSIDConnectionName() -> String? {
guard let interfaces = CNCopySupportedInterfaces() as? [String] else {
return nil
}
for ifname in interfaces {
if let interfaceData = CNCopyCurrentNetworkInfo(ifname as CFString) as? [String: Any],
let currentSSID = interfaceData["SSID"] as? String {
return currentSSID
}
}
return nil
}
Upvotes: 4
Reputation: 535304
Change
let interfaceData = unsafeInterfaceData! as Dictionary!
to
let interfaceData = unsafeInterfaceData! as NSDictionary
Reason: unsafeInterfaceData
is a CFDictionary. A CFDictionary is directly castable to an NSDictionary, because they are toll-free bridged. That's good enough to get us subscripting, so we can use an expression like interfaceData["SSID"]
.
Upvotes: 7