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