2016-11-04 58 views
1

给定Any类型的值是否可以检查并查看它是否是可选的? 此代码不起作用,因为不是检查,看它是否是可选的它是不是试图投它,和它@ dfri的解决方案通过鉴于Swift的`Any`类型,我可以确定它是否是`Optional`?

let a: Any = "5" 

switch a { 
case let optional as Optional<Any>: 
    if case .some(let value) = optional { 
     print("wrapped value of `\(a)` is `\(value)`") 
    } 

default: 
    print("\(a) is not an optional") 
} 

基地

private func isOptional(input: Any) -> Bool { 
    let mirror = Mirror(reflecting: input) 
    let style = mirror.displayStyle 

    switch style { 
    case .some(.optional): 
     return true 
    default: 
     return false 
    } 
} 
+0

只是好奇,为什么你想在运行时检查一个变量是可选的?通常,当您查看代码时,您已经知道该期待什么。我不是说你做错了什么,只是想知道。 –

+1

在你的代码中,'a'是_typed_ as Any。因此它可以不是'可选'。 – matt

+1

@matt我认为op是想知道由非可选的'Any'实例_包装的值是否可选(不是我有什么想法,这将是有用的)。 – dfri

回答

1

你可以使用运行时自检Mirror

let foo: String? = "foo" 
let bar: String = "bar" 
var a: Any = foo 

// if wrapping an optional, the reflection of the value has 
// a displaystyle "optional" 
if let displayStyle = Mirror.init(reflecting: a).displayStyle { 
    print(displayStyle) // optional 
} 

// for a non-optional fundamental native type: no displaystyle 
a = bar 
if let displayStyle = Mirror.init(reflecting: a).displayStyle { 
    print(displayStyle) 
} // prints nothing 

可选/可选示例,其中,基础类型是用户定义的(非天然的):

struct Foo {} 
let foo: Foo? = Foo() 
let bar: Foo = Foo() 
var a: Any = foo 

// if wrapping an optional, the reflection of the value has 
// a displaystyle "optional" 
if let displayStyle = Mirror(reflecting: a).displayStyle { 
    print(displayStyle) // optional 
} 

// for a non-optional non-fundamental type: 
a = bar 
if let displayStyle = Mirror(reflecting: a).displayStyle { 
    print(displayStyle) // struct 
} 

如果不想需要使用绑定displayStyle变量(例如打印),而只是想检查包裹的值是否是任何形式的可选项,你可以添加一个布尔条款,规定持有displayStyle案件可选结合if声明,

if let displayStyle = Mirror(reflecting: a).displayStyle, 
    displayStyle == .optional { 
    // is an optional ... 
} 

...或删除使用零合并运算符,取而代之的是单个条件表达式完全结合(??

if Mirror(reflecting: a).displayStyle ?? .class == .optional { 
    // is an optional 
} 

注意然而,对于上述所有的方法中,这简单地告诉您如dev的由Any实例包裹类型是可选的还是不是:Swifts输入系统stil我对此一无所知。

+0

谢谢,使用displayStyle工程很好,如果我没有找到一个不使用反射的更清洁的解决方案,我会接受 – aryaxt

+0

@aryaxt高兴地帮助! – dfri

0
let a: Any = "5" 
let b: Any? = "5" 

if type(of: a) == Optional<Any>.self { 
    print("a is optional") 
} else { 
    print("a is not optional") 
} 

if type(of: b) == Optional<Any>.self { 
    print("b is optional") 
} else { 
    print("b is not optional") 
} 

/* 
a is not optional 
b is optional 
*/ 

另一个例子......

let a: Any = 5 
let b: Any? = 5 
let c: Any = "5" 
let d: Any? = "5" 


let arr: [Any] = [a,b as Any,c,d as Any] 
arr.forEach { (x) in 
    print(type(of: x)) 
} 

/* 
Int 
Optional<Any> 
String 
Optional<Any> 
*/ 
+0

此解决方案不适用于以下输入:“let a =”5“ ,let b = Optional.some(”5“)' ''' – aryaxt

+0

@aryaxt因为您示例中的b具有类型Optional ,请检查它的类型(of:Optional.some(“5”)) – user3441734

+0

我需要一个动态的解决方案,可以随时使用并涵盖所有情况。 @ dfri的答案解决了问题 – aryaxt

相关问题