Czy Swift wspiera refleksję? na przykład czy istnieje coś takiego jak valueForKeyPath:
i setValue:forKeyPath:
dla obiektów Swift?Czy Swift wspiera refleksję?
W rzeczywistości ma nawet system dynamicznego typu, coś jak obj.class
w Objective-C?
Czy Swift wspiera refleksję? na przykład czy istnieje coś takiego jak valueForKeyPath:
i setValue:forKeyPath:
dla obiektów Swift?Czy Swift wspiera refleksję?
W rzeczywistości ma nawet system dynamicznego typu, coś jak obj.class
w Objective-C?
Wygląda na to, że jest to początek jakiegoś wsparcia refleksji:
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
Od mchambers istota, tutaj: https://gist.github.com/mchambers/fb9da554898dae3e54f2
Dzięki. Bardzo pomocne informacje! –
Cóż, nie uważam tego za prawdziwą refleksję. Po pierwsze, jest to tylko do odczytu. Wydaje mi się, że to po prostu hack, aby włączyć debugowanie w Xcode. Protokół 'Odbicie' faktycznie cytuje słowo' IDE' kilka razy. – Sulthan
I działa tylko dla właściwości. Bez refleksji metodologicznej. – Sulthan
Dokumentacja mówi o dynamiczny system typów, głównie o
Type
i dynamicType
Zobacz Metatype Type (in Language Reference)
Przykład:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
Teraz zakładając TestObject
rozciąga NSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
Obecnie nie wdrożono żadnych refleksji.
EDIT: Byłem najwyraźniej w błędzie, zobacz odpowiedź Stevex. Istnieje pewna prosta refleksja na temat odczytu wbudowanych właściwości, prawdopodobnie w celu umożliwienia kontrolerom IDE sprawdzania zawartości obiektów.
Jeśli klasa rozszerza NSObject
, to wszystkie introspekcji Objective-C i dynamizm działa. Obejmuje to:
Jednym z niedociągnięć tej funkcji jest obsługa opcjonalnych typów wartości Swift. Na przykład właściwości Int można wyliczyć i zmodyfikować, ale Int? właściwości nie mogą. Typy opcjonalne mogą być wyliczane częściowo za pomocą parametru reflect/MirrorType, ale wciąż nie są modyfikowane.
Jeśli klasa nie rozszerza się na NSObject
, działa tylko nowe, bardzo ograniczone (i w toku?) Odbicie (patrz reflect/MirrorType), które dodaje ograniczoną możliwość zadawania instancji dotyczących jej klasy i właściwości, ale żadne dodatkowych funkcji powyżej.
Gdy nie rozszerzasz NSObject lub używasz dyrektywy "@objc", Swift domyślnie stosuje wysyłkę statyczną i vtable. Jest to jednak szybsze, ponieważ brak maszyny wirtualnej nie pozwala na przechwycenie metody środowiska wykonawczego. To przechwycenie jest podstawową częścią kakao i jest wymagane dla następujących typów funkcji:
Dlatego zaleca się, aby jego clases w aplikacjach Cocoa/Cocoa Touch realizowanych ze SWIFT:
Podsumowanie:
referencyjny dane: Wykonanie napowietrzne dla metody inwokacji:
(rzeczywista wydajność zależy od sprzętu, ale proporcje pozostaną podobne).
Ponadto atrybut dynamiczny pozwala nam wyraźnie polecić Swiftowi, że metoda powinna korzystać z dynamicznej wysyłki, a zatem będzie wspierać przechwytywanie.
public dynamic func foobar() -> AnyObject {
}
Nawet przy użyciu technik Objective-C wydaje się nie działać dla opcjonalnych typów Swift. Proponuję zauważyć to ograniczenie w odpowiedzi, chyba że brakuje mi jakiejś sztuczki. – Lee
@LeeWhitney, edytuj odpowiedź. –
Wygląda na to, że interfejs API Swift do refleksji nie jest obecnie priorytetem dla Apple. Ale oprócz @stevex answer jest inna funkcja w standardowej bibliotece, która pomaga.
Od wersji beta 6 _stdlib_getTypeName
otrzymuje nazwę zmienną typu "zniekształcona". Pasta ta w pustym zabaw:
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))")
wyjście jest:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Ewan Swick's blog entry pomaga rozwiązać te łańcuchy:
np _TtSi
oznacza wewnętrzny typ Swifta: Int
.
'_stdlib_getDemangledTypeName' może być również użyty – aleclarson
@aleclarson Tak, jest to również przydatne. – Klaas
nie są tymi prywatnymi API? Czy Apple zatwierdzi aplikację, jeśli będzie używana? –
Można rozważyć użycie zamiast tego toString(). Jest on publiczny i działa tak samo, jak _stdlib_getTypeName() z tą różnicą, że działa również na AnyClass, np. na placu zabaw wpisz
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"
Utworzyłem klasę pomocniczą do refleksji w Swift. Można go znaleźć na stronie: https://github.com/evermeer/EVReflection –
Usunęli odbicie w Swift 2.0. Oto jak wyliczam atrybuty i wartości [link] (http://stackoverflow.com/questions/25463146/iterate-over-object-class-attributes-in-swift/32969324#32969324) – mohacs