【问题标题】:Is it possible to cast Any to an Optional?是否可以将 Any 转换为 Optional?
【发布时间】:2015-03-15 12:54:38
【问题描述】:

假设我有一段这样的代码:

let x: Int? = 10  
let y: Any = x

现在我想将 y 转换为 Int?:

let z = y as Int? // Error: Cannot downcast from 'Any' to a more optional type 'Int?'

这是不可能的还是有其他方法?

【问题讨论】:

    标签: swift casting optional


    【解决方案1】:

    对于 Swift 2.0,您可以使用以下内容:

    let x: Int? = 10
    let y: Any = x
    let z = Mirror(reflecting: y).descendant("Some") as? Int
    

    或者作为一个函数:

    func castToOptional<T>(x: Any) -> T? {
        return Mirror(reflecting: x).descendant("Some") as? T
    }
    let x: Int? = 10
    let y: Any = x
    let z: Int? = castToOptional(y)
    

    如果您不喜欢反射,也可以这样做:

    func castToOptional<T>(x: Any) -> T {
        return x as! T
    }
    let x: Int? = 10
    let y: Any = x
    let z: Int? = castToOptional(y)
    

    【讨论】:

    • 我认为此方法无法将 Any 转换为 Swift 3 / xcode 8 中的类型可选。
    • 啊哈! some 中的小写“s”。阅读发行说明有时很有用!对于 swift 3,请使用 let z = Mirror(reflecting: y).descendant("some") as? Int
    • Mirror(reflecting: x).descendant(…) 方法在 Swift 3 中不起作用(Mirror(reflecting: x).children.count0),但 return x as! T 可以!出于某种奇怪的原因,尝试执行(myAnyVar as! SCNRenderingAPI?) 会给我一个编译时错误error: cannot downcast from 'Any' to a more optional type 'SCNRenderingAPI?',但是在函数内部执行与您所拥有的相同的转换效果很好。干杯! |建议编辑:“或者,如果你不喜欢 Reflection,你可以这样做:”“或者你可以在 Swift 3 中这样做,或者如果你不喜欢 Reflection:”我>
    【解决方案2】:
    func castAsOptionalInt(value: Any)->Int? {
        let mirror = Mirror(reflecting:value)
        if mirror.subjectType == Optional<Int>.self {
            let ret = mirror.children.first?.1
            return ret as? Int
        } else {
            return nil
        }
    }
    
    let x: Int? = 10
    let y: Any = x
    let z = castAsOptionalInt(y) // 10
    let a: Double? = 10
    let b: Any = a
    let c = castAsOptionalInt(b) // nil
    

    【讨论】:

      【解决方案3】:

      您可以这样做以获得 Any 上的可选输出

      func unwrap(any:Any) -> Any? {
          let mi:MirrorType = reflect(any)
          if mi.disposition != .Optional {
              return any
          }
          if mi.count == 0 { return nil } // Optional.None
          let (name,some) = mi[0]
          return some.value
      }
      

      所以在你的情况下,

      let z = unwrap(y) as? Int

      参考:How to unwrap an optional value from Any type?

      【讨论】:

      • 但无法进行强制转换..它返回 nil
      【解决方案4】:

      这个解决方案怎么样,我做了之前答案的通用版本。

      fileprivate func unwrap<T>(value: Any)
        -> (unwraped:T?, isOriginalType:Bool) {
      
        let mirror = Mirror(reflecting: value)
        let isOrgType = mirror.subjectType == Optional<T>.self
        if mirror.displayStyle != .optional {
          return (value as? T, isOrgType)
        }
        guard let firstChild = mirror.children.first else {
          return (nil, isOrgType)
        }
        return (firstChild.value as? T, isOrgType)
      }
      
      let value: [Int]? = [0]
      let value2: [Int]? = nil
      
      let anyValue: Any = value
      let anyValue2: Any = value2
      
      let unwrappedResult:([Int]?, Bool)
        = unwrap(value: anyValue)    // ({[0]}, .1 true)
      let unwrappedResult2:([Int]?, Bool)
        = unwrap(value: anyValue2)  // (nil, .1 true)
      let unwrappedResult3:([UInt]?, Bool)
        = unwrap(value: anyValue)  // (nil, .1 false)
      let unwrappedResult4:([NSNumber]?, Bool)
        = unwrap(value: anyValue)  ({[0]}, .1 false)
      

      以下是 Playground 上的代码。

      【讨论】:

        【解决方案5】:

        如果有人正在寻找即插即用的字典解决方案,类似这样:

        extension Dictionary where Value == Any {
            func typedValue<T>(forKey key: Key) -> T? {
                if let anyValue: Any = self[key] {
                    return (anyValue as! T)
                }
                return nil
            }
        
            func optionalTypedValue<T>(forKey key: Key) -> T?? {
                return self.typedValue(forKey: key)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-09-14
          • 1970-01-01
          • 2018-11-21
          • 2010-09-28
          • 1970-01-01
          • 2021-10-28
          • 2021-10-15
          • 2020-11-24
          相关资源
          最近更新 更多