Getting property value using its string name in pure Swift using reflection

I want to use Swift (not Objective-C runtime) Reflection to create a method like this:

func valueFor(property:String, of object:Any) -> Any? {
    ...
}

To some extent I can do this using:

func valueFor(property:String, of object:Any) -> Any? {
    let mirror = Mirror(reflecting: object)
    return mirror.descendant(property)
}

FROM

class TestMe {
    var x:Int!
}

let t = TestMe()
t.x = 100
let result = valueFor(property: "x", of: t)
print("\(result); \(result!)")

Will print what I expect:

Optional (100); one hundred

When I do this:

let t2 = TestMe()    
let result2 = valueFor(property: "x", of: t2)
print("\(result2)")

Output:

Optional (zero)

This may seem reasonable, except if:

var x:Int!
print("\(x)")

This produces:

zero

but not Optional(nil). The bottom line is that I have difficulty programmatically determining that a value t2.xis equal nilusing the method valueFor.

If I continue the above code with

if result2 == Optional(nil)! {
    print("Was nil1")
}

if result2 == nil {
    print("Was nil2")
}

None of these operators printprint anything.

Xcode result2 , :

▿ Optional<Any>
  - some : nil

, : , - , valueFor?

Additional1: :

switch result2 {
case .some(let x):
    // HERE
    break
default:
    break
}

HERE, x nil. , Any?, nil .

Additional2: :

switch result2 {
case .some(let x):
    let z:Any? = x
    print("\(z)")
    if z == nil {
        print("Was nil3")
    }
    break
default:
    break
}

():

()

. result2 ​​ !

+6
1

, , . :

func isNilDescendant(_ any: Any?) -> Bool {
    return String(describing: any) == "Optional(nil)"
}

func valueFor(property:String, of object:Any) -> Any? {
    let mirror = Mirror(reflecting: object)
    if let child = mirror.descendant(property), !isNilDescendant(child) {
        return child
    }
    else {
        return nil
    }
}
+2

Source: https://habr.com/ru/post/1017007/


All Articles