LoginSignup
7
2

More than 5 years have passed since last update.

SwiftのAnyに突っ込まれたOptionalを取り出す

Posted at

Anyに代入したOptional

まずは検証のためのコード

protocol A { }

protocol B: A { }

class C: B { }

class D {
    var c: C?
}

let c: C = C()
let d: D = D()

c.dis Aであることを判定する。

Anyに埋もれたOptional(Type)

func checkAny(value: Any) {
    switch value {
    case is A:
        print("is A")
    default:
        print("is not A")
    }
}

checkAny(value: d.c)
d.c = c
checkAny(value: d.c)
checkAny(value: c)
// 結果
is not A
is not A
is A

だめだ。。

素晴らしい援護射撃
https://twitter.com/hiragram/status/935858469298626565

そこで引数を修正AnyAny?に変更

func checkOptionalAny(value: Any?) {

    guard let value = value else {
        print("is nil")
        return
    }

    switch value {
    case is A:
        print("is A")
    default:
        print("is not A")
    }
}

checkOptionalAny(value: d.c)
d.c = c
checkOptionalAny(value: d.c)
checkOptionalAny(value: c)
// 結果
is A
is A
is A

でけた!

がしかし!

Mirrorの中のAnyに中に埋もれるvalue

d.c = c
let mirror = Mirror(reflecting: d)
mirror.children.forEach { (key, value) in
    checkOptionalAny(value: value)
}
// 結果
is not A

MirrorしちゃうとAny?にできないじゃない。😅

がしかし!
この関数を使ってみる。

func unwrap(_ value: Any) -> Any? {
    let mirror = Mirror(reflecting: value)
    if let (_, v) = mirror.children.first {
        return v
    }
    return nil
}
d.c = c
let mirror = Mirror(reflecting: d)
mirror.children.forEach { (key, value) in
    checkOptionalAny(value: value)
    checkOptionalAny(value: unwrap(value))
}
is not A
is A

ついにでけた!

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2