Unterstützt Swift Reflexion? zB gibt es so etwas wie valueForKeyPath:
und setValue:forKeyPath:
für Swift-Objekte?
Hat es überhaupt ein dynamisches Typsystem, so etwas wie obj.class
in Objective-C?
Unterstützt Swift Reflexion? zB gibt es so etwas wie valueForKeyPath:
und setValue:forKeyPath:
für Swift-Objekte?
Hat es überhaupt ein dynamisches Typsystem, so etwas wie obj.class
in Objective-C?
Antworten:
Es sieht so aus, als würde eine Reflexionsunterstützung beginnen:
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
Von mchambers gist hier: https://gist.github.com/mchambers/fb9da554898dae3e54f2
Mirror
zitiert das Wort tatsächlich IDE
mehrmals.
_stdlib_getTypeName
helfen können.
Wenn eine Klasse erweitert wird NSObject
, funktioniert die gesamte Selbstbeobachtung und Dynamik von Objective-C. Das beinhaltet:
Ein Nachteil dieser Funktionalität ist die Unterstützung optionaler Swift-Werttypen. Zum Beispiel können Int-Eigenschaften aufgezählt und geändert werden, aber Int? Eigenschaften können nicht. Optionale Typen können teilweise mit Reflect / MirrorType aufgelistet, aber immer noch nicht geändert werden.
Wenn eine Klasse nicht erweitert wird NSObject
, funktioniert nur die neue, sehr eingeschränkte (und in Bearbeitung befindliche?) Reflexion (siehe Reflect / MirrorType), wodurch eine Instanz nur eingeschränkt nach ihrer Klasse und ihren Eigenschaften gefragt werden kann, jedoch keine der oben genannten zusätzlichen Funktionen .
Wenn Sie NSObject nicht erweitern oder die Direktive '@objc' verwenden, verwendet Swift standardmäßig den statischen und vtable-basierten Versand. Dies ist jedoch schneller, da in Abwesenheit einer virtuellen Maschine kein Abfangen von Laufzeitmethoden möglich ist. Dieses Abfangen ist ein wesentlicher Bestandteil von Cocoa und wird für die folgenden Arten von Funktionen benötigt:
Daher wird empfohlen, Klassen in Cocoa / CocoaTouch-Anwendungen mit Swift zu implementieren:
Zusammenfassung:
Referenzdaten: Ausführungsaufwand für Methodenaufrufe:
(Die tatsächliche Leistung hängt von der Hardware ab, die Verhältnisse bleiben jedoch ähnlich.)
Das dynamische Attribut ermöglicht es uns außerdem, Swift explizit anzuweisen, dass eine Methode den dynamischen Versand verwenden soll, und unterstützt daher das Abfangen.
public dynamic func foobar() -> AnyObject {
}
Die Dokumentation spricht hauptsächlich von einem dynamischen Typsystem
Type
und dynamicType
Siehe Metatyp Typ (in der Sprachreferenz)
Beispiel:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
Nun geht man davon aus, dass es sich TestObject
ausdehntNSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
Derzeit ist keine Reflexion implementiert.
EDIT: Ich habe mich anscheinend geirrt, siehe stevex 'Antwort. Es gibt einige einfache schreibgeschützte Überlegungen zu eingebauten Eigenschaften, wahrscheinlich um IDEs die Möglichkeit zu geben, Objektinhalte zu überprüfen.
Es scheint, dass eine Swift Reflection API für Apple derzeit keine hohe Priorität hat. Neben der Antwort von @stevex gibt es in der Standardbibliothek noch eine weitere Funktion, die hilft.
Ab Beta 6 _stdlib_getTypeName
wird der verstümmelte Typname einer Variablen abgerufen. Fügen Sie dies in einen leeren Spielplatz ein:
import Foundation
class PureSwiftClass {
}
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")
Die Ausgabe ist:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Der Blogeintrag von Ewan Swick hilft dabei, diese Zeichenfolgen zu entschlüsseln:
zB _TtSi
steht für Swifts internen Int
Typ.
Mike Ash hat einen großartigen Blogeintrag zum gleichen Thema .
Möglicherweise möchten Sie stattdessen toString () verwenden. Es ist öffentlich und funktioniert genauso wie _stdlib_getTypeName (), mit dem Unterschied, dass es auch auf AnyClass funktioniert , z. B. auf einem Spielplatz
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"
Kein reflect
Schlüsselwort in Swift 5, jetzt können Sie verwenden
struct Person {
var name="name"
var age = 15
}
var me = Person()
var mirror = Mirror(reflecting: me)
for case let (label?, value) in mirror.children {
print (label, value)
}
json
Deserialisierung anwenden