2016-12-02 17 views
1

私は、構造体にnil値があるかどうかを調べるためにリフレクションを使用しています。Anyにnilを指定したAny値をAnyにキャストする方法を教えてください。

struct MyStruct { 
    let myString: String? 
} 

let properties = Mirror(reflecting: MyStruct(myString: nil)).children.filter { $0.label != nil } 

for property in properties { 
    if property.value == nil { // value has type "Any" will always fail. 
     print("property \(property.label!) is nil") 
    } 
} 

どのようにAny型をAny型にキャストしますか?

答えて

5

は単にAnyに包まれたプロパティ値でnilコンテンツをチェックするために、あなた、他の回答に記載された方法に反して、実際に鋳造/結合/ Anyタイプ以外のコンクリートにチェックを中心にあなたのように動作することができますOptional<Any>.noneまたはOptional<Any>.some(...)にパターンマッチングを直接適用することにより、

例のセットアップ(異なるメンバーの種類:我々は単にnilコンテンツをチェック反射のためにすべてのこれらの異なるタイプに注釈を付けたくない)

struct MyStruct { 
    let myString: String? 
    let myInt: Int? 
    let myDouble: Double? 
    // ... 
    init(_ myString: String?, _ myInt: Int?, _ myDouble: Double?) { 
     self.myString = myString 
     self.myInt = myInt 
     self.myDouble = myDouble 
    } 
} 

シンプルなログ:nil値プロパティ

のプロパティ名を抽出

パターン一致がOptional<Any>.noneの場合、単にnilエンティティのログ情報をログに記録する場合:

for case (let label as String, Optional<Any>.none) in 
    Mirror(reflecting: MyStruct("foo", nil, 4.2)).children { 
    print("property \(label) is nil") 
} 
/* property myInt is nil */ 

もう少し詳細なログ:以下Optional<Any>.some(...)に一致nilだけでなく、非nil値を持つプロパティ

柄のため、場合にあなたがより多くの詳細なログをしたい(バインドさx値はnil非あなたの保証に対応Anyインスタンス)の代わりswitchケースを用い

for property in Mirror(reflecting: MyStruct("foo", nil, 4.2)).children { 
    if let label = property.label { 
     if case Optional<Any>.some(let x) = property.value { 
      print("property \(label) is not nil (value: \(x))") 
     } 
     else { 
      print("property \(label) is nil") 
     } 
    } 
} 
/* property myString is not nil (value: foo) 
    property myInt is nil 
    property myDouble is not nil (value: 4.2) */ 

または、後者:

for property in Mirror(reflecting: MyStruct("foo", nil, 4.2)).children { 
    switch(property) { 
     case (let label as String, Optional<Any>.some(let x)): 
      print("property \(label) is not nil (value: \(x))") 
     case (let label as String, _): print("property \(label) is nil") 
     default:() 
    } 
} 
/* property myString is not nil (value: foo) 
    property myInt is nil 
    property myDouble is not nil (value: 4.2) */ 
0

Stringへのキャストは、String(describing: value)またはvalue as? Stringで直接そのタイプをテストすることで回避できます。

for (label, value) in properties { 
    if !(value is String) { 
    print("Property \(label!) is nil") 
    } 
} 

enter image description here

0

あなたはAny?型にAnyをキャストすることはできません。残念ながらAnynilを保持するenum Optional<T>を実際に保持しているため、nilと比較できません。

AnyをオプションのタイプAny?にキャストしようとするのではなく、すでにAnyからStringタイプにあるオプションのタイプをキャストすることをお勧めします。あなたは、型キャストとの結合オプションを使用する必要があります:彼らは実際にはcase nonecase some(T)を評価列挙型(Optional<T>)であるため、

for property in properties { 
    if let value = property.value as? String { 
     print ("property \(property.label!) is not nil"); 
    } else { 
     print ("property \(property.label!) is nil"); 
    } 
} 

Anyタイプがoptionals含めて、何かを保持することができます。

nil == Optional<T>.none // Always returns true 

ので、代わりの方が良いですnilAnyタイプを評価することは、オプションの結合をしようとする:だからnilは、これらの例実際には1です。それが成功するならnilを持っていません、もしそれが実際にnilを持っていなければ。

0

これは最良の答えではありません。しかしそれはあなたの問題を解決することができます。

prodevmxは

nilの== Optional.noneが//常に真

を返しますので、あなただけの

if let value = property.value as? Any { 
} 

を確認することができません。この状態は常に通過して、 "どれ" それはだ、言ったようにオプションの値ではありません。

func checkAnyContainsNil(object : Any) -> Bool { 
    let value = "\(object)" 
    if value == "nil" { 
     return true 
    } 
    return false 
} 

がnilのオブジェクトを文字列に変換し、この機能を使用すると、文字列が

nilであるかどうかを確認してください
関連する問題