2016-11-04 56 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

相關問題