我想使用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!)")
这打印出我期望的内容:
可选(100); 100
当我这样做时:
let t2 = TestMe()
let result2 = valueFor(property: "x", of: t2)
print("\(result2)")
输出结果为:
可选(无)
这似乎是合理的,除非我这样做:
var x:Int!
print("\(x)")
打印出来:
零
而不是Optional(nil)
。最重要的是,我无法使用我的t2.x
方法以编程方式确定nil
的值为valueFor
。
如果我继续上述代码:
if result2 == Optional(nil)! {
print("Was nil1")
}
if result2 == nil {
print("Was nil2")
}
这些print
语句都没有输出任何内容。
当我将断点放入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
打印出完全相同的东西!
答案 0 :(得分:2)
这有点像黑客,但我认为它会为我解决问题。我还在寻找更好的解决方案:
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
}
}
答案 1 :(得分:0)
好吧,我知道已经 4 年了,但我使用的是 Xcode 12 并且仍然面临同样的问题。由于这个问题似乎没有答案,我将添加对我有用的内容。
func valueFor(property: String, of object: Any) -> Any? {
let optionalPropertyName = "some"
let mirror = Mirror(reflecting: object)
if let child = mirror.descendant(property) {
if let optionalMirror = Mirror(reflecting: child), optionalMirror.displayStyle == DisplayStyle.optional {
return optionalMirror.descendant(optionalPropertyName)
} else {
return child
}
} else {
return nil
}
}
通过使用 Mirror 检查可选项,然后使用“some”提取可选项,您将返回一个真正的对象或 nil。当它通过 Any? 返回给调用者时?返回,您现在可以检查该值并使其正常工作。