【问题标题】:Swift 3 Protocol casting on Any value containing OptionalSwift 3 协议强制转换任何包含 Optional 的值
【发布时间】:2023-03-24 00:04:01
【问题描述】:

这是一些奇怪的行为,我有一个 Any 类型的值,我希望打开它的协议一致性,当该值的 real 类型是可选的时,它不起作用:

let something: Int? = 42

switch something {
case let x as Equatable: print("Yeepee! The answer is \(x)") // Here's what is matched
default: print("Boohoo!") 
}

let anything: Any = something // anything contains a Int? value

switch anything {
case let x as Equatable: print("Yeepee! The answer is \(x)")
default: print("Boohoo!")  // Here's what is matched
}

首先我根本不明白为什么行为不同,那么我怎样才能使第二个开关正确匹配该值,即使它是可选的?

提前致谢。

【问题讨论】:

  • 谢谢,但不幸的是它使用了反射 API,目前该 API 旨在供 Playground 或内部调试器使用,而不是用于生产代码。此外,reflect 函数在 Swift 3 中不可用。
  • 是的,这确实是一个很好的例子(实际上是典型的例子之一)为什么Any 在 Swift 中是一个如此可怕的类型,需要尽可能地加以限制。基本上,这是一个“如果你需要这个,你就走错路了”的情况。 Swift 在面对Any 时会不断爆炸(而在面对AnyObject 时只会稍微小一点),而最微妙和最普遍的爆炸版本之一是它与 Optional Promotion 交互以完成所有操作各种你没想到的事情。

标签: swift casting protocols swift3 optional


【解决方案1】:

感谢@Shadow,我想出了这个解决方案,但正如我所说,它使用反射 API,它不是用于生产,而是更多用于 Playground 或调试器:

func forceUnwrap(any:Any) -> Any {
    let mirror = Mirror(reflecting: any)

    if mirror.displayStyle != .optional {
        return any
    }

    if mirror.children.count == 0 {
        return NSNull()
    }

    let (_, some) = mirror.children.first!

    return forceUnwrap(any: some)
}

switch forceUnwrap(any:anything) {
case let x as Equatable: print("Yeepee! \(x)")
default: print("Boohoo!")
}

但如果有人有使用反射 API 的解决方案,我将不胜感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    相关资源
    最近更新 更多