讀古今文學網 > 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