Swift 2: Reflection

Swift fehlt leider ein allgemein gültiger Ansatz, um die Eigenschaften von Objekten bzw. Typen festzustellen. Andere Programmiersprachen besitzen dafür Reflection-Funktionen, z.B. Objective C, C# oder Java.

Swift ist aber zumindest eingeschränkt zur Selbstreflexion in der Lage, wobei sich die Vorgehensweise in der gestern freigegebenen Beta 4 von Xcode 7 Beta 4 nochmals geändert hat:

  • Die globale Funktion reflect ist verschwunden, ebenso der MirrorType.
  • Dafür gibt es die neue Mirror-Klasse.

Mit Mirror(data) erzeugen Sie ein Mirror-Objekt, das das Element bzw. Objekt der Variablen data beschreibt. Das Mirror-Objekt verrät, wie viele Eigenschaften das betroffene Objekt hat. Diese Subelemente können in einer Schleife durchlaufen werden. Das funktioniert aber nur für in Swift definierte Typen.

// Klasse als Testbasis
class MyClass {
  var a:Double = 1.0
  var b:Int = 2
  func f() -> Double { return a+Double(b) }
}

var x = MyClass()      // ein Objekt der Klasse
let mirr = Mirror(reflecting: x)
mirr.description       // "Mirror for MyClass"
mirr.children.count    // 2
for c in mirr.children {
  print("Label: \(c.label), Value: \(c.value)")
}
// Ausgabe: Label: Optional("a"), Value: 1.0
//          Label: Optional("b"), Value 2

Mit der undokumentierten Funktion _stdlib_getDemangledTypeName können Sie den
Typnamen eines Objekts herausfinden:

let demangled = _stdlib_getDemangledTypeName(x)
// Ausgabe: "MyClass"

Zum Experimentieren können Sie sich die eigene Funktion demangle definieren:

func demangle (obj:Any) -> String{
  return _stdlib_getDemangledTypeName(obj)
}
demangle(x)            // "MyClass"
demangle(2.4)          // "Swift.Double"
demangle(NSDate())     // "NSDate"
demangle([1, 2, 3])    // "Swift.Array<Swift.Int>"
demangle( (1, 2, 3) )  // "(Swift.Int, Swift.Int, Swift.Int)"