2016-04-16 9 views
2

にどれをキャストすると、ここで私は仕事アレイ

struct A { 
    var x:Int = 0 
} 

struct B { 
    var y:Int = 0 
} 

var c: [String:Any] = [ 
    "a":[A()], 
    "b":[B()] 
] 

for (key, value) in c { 
    let arr = value as! [Any] 
} 

はそれだけで例外をスロー作ってみるのコードです。実行時例外はAnyを[Any]にキャストしようとすると発生します。

達成したい主なことは、Anyが配列の場合、Anyの要素を反復することです。私にはAnyを[Any]にキャストするのは自然だったが、なんらかの理由でうまくいかない。では、どうすればわかりやすいことができますか?

[Any]を[A]または[B]にキャストする回避策がいくつか見受けられましたが、配列には任意の構造体が含まれている可能性があります。

+0

私は本当にあなたのデータ構造があなたがこのようなことをしようとしているように見えるかを知りたいのです。これは[XY問題](http://meta.stackexchange.com/q/66377/244435)のように聞こえます。 – nhgrif

答えて

4

辞書の値がコレクション型であるかどうかを検査するために実行時イントロスペクションを使用することができます。子要素(配列の場合は要素)を反復処理し、実際の配列Anyに追加します。 Swiftにあなたの辞書のAnyの値が実際にはの配列であることを知らせます。

/* Example setup */ 
struct A { 
    var x: Int 
    init(_ x: Int) { self.x = x } 
} 

struct B { 
    var y: Int 
    init(_ y: Int) { self.y = y } 
} 

var c: [String:Any] = [ 
    "a": [A(1), A(2)], 
    "b": [B(3)], 
    "c": "JustAString", 
    "d": A(0) 
] 

など。あるいは

/* runtime introspection to extract array values from dictionary */ 
var commonAnyArr: [[Any]] = [] 
for (_, value) in c { 
    if case let m = Mirror(reflecting: value) 
     where (m.displayStyle ?? .Struct) == .Collection { 
     let arr = m.children.map { $0.value } 
     commonAnyArr.append(arr) 
    } 
} 

/* resulting array of any arrs, that Swift now recognize as actual arrays */ 
commonAnyArr.forEach { print($0) } 
/* [B(y: 3)] 
    [A(x: 1), A(x: 2)] */ 

commonAnyArr.flatten().forEach { print($0) } 
/* B(y: 3) 
    A(x: 1) 
    A(x: 2) */ 

を以下のように、(ただし新しい辞書にAny値によって包まれ、基礎となる値は、実際にはアレイであるcの唯一のキーと値のペアを含む、新たな辞書を構築するために、実行時イントロスペクションを使用し値がAnyの配列であることを明示的に指定します)。

/* runtime introspection to extract array values from dictionary */ 
var dictOfAnyArrs: [String: [Any]] = [:] 
for (key, value) in c { 
    if case let m = Mirror(reflecting: value) 
     where (m.displayStyle ?? .Struct) == .Collection { 
     let arr = m.children.map { $0.value } 
     dictOfAnyArrs[key] = arr 
    } 
} 

/* "remaining" dictionary keys now only with [Arr] values */ 
for (key, arr) in dictOfAnyArrs { 
    for element in arr { 
     print("Do something with element \(element)") 
    } 
    print("---") 
} 
/* Do something with element B(y: 3) 
    --- 
    Do something with element A(x: 1) 
    Do something with element A(x: 2) 
    ---        */ 

だけではなく、技術的な側面のうち、より上記(スウィフトの目と静的型付けとランタイムの安全性におけるその誇りで)やや「ハック」と考えることができ、そしておそらくほとんどが面白いことに注意してください実際の生産コードで使用されるよりも(私は個人的には自分自身の生産で上記のようなものを許可しません)。おそらく、あなたが一歩踏み出してこの問題にどのように遭遇したかを見てみると、コードを再作成して、ランタイムハッキングに頼る必要がないように設計することができます。

+0

ああありがとう、それは動作します!私が欠けていた点は、AnyがArrayの場合、Mirrorの子はその要素になります。 – user1682175

+0

@ user1682175お寄せいただきありがとうございます。あなたの質問に答えるだけでなく、私の答えの一番下にある免責事項を書き留めておいてください。質問している問題に達する前に別の方法を使用すると、上記の解決策が完全に回避される可能性がありますこの質問)。ハッピーコーディング! – dfri

+0

私は、構造体のstructsの構造体などが私のアプリケーションで持っている。私がしなければならないことは、見栄えの良いjsonの方法でコンソールにこれを印刷することです。これが私がこの問題に遭遇した場所です。 – user1682175