映月读书网 > iOS编程基础:Swift、Xcode和Cocoa入门指南 > 5.4 内省 >

5.4 内省

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