Swift提供了有限的能力来内省对象,即让一个对象显示其属性名和属性值。该特性用于调试的目的,而不是用于程序的逻辑。比如,你可以通过它在Xcode调试窗格中修改对象的显示方式。
要想内省一个对象,在实例化Mirror时请将其作为reflecting参数。Mirror的children是个名值对元组,描述了原始对象的属性。下面这个Dog类有个description属性,它利用了内省特性。相比于硬编码类实例属性的列表,我们通过内省实例来获取属性名与属性值。这意味着,我们可以在后面添加更多的属性,而无须修改description实现:
struct Dog : CustomStringConvertible { var name = "Fido" var license = 1 var description : String { var desc = "Dog (" let mirror = Mirror(reflecting:self) for (k,v) in mirror.children { desc.appendContentsOf("/(k!): /(v), ") } let c = desc.characters.count return String(desc.characters.prefix(c-2)) + ")" }}
如果实例化Dog并将实例传递给print,那么控制台会打印出如下内容:
Dog (name: Fido, license: 1)
如果对象类型使用了CustomStringConvertible(description属性)与CustomDebugStringConvertible(debugDescription属性)协议,那么我们首选description,不过还可以通过debugPrint函数输出debugDescription。
通过使用CustomReflectable协议,我们可以接管Mirror的children。要想做到这一点,我们实现了customMirror方法,返回自定义的Mirror对象,其children属性是我们所配置的名值对元组集合。
在下面这个简单的示例中,我们实现了customMirror来支持对属性的修改:
struct Dog : CustomReflectable { var name = "Fido" var license = 1 func customMirror -> Mirror { let children : [Mirror.Child] = [ ("ineffable name", self.name), ("license to kill", self.license) ] let m = Mirror(self, children:children) return m }}
结果就是,当我们在Xcode调试窗格控制台中打印出Dog实例时,自定义属性名会显示:
- ineffable name : "Fido"- license to kill : 1