Does Swift support reflection? e.g. is there something like valueForKeyPath:
and setValue:forKeyPath:
for Swift objects?
Actually does it even have a dynamic type system, something like obj.class
in Objective-C?
Does Swift support reflection? e.g. is there something like valueForKeyPath:
and setValue:forKeyPath:
for Swift objects?
Actually does it even have a dynamic type system, something like obj.class
in Objective-C?
Looks like there's the start of some reflection support:
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
From mchambers gist, here: https://gist.github.com/mchambers/fb9da554898dae3e54f2
Mirror
actually quotes the word IDE
several times. –
Stifling _stdlib_getTypeName
can help. –
Jackstay If a class extends NSObject
, then all of Objective-C's introspection and dynamism works. This includes:
One shortcoming of this functionality is support for Swift optional value types. For example Int properties can be enumerated and modified but Int? properties cannot. Optional types can be enumerated partially using reflect/MirrorType, but still not modified.
If a class does not extend NSObject
, then only the new, very limited (and in progress?) reflection works (see reflect/MirrorType), which adds limited ability to ask a instance about its class and properties, but none of the additional features above.
When not extending NSObject, or using the '@objc' directive, Swift defaults to static- and vtable-based dispatch. This is faster, however, in the absence of a virtual machine does not allow runtime method interception. This interception is a fundamental part of Cocoa and is required for the following types of features:
Therefore its recommended that clases in Cocoa/CocoaTouch applications implemented with Swift:
Summary:
Reference data: Execution overhead for method invocations:
(actual performance depends on hardware, but the ratios will remain similar).
Also, the dynamic attribute allows us to explicitly instruct Swift that a method should use dynamic dispatch, and will therefore support interception.
public dynamic func foobar() -> AnyObject {
}
The documentation speaks about a dynamic type system, mainly about
Type
and dynamicType
See Metatype Type (in Language Reference)
Example:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
Now assuming TestObject
extends NSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
Currently, there is no reflection implemented.
EDIT: I was apparently wrong, see stevex's answer. There is some simple readonly reflection for properties build in, probably to allow IDEs to inspect object contents.
No reflect
keyword in Swift 5, now you can use
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
deserialization –
Preemie It seems that a Swift reflection API is not a high priority for Apple at the moment. But besides @stevex answer there is another function in the standard library that helps.
As of beta 6 _stdlib_getTypeName
gets the mangled type name of a variable. Paste this into an empty playground:
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))")
The output is:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Ewan Swick's blog entry helps to decipher these strings:
e.g. _TtSi
stands for Swift's internal Int
type.
You might want to consider using toString() instead. It is public and works just the same as _stdlib_getTypeName() with the difference that it also works on AnyClass, e.g. in a Playground enter
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"
© 2022 - 2024 — McMap. All rights reserved.