关于Swift中AnyObject的思考

时间:2018-07-10 18:03:09

标签: swift reflection

我看不到空协议如何改变反映对象的能力。通常无法对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)")
}

打印

 

(嗯,什么都没有。)

2 个答案:

答案 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将装箱为中间类型:

enter image description here

此框会产生一些奇怪的中间内部类型,您可以在使用例如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)")
}
相关问题