Поддерживает ли Swift отражение? например есть ли что-то вроде valueForKeyPath:
и setValue:forKeyPath:
для объектов Swift?
На самом деле у него даже есть система динамического типа, что-то вроде obj.class
в Objective-C?
Поддерживает ли Swift отражение? например есть ли что-то вроде valueForKeyPath:
и setValue:forKeyPath:
для объектов Swift?
На самом деле у него даже есть система динамического типа, что-то вроде obj.class
в Objective-C?
Похоже, что начало некоторой поддержки отражения:
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
Из mchambers gist, здесь: https://gist.github.com/mchambers/fb9da554898dae3e54f2
Если класс расширяет NSObject
, то работает все интроспекция и динамизм Objective-C. Это включает в себя:
Одним из недостатков этой функции является поддержка дополнительных типов значений Swift. Например, свойства Int могут быть перечислены и изменены, но Int? свойства не могут. Необязательные типы могут быть перечислены частично с использованием mirror/MirrorType, но все еще не изменены.
Если класс не расширяет NSObject
, то работает только новое, очень ограниченное (и в процессе?) отражение (см. отражение /MirrorType ), что добавляет ограниченную способность запрашивать экземпляр о его классе и свойствах, но ни одна из дополнительных функций выше.
Если не расширять NSObject или использовать директиву "@objc", по умолчанию Swift используется для отправки по статической и виртуальной таблицам. Однако это происходит быстрее, но при отсутствии виртуальной машины не разрешается перехват метода времени исполнения. Этот перехват является фундаментальной частью Cocoa и требуется для следующих типов функций:
Поэтому рекомендуется, чтобы классы в приложениях Cocoa/CocoaTouch, реализованных с помощью Swift:
Резюме:
Справочные данные: служебные данные выполнения для вызовов методов:
(фактическая производительность зависит от аппаратного обеспечения, но коэффициенты останутся похожими).
Кроме того, динамический атрибут позволяет нам явно проинструктировать Swift о том, что метод должен использовать динамическую отправку и, следовательно, поддерживать перехват.
public dynamic func foobar() -> AnyObject {
}
Документация говорит о системе динамического типа, в основном о
Type
и dynamicType
См. Тип метатипа (в справочнике по языку)
Пример:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
Теперь предположим, что TestObject
extends NSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
В настоящее время не реализовано отражение.
РЕДАКТИРОВАТЬ: Я, по-видимому, ошибался, см. stevex ответ. Существует некоторое простое отображение readonly для построения свойств, возможно, чтобы IDE могли проверять содержимое объекта.
Похоже, что API Swift для отражения в настоящее время не является для Apple приоритетом. Но помимо @stevex answer есть другая функция в стандартной библиотеке, которая помогает.
Начиная с бета-версии 6 _stdlib_getTypeName
получает измененное имя переменной. Вставьте это в пустую детскую площадку:
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))")
Вывод:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Запись в блоге Ewan Swick помогает расшифровать эти строки:
например. _TtSi
обозначает внутренний тип Swift Int
.
У Майка Эша отличная запись в блоге, посвященная той же теме.
Вместо этого вы можете использовать toString(). Он является общедоступным и работает так же, как _stdlib_getTypeName() с той разницей, что он также работает на AnyClass, например. на игровой площадке введите
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"