避免从 Any 强制向下转换为 CFString

Avoiding forced downcast from Any to CFString

所以这是我从另一个问题中找到的一些代码,它强制从 Any 向下转换为 CFString

import SystemConfiguration.CaptiveNetwork

func fetchSSIDInfo() -> String? {
    var ssid: String?
    if let interfaces = CNCopySupportedInterfaces() as NSArray? {
        for interface in interfaces {
            // is there any way to remove the force downcast below 
            if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? {
                ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
                break
            }
        }
    }
    return ssid
}

你必须使用强制向下转换还是有其他方法?处理旧的 Corefoundation 对象时是否有特殊规则?因为使用 NSObjects 似乎简单多了。

导入 Foundation 为编译器提供有关 Core Foundation 类型和 Foundation 类型之间桥接的信息。然后根据需要投射数组:

import Foundation
import SystemConfiguration.CaptiveNetwork

func fetchSSIDInfo() -> String? {
    var ssid: String?
    if let interfaces = CNCopySupportedInterfaces() as? [CFString] {
        for interface in interfaces {
            if let interfaceInfo = CNCopyCurrentNetworkInfo(interface) as NSDictionary? {
                ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
                break
            }
        }
    }
    return ssid
}

您可以避免强制向下转换 通过条件转换安全地验证 CFArray return 中的元素类型 CNCopySupportedInterfaces每个元素到 String,然后到 CNCopyCurrentNetworkInfo 调用中的 CFString

func fetchSSIDInfo() -> String? {
    var ssid: String?
    if let interfaces = CNCopySupportedInterfaces() as NSArray? {
        for cfInterface in interfaces {
            guard let interface = cfInterface as? String else {
                continue
            }
            if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as CFString) as NSDictionary? {
                ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
                break
            }
        }
    }
    return ssid
}

有条件地将 CNCopySupportedInterfaces 的 return 值转换为 [CFString] 可以避免强制向下转换,但不会安全地验证数组中元素的类型。例如,以下代码片段将编译但在执行时引发 NSException。

let cfArray = [1 as CFNumber, 2 as CFNumber] as CFArray
if let arrayOfStrings = cfArray as? [CFString] {
    for e in arrayOfStrings {
        print((e as String).appending("foo"))
    }
}