【问题标题】:Avoiding forced downcast from Any to CFString避免从 Any 强制向下转换为 CFString
【发布时间】:2020-02-05 18:47:13
【问题描述】:

所以这是我从另一个问题中找到的一些代码,它强制从 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 似乎要简单得多。

【问题讨论】:

  • 最好添加一个链接到问题(或答案),从那里获得您所询问的代码。
  • 尽量将 CoreFoundation 类型直接转换为 Swift 类型,而不是 typeless NSArray/NSDictionary 例如 if let interfaces = CNCopySupportedInterfaces() as? [CFString] { ...

标签: swift casting downcast cfstring


【解决方案1】:

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

【讨论】:

  • 我认为as NSDictionary?也可以替换为as? [CFString: Any]
  • 可能,但我现在实际上无法轻松测试,因为CNCopyCurrentNetworkInfo 仅适用于 iOS,我正在 macOS 上进行测试。
  • 我可以确认它在 iOS 项目中编译,但由于我所在的地方缺乏强制网络,我无法测试它。
【解决方案2】:

您可以避免强制向下转换并且通过有条件地将每个元素转换为String,然后转换为@987654324,安全地验证CNCopySupportedInterfaces 返回的CFArray 中的元素类型@ 在您的CNCopyCurrentNetworkInfo 通话中。

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 的返回值转换为[CFString] 可以避免强制向下转换,但不会安全地验证数组中元素的类型。例如,下面的 sn-p 将编译但在执行时会引发 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"))
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多