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)
}
With
class TestMe {
var x:Int!
}
let t = TestMe()
t.x = 100
let result = valueFor(property: "x", of: t)
print("\(result); \(result!)")
This prints out what I'd expect:
Optional(100); 100
When I do:
let t2 = TestMe()
let result2 = valueFor(property: "x", of: t2)
print("\(result2)")
The output is:
Optional(nil)
This might seem reasonable, except that if I do:
var x:Int!
print("\(x)")
This prints out:
nil
and not Optional(nil)
. The bottom line is that I'm having difficulty programmatically determining that the value of t2.x
is nil
using my valueFor
method.
If I continue the above code with:
if result2 == Optional(nil)! {
print("Was nil1")
}
if result2 == nil {
print("Was nil2")
}
Neither of these print
statements output anything.
When I put a breakpoint into Xcode and look at the value of result2
with the debugger, it shows:
▿ Optional<Any>
- some : nil
So, my question is: How can I determine if the original member variable was nil using the result from valueFor
?
Additional1: If I do:
switch result2 {
case .some(let x):
// HERE
break
default:
break
}
and put a breakpoint at HERE
, the value of x turns out to be nil
. But, even if I assign it to an Any?
, comparing it to nil
is not true.
Additional2: If I do:
switch result2 {
case .some(let x):
let z:Any? = x
print("\(z)")
if z == nil {
print("Was nil3")
}
break
default:
break
}
This prints out (only):
Optional(nil)
I find this especially odd. result2
prints out exactly the same thing!
This is a bit of a hack, but I think it's going to solve the problem for me. I'm still looking for better solutions:
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With