【问题标题】:Determine if Any.Type is Optional确定 Any.Type 是否是可选的
【发布时间】:2015-09-12 07:39:20
【问题描述】:

我正在尝试确定给定类型 t (Any.Type) 是否为可选类型,我正在使用此测试

t is Optional<Any>.Type

但它总是返回 false。

那么有什么办法可以做到吗?

【问题讨论】:

    标签: swift dynamic


    【解决方案1】:

    假设你想要做的是这样的:

    let anyType: Any.Type = Optional<String>.self
    anyType is Optional<Any>.Type // false
    

    遗憾的是 swift 目前(从 Swift 2 开始)不支持 covariance nor contravariance 并且无法直接针对 Optional.Type 进行类型检查:

    // Argument for generic parameter 'Wrapped' could not be inferred
    anyType is Optional.Type // Causes error
    

    另一种方法是让Optional 扩展特定协议,并检查该类型:

    protocol OptionalProtocol {}
    
    extension Optional : OptionalProtocol {}
    
    let anyType: Any.Type = Optional<String>.self
    anyType is OptionalProtocol.Type // true
    

    【讨论】:

    【解决方案2】:

    聚会有点晚了。但是,我遇到了同样的问题。这是我的代码。

    func isOptional(_ instance: Any) -> Bool {
        let mirror = Mirror(reflecting: instance)
        let style = mirror.displayStyle
        return style == .optional
    }
    
    let a: Int = 1 // false
    let b: Int? = 2 // true
    let c: Double = 3.0 // false
    let d: Double? = 4.0 // true
    let e: NSString = "Hello" // false
    let f: NSString? = "Hello" // true
    
    
    isOptional(a) // fasle
    isOptional(b) // true - warning
    isOptional(c) // false
    isOptional(d) // true - warning
    isOptional(e) // false
    isOptional(f) // true - warning
    

    我觉得不错。 swift4

    【讨论】:

      【解决方案3】:

      你可以这样做:

      extension Mirror {
          static func isOptional(any: Any) -> Bool {
              guard let style = Mirror(reflecting: any).displayStyle,
                  style == .optional else { return false }
              return true
          }
      }
      

      用法:

      XCTAssertTrue(Mirror.isOptional(any: Optional(1)))
      

      或者如果您需要从 Any 转换为 Optional

      protocol _Optional {
          var isNil: Bool { get }
      }
      
      extension Optional: _Optional {
          var isNil: Bool { return self == nil }
      }
      
      func isNil (_ input: Any) -> Bool {
          return (input as? _Optional)?.isNil ?? false
      }
      

      用法:

      isNil(nil as String?) // true
      isNil("") // false
      

      【讨论】:

        【解决方案4】:

        Optionals 符合ExpressibleByNilLiteral,所以你可以使用它:

        let t = Optional<String>.self
        t is ExpressibleByNilLiteral.Type // true
        

        【讨论】:

        • 值得注意的是,Apple 说“只有 Optional 类型符合 ExpressibleByNilLiteral。不鼓励将 nil 用于其他目的的类型符合 ExpressibleByNilLiteral。”。否则,这只是一个必要条件,而不是充分条件。
        【解决方案5】:

        您可以使用泛型来实现此目的:

        func isOptional<T>(x:T?)->Bool
        {
            return true
        }
        
        func isOptional<T>(x:T)->Bool
        {
            return false
        }
        

        编辑

        上面的代码可以用来判断一个变量是否是可选类型。 我想出了解变量包含类型的唯一方法是使用反射:

        var t1:Any.Type=(String?).self
        var t2:Any.Type=(String).self
        Mirror(reflecting: t1).description
        Mirror(reflecting: t2).description
        

        对 Mirror 的第一次调用给出字符串 "Mirror for Optional&lt;String&gt;.Type",第二次给出"Mirror for String.Type"

        我知道比较字符串不是一种方便的检查方式,我会再次尝试寻找更高效的东西..

        【讨论】:

        • t 从来都不是可选的,它始终是一个类型对象(可能代表一个可选),所以总是会调用第二种方法。
        猜你喜欢
        • 2018-08-03
        • 1970-01-01
        • 2012-04-11
        • 1970-01-01
        • 2013-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多