我看不到空协议如何改变反映对象的能力。通常无法对AnyObject
进行反思吗?如果是这样,那为什么呢?
示例:
protocol Protocol {}
struct Bar : Protocol {
let bar: String
}
let bar = Bar(bar: "bar") as Protocol
for (label, value) in Mirror(reflecting: bar).children {
print("property: \(label!), value: \(value)")
}
打印
property: bar, value: bar
而
struct Baz {
let baz: String
}
let baz = Baz(baz: "baz") as AnyObject
for (label, value) in Mirror(reflecting: baz).children {
print("property: \(label!), value: \(value)")
}
打印
(嗯,什么都没有。)
答案 0 :(得分:0)
将实例投射到AnyObject
将破坏该实例的类型。
在您的情况下,通用类型可能会解决您的问题。
func checkProperties<T: Any>(of instance: T) {
let children: Mirror.Children
children = Mirror(reflecting: instance).children
children.forEach {
print($0.label, $0.value)
}
}
现在,您可以在任何对象上调用此函数,而无需像这样进行投射:
checkProperties(of: Baz(baz: "baz"))
这意味着该函数需要从Any
继承的任何实例,但它将保持其类型
答案 1 :(得分:0)
要保留类型,请使用Any
代替AnyObject
,例如
let anyBaz = Baz(baz: "baz") as Any
var anyBazMirror = Mirror(reflecting:anyBaz)
var anyBazType = anyBazMirror.subjectType
print(anyBazType == Baz.self) // true
for (label, value) in anyBazMirror.children {
print("any property: \(label!), value: \(value)")
}
AnyObject
怎么了?顾名思义,AnyObject
旨在表示任何 object 。因此,在理想情况下,我们会期望出现编译器错误,指出您的结构Baz
不是引用类型,因此不是对象,因此无法转换为此类。
多亏了Object C的传统,我们有时需要像向对象“传递”值之类的行为,因为Swift中的许多类型(如数组,字符串等)都是值类型,但是Objective C API需要对象。
因此,有一些编译器技巧可以最大程度地减少人工铸造狂欢。如果将值类型转换为AnyObject
,则编译器通过调用内部函数Swift._bridgeAnythingToObjectiveC
将装箱为中间类型:
此框会产生一些奇怪的中间内部类型,您可以在使用例如print(String(describing: baz))
:
__ lldb_expr_77.Baz(baz:“ baz”)
尽管如此,它只是桥接而已,没有被破坏 。如果可以将其转换回原来的结构,则可以再次获得全部款项:
// from above:
// let baz = Baz(baz: "baz") as AnyObject
let bazStruct = baz as! Baz
for (label, value) in Mirror(reflecting: bazStruct).children {
print("property: \(label!), value: \(value)")
}