微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用反射在纯Swift中使用它的字符串名称获取属性的值

我想使用 Swift(不是Objective-C运行时)Reflection来创建这样的方法

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

在某种程度上,我可以这样做:

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

class TestMe {
    var x:Int!
}

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

这打印出我期望的东西:

Optional(100); 100

当我做:

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

输出是:

Optional(nil)

这似乎是合理的,除非我这样做:

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

打印出:

nil

而不是可选(零).底线是我使用我的valueFor方法以编程方式确定t2.x的值为nil时遇到困难.

如果我继续上面的代码

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

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

这些打印语句都没有输出任何内容.

当我将断点放入Xcode并使用调试器查看result2的值时,它显示

▿ Optional<Any>
  - some : nil

所以,我的问题是:如何使用valueFor的结果确定原始成员变量是否为零?

Additional1:
如果我做:

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

并在此处设置断点,x的值结果为零.但是,即使我将它分配给Any?,将它与nil进行比较也不是真的.

Additional2:
如果我做:

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

这打印出来(仅):

Optional(nil)

我发现这特别奇怪. result2打印出完全相同的东西!

解决方法

这有点像黑客,但我认为这将解决我的问题.我仍在寻找更好的解决方案:

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
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐