Чи підтримує Свіфт відображення? наприклад, є щось на зразок valueForKeyPath:
і setValue:forKeyPath:
для об'єктів Swift?
Насправді у нього навіть є система динамічного типу, щось на зразок obj.class
об’єктива-C?
Чи підтримує Свіфт відображення? наприклад, є щось на зразок valueForKeyPath:
і setValue:forKeyPath:
для об'єктів Swift?
Насправді у нього навіть є система динамічного типу, щось на зразок obj.class
об’єктива-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
Mirror
фактично цитує це слово IDE
кілька разів.
_stdlib_getTypeName
можна допомогти.
Якщо клас поширюється NSObject
, то вся самоаналіз і динамізм Objective-C працює. Це включає:
Одним з недоліків цієї функції є підтримка додаткових типів значень Swift. Наприклад, Int властивості можна перерахувати та змінити, але Int? властивості не можуть. Необов’язкові типи можна перерахувати частково за допомогою відображення / MirrorType, але все ще не змінювати.
Якщо клас не поширюється NSObject
, то працює лише нове, дуже обмежене (і триває?) Відображення (див. Відображення / MirrorType), що додає обмежену можливість запитувати екземпляр про його клас та властивості, але жодна з додаткових функцій, наведених вище .
Якщо ви не поширюєте NSObject або не використовуєте директиву "@objc", Swift за замовчуванням відправляє статичну та Vtable відправлення. Це швидше, однак за відсутності віртуальної машини не допускається перехоплення методом виконання. Цей перехоплення є основоположною частиною какао і вимагається для таких типів ознак:
Тому рекомендується, щоб пункти в програмах 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
поширюєтьсяNSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
Наразі відображення не реалізовано.
EDIT: Я, мабуть, помилявся, дивіться відповідь stevex. Існує просте відображення лише для читання властивостей, можливо, щоб IDE могли перевіряти вміст об'єкта.
Схоже, що інтерфейс відбиття Swift наразі не є пріоритетним для Apple. Але крім відповіді @stevex, у стандартній бібліотеці є ще одна функція, яка допомагає.
З бета-версії 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
Запис у блозі Юана Свіка допомагає розшифрувати ці рядки:
наприклад, _TtSi
означає внутрішній Int
тип Свіфта .
Майк Еш має чудовий запис у блозі, що висвітлює ту саму тему .
Можливо, ви хочете замість цього використати toString () . Він є загальнодоступним і працює так само, як _stdlib_getTypeName () з тією різницею, що він також працює на AnyClass , наприклад, введіть на дитячу площадку
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"
У reflect
Swift 5 немає ключового слова, тепер його можна використовувати
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
десеріалізації