Jak wydrukować typ lub klasę zmiennej w Swift?

335

Czy istnieje sposób szybkiego wydrukowania typu środowiska wykonawczego zmiennej? Na przykład:

var now = NSDate()
var soon = now.dateByAddingTimeInterval(5.0)

println("\(now.dynamicType)") 
// Prints "(Metatype)"

println("\(now.dynamicType.description()")
// Prints "__NSDate" since objective-c Class objects have a "description" selector

println("\(soon.dynamicType.description()")
// Compile-time error since ImplicitlyUnwrappedOptional<NSDate> has no "description" method

W powyższym przykładzie szukam sposobu, aby pokazać, że zmienna „wkrótce” jest typu ImplicitlyUnwrappedOptional<NSDate>, a przynajmniej NSDate!.

Matt Bridges
źródło
43
@JasonMArcher Powiedz mi, jak to jest duplikat, jeśli zadane przez ciebie pytanie zostało zadane 4 dni po tym?
akashivskyy
Istnieje wiele pytań dotyczących testowania typu obiektu Swift lub odczytywania typu obiektu Swift. Po prostu znajdujemy najlepsze pytania, które można wykorzystać jako „główne” pytania na ten temat. Sugerowany duplikat ma znacznie dokładniejszą odpowiedź. Nie oznacza to, że zrobiłeś coś złego, po prostu staramy się zmniejszyć bałagan.
JasonMArcher
4
Sugerowany duplikat nie odpowiada na to samo pytanie; Type.self nie może zostać wydrukowany na konsoli w celu debugowania, służy do przekazywania do innych funkcji, które przyjmują Typy jako obiekty.
Matt Bridges,
2
OT: Bardzo dziwne, że Swift nie oferuje tego po wyjęciu z pudełka i trzeba się bawić z tak niskimi poziomami bibliotek C. Warto zgłosić błąd?
qwerty_so
Chłopaki, poniżej przedstawiłem odpowiedź. Proszę spojrzeć i dać mi znać, czy tego się oczekuje.
DILIP KOSURI

Odpowiedzi:

377

Aktualizacja z września 2016 r

Swift 3.0: Użyj type(of:), np. type(of: someThing)(Ponieważ dynamicTypesłowo kluczowe zostało usunięte)

Aktualizacja październik 2015 :

Zaktualizowałem poniższe przykłady do nowej składni Swift 2.0 (np. printlnZostał zastąpiony print, toString()jest teraz String()).

Z informacji o wersji Xcode 6.3 :

@nschum wskazuje w komentarzach, że uwagi do wydania Xcode 6.3 pokazują inny sposób:

Wartości typu są teraz drukowane jako pełna nazwa typu demontowanego, jeśli są używane z interpolacją println lub łańcucha.

import Foundation

class PureSwiftClass { }

var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"

print( "String(myvar0.dynamicType) -> \(myvar0.dynamicType)")
print( "String(myvar1.dynamicType) -> \(myvar1.dynamicType)")
print( "String(myvar2.dynamicType) -> \(myvar2.dynamicType)")
print( "String(myvar3.dynamicType) -> \(myvar3.dynamicType)")

print( "String(Int.self)           -> \(Int.self)")
print( "String((Int?).self         -> \((Int?).self)")
print( "String(NSString.self)      -> \(NSString.self)")
print( "String(Array<String>.self) -> \(Array<String>.self)")

Które wyjścia:

String(myvar0.dynamicType) -> __NSCFConstantString
String(myvar1.dynamicType) -> PureSwiftClass
String(myvar2.dynamicType) -> Int
String(myvar3.dynamicType) -> String
String(Int.self)           -> Int
String((Int?).self         -> Optional<Int>
String(NSString.self)      -> NSString
String(Array<String>.self) -> Array<String>

Aktualizacja dla Xcode 6.3:

Możesz użyć _stdlib_getDemangledTypeName():

print( "TypeName0 = \(_stdlib_getDemangledTypeName(myvar0))")
print( "TypeName1 = \(_stdlib_getDemangledTypeName(myvar1))")
print( "TypeName2 = \(_stdlib_getDemangledTypeName(myvar2))")
print( "TypeName3 = \(_stdlib_getDemangledTypeName(myvar3))")

i uzyskaj to jako wynik:

TypeName0 = NSString
TypeName1 = __lldb_expr_26.PureSwiftClass
TypeName2 = Swift.Int
TypeName3 = Swift.String

Oryginalna odpowiedź:

Przed Xcode 6.3 _stdlib_getTypeNamedostał zniekształconą nazwę zmiennej. Wpis na blogu Ewana Swicka pomaga rozszyfrować te ciągi:

np. _TtSioznacza wewnętrzny Inttyp Swift .

Mike Ash ma świetny wpis na blogu na ten sam temat .

Klaas
źródło
2
Skąd dowiedziałeś _stdlib_getTypeName()? Zintegrowana REPL już nie istnieje, swift-ide-testteż nie istnieje, a drukowanie Xcode modułu Swift _zawiera wartości z prefiksem.
Lily Ballard,
10
Wygląda na to, że mogę lldbłatwo wyszukiwać symbole w replice. Jest też _stdlib_getDemangledTypeName()i _stdlib_demangleName().
Lily Ballard
1
Och, fajnie, nie zdawałem sobie sprawy, że imageto skrót target modules. Skończyło się na użyciu target modules lookup -r -n _stdlib_, co oczywiście lepiej wyraża się jakoimage lookup -r -n _stdlib_ libswiftCore.dylib
Lily Ballard
1
FYI - Wygląda na to, że toString (...) zostało zastąpione przez String (...).
Nick
6
Swift 3.0: Słowo dynamicTypekluczowe zostało usunięte z Swift. W jego miejsce dodano nową prymitywną funkcję type(of:)do języka: github.com/apple/swift/blob/master/CHANGELOG.md
Szu
46

Edycja: W Swift 1.2 wprowadzono nową toStringfunkcję (Xcode 6.3) .

Możesz teraz wydrukować zdemontowany typ dowolnego typu za pomocą .selfi dowolnej instancji za pomocą .dynamicType:

struct Box<T> {}

toString("foo".dynamicType)            // Swift.String
toString([1, 23, 456].dynamicType)     // Swift.Array<Swift.Int>
toString((7 as NSNumber).dynamicType)  // __NSCFNumber

toString((Bool?).self)                 // Swift.Optional<Swift.Bool>
toString(Box<SinkOf<Character>>.self)  // __lldb_expr_1.Box<Swift.SinkOf<Swift.Character>>
toString(NSStream.self)                // NSStream

Spróbuj zadzwonić YourClass.selfi yourObject.dynamicType.

Odniesienie: https://devforums.apple.com/thread/227425 .

akashivskyy
źródło
2
Odpowiedziałem na ten wątek, ale dodam tutaj swój komentarz. Te wartości są typu „Metatype”, ale wydaje się, że nie ma łatwego sposobu, aby dowiedzieć się, jaki typ reprezentuje obiekt Metatype i właśnie tego szukam.
Matt Bridges
Są typu Metatype i są klasami. Reprezentują klasę. Nie jestem pewien, na czym dokładnie polega Twój problem. someInstance.dynamicType.printClassName()wypisze nazwę klasy.
Plik analogowy
18
metoda printClassName () to tylko przykładowa metoda, którą utworzyli w jednym z przykładów w dokumentach, nie jest to wywołanie API, do którego można uzyskać dostęp.
Dave Wood
4
FYI - Wygląda na to, że toString (...) zostało zastąpione przez String (...)
Nick
33

Swift 3.0

let string = "Hello"
let stringArray = ["one", "two"]
let dictionary = ["key": 2]

print(type(of: string)) // "String"

// Get type name as a string
String(describing: type(of: string)) // "String"
String(describing: type(of: stringArray)) // "Array<String>"
String(describing: type(of: dictionary)) // "Dictionary<String, Int>"

// Get full type as a string
String(reflecting: type(of: string)) // "Swift.String"
String(reflecting: type(of: stringArray)) // "Swift.Array<Swift.String>"
String(reflecting: type(of: dictionary)) // "Swift.Dictionary<Swift.String, Swift.Int>"
Evgenii
źródło
1
Implementacja Swift 2 jest szczególnie przyjemna w przypadku enum. Czy ktoś wie, czy takie zachowanie jest udokumentowane / zagwarantowane przez Apple? Standardowa biblioteka zawiera jedynie komentarz, który nadaje się do debugowania ...
milos
30

Czy tego szukasz?

println("\(object_getClassName(now))");

Wyświetla „__NSDate”

AKTUALIZACJA : Uwaga: wydaje się, że nie działa już od wersji Beta05

Haiku Oezu
źródło
2
Nie działa dla szybkich klas. Zwraca „Niebezpieczny wskaźnik (0x7FBB18D06DE0)”
aryaxt
4
Nie działa też dla klas ObjC (przynajmniej w wersji Beta5), dla NSManagedObject dostaję „Builtin.RawPointer = adres”
Kendall Helmstetter Gelner
23

Mój obecny Xcode to wersja 6.0 (6A280e).

import Foundation

class Person { var name: String; init(name: String) { self.name = name }}
class Patient: Person {}
class Doctor: Person {}

var variables:[Any] = [
    5,
    7.5,
    true,
    "maple",
    Person(name:"Sarah"),
    Patient(name:"Pat"),
    Doctor(name:"Sandy")
]

for variable in variables {
    let typeLongName = _stdlib_getDemangledTypeName(variable)
    let tokens = split(typeLongName, { $0 == "." })
    if let typeName = tokens.last {
        println("Variable \(variable) is of Type \(typeName).")
    }
}

Wynik:

Variable 5 is of Type Int.
Variable 7.5 is of Type Double.
Variable true is of Type Bool.
Variable maple is of Type String.
Variable Swift001.Person is of Type Person.
Variable Swift001.Patient is of Type Patient.
Variable Swift001.Doctor is of Type Doctor.
Matt Hagen
źródło
1
Dobrze, ale pytanie zawierało także Opcjonalne, wyjście opcji opcjonalnych jest ustawione Optional(...), więc kod będzie zwracany tylko Optionaljako Typ. Powinien również być wyświetlany var optionalTestVar: Person? = Person(name:"Sarah")jako Opcjonalny (Osoba) i zmieniać się w opcji Osoba! as ImplicitlyUnwrappedOptional (Person)
Binarian
18

Począwszy od Xcode 6.3 z Swift 1.2, możesz po prostu przekonwertować wartości typu na w pełni demontowane String.

toString(Int)                   // "Swift.Int"
toString(Int.Type)              // "Swift.Int.Type"
toString((10).dynamicType)      // "Swift.Int"
println(Bool.self)              // "Swift.Bool"
println([UTF8].self)            // "Swift.Array<Swift.UTF8>"
println((Int, String).self)     // "(Swift.Int, Swift.String)"
println((String?()).dynamicType)// "Swift.Optional<Swift.String>"
println(NSDate)                 // "NSDate"
println(NSDate.Type)            // "NSDate.Type"
println(WKWebView)              // "WKWebView"
toString(MyClass)               // "[Module Name].MyClass"
toString(MyClass().dynamicType) // "[Module Name].MyClass"
pływanie
źródło
Czy w 1.2 jest możliwy inny kierunek? Aby zainicjować instancję na podstawie nazwy klasy?
user965972
@ user965972 O ile mi wiadomo, nie sądzę, że istnieje.
kiding
17

Nadal możesz uzyskać dostęp do klasy, poprzez className(która zwraca a String).

Jest kilka sposobów, aby uzyskać klasę, na przykład classForArchiver, classForCoder, classForKeyedArchiver(wszystkie powrotne AnyClass!).

Nie można uzyskać typu prymitywu (prymityw nie jest klasą).

Przykład:

var ivar = [:]
ivar.className // __NSDictionaryI

var i = 1
i.className // error: 'Int' does not have a member named 'className'

Jeśli chcesz uzyskać typ prymitywu, musisz użyć bridgeToObjectiveC(). Przykład:

var i = 1
i.bridgeToObjectiveC().className // __NSCFNumber
Leandros
źródło
Założę się, że to prymitywne. Niestety nie można uzyskać typu prymitywnego.
Leandros,
Te przykłady nie działają na placu zabaw. Pojawia się błąd zarówno dla prymitywów, jak i nie-prymitywów.
Matt Bridges,
spróbuj import Cocoa.
Leandros,
9
klasaName wydaje się być dostępna tylko dla obiektów NSO podczas programowania dla OSX; nie jest dostępny w pakiecie iOS SDK ani dla obiektów NSO, ani dla „normalnych” obiektów
Matt Bridges
3
classNamejest częścią obsługi AppleScript przez Cocoa i zdecydowanie nie powinien być używany do ogólnej introspekcji. Oczywiście nie jest dostępny na iOS.
Nikolai Ruhe
16

Możesz użyć funkcji odbicia, aby uzyskać informacje o obiekcie.
Na przykład nazwa klasy obiektu:

var nazwa_klasy = odzwierciedla (teraz). podsumowanie
Stan
źródło
W wersji beta 6 otrzymałem nazwę aplikacji + nazwę klasy w lekko zniekształconej formie, ale to początek. +1 za reflect(x).summary- dzięki!
Olie,
nie działał, drukuje pustą linię w Swift 1.2 Xcode 6.4 i iOs 8.4
Juan Boero
13

Miałem szczęście z:

let className = NSStringFromClass(obj.dynamicType)
mxcl
źródło
@hdost koleś nic nie działało, ale działał classForCoder.
Satheeshwaran
12

Typ użycia Xcode 8 Swift 3.0 (of :)

let className = "\(type(of: instance))"
Hari Kunwar
źródło
10

W Xcode 8, Swift 3.0

Kroki:

1. Uzyskaj typ:

Opcja 1:

let type : Type = MyClass.self  //Determines Type from Class

Opcja 2:

let type : Type = type(of:self) //Determines Type from self

2. Konwertuj typ na ciąg:

let string : String = "\(type)" //String
użytkownik1046037
źródło
8

W Swift 3.0 możesz używać type(of:), ponieważ dynamicTypesłowo kluczowe zostało usunięte.

Bruno Serrano
źródło
7

SWIFT 5

W najnowszej wersji Swift 3 możemy uzyskać ładny opis nazw typów za pomocą Stringinicjatora. Na przykład print(String(describing: type(of: object))). Gdzie object może być zmienna instancji, taka jak tablica, słownik, an Int, NSDateinstancja klasy niestandardowej itp.

Oto moja pełna odpowiedź: Uzyskaj nazwę klasy obiektu jako ciąg znaków w Swift

To pytanie szuka sposobu na uzyskanie nazwy klasy obiektu jako ciągu, ale zaproponowałem także inny sposób na uzyskanie nazwy klasy zmiennej, która nie jest podklasą NSObject. Oto on:

class Utility{
    class func classNameAsString(obj: Any) -> String {
        //prints more readable results for dictionaries, arrays, Int, etc
        return String(describing: type(of: obj))
    }
}

Zrobiłem funkcję statyczną, która przyjmuje jako parametr obiekt typu Anyi zwraca nazwę swojej klasy jako String:).

Testowałem tę funkcję z niektórymi zmiennymi, takimi jak:

    let diccionary: [String: CGFloat] = [:]
    let array: [Int] = []
    let numInt = 9
    let numFloat: CGFloat = 3.0
    let numDouble: Double = 1.0
    let classOne = ClassOne()
    let classTwo: ClassTwo? = ClassTwo()
    let now = NSDate()
    let lbl = UILabel()

i wynik był:

  • słownik jest typu Dictionary
  • tablica jest typu Array
  • numInt jest typu Int
  • numFloat jest typu CGFloat
  • numDouble jest typu Double
  • classOne jest typu: ClassOne
  • classTwo jest typu: ClassTwo
  • teraz jest typu: Data
  • lbl jest typu: UILabel
mauricioconde
źródło
5

Korzystając z Cocoa (nie CocoaTouch), możesz użyć classNamewłaściwości dla obiektów, które są podklasami NSObject.

println(now.className)

Ta właściwość nie jest dostępna dla normalnych obiektów Swift, które nie są podklasami NSObject (w rzeczywistości w Swift nie ma identyfikatora głównego ani typu obiektu).

class Person {
    var name: String?
}

var p = Person()
println(person.className) // <- Compiler error

W CocoaTouch w tej chwili nie ma sposobu, aby uzyskać opis ciągu typu danej zmiennej. Podobna funkcjonalność również nie istnieje dla prymitywnych typów w Cocoa lub CocoaTouch.

Swift REPL jest w stanie wydrukować podsumowanie wartości, w tym ich typ, więc możliwe jest, że ten sposób introspekcji będzie możliwy za pośrednictwem interfejsu API w przyszłości.

EDYCJA : dump(object)wydaje się załatwić sprawę.

Matt Bridges
źródło
Nawet od Xcode 10 i Swift 4.2 dump(object)jest naprawdę potężny. Dziękuję Ci.
Alex Zavatone
5

Najlepsza odpowiedź nie ma działającego przykładu nowego sposobu na zrobienie tego za pomocą type(of:. Aby pomóc początkującym jak ja, oto działający przykład, zaczerpnięty głównie z dokumentów Apple tutaj - https://developer.apple.com/documentation/swift/2885064-type

doubleNum = 30.1

func printInfo(_ value: Any) {
    let varType = type(of: value)
    print("'\(value)' of type '\(varType)'")
}

printInfo(doubleNum)
//'30.1' of type 'Double'
Joshua Dance
źródło
4

Próbowałem tutaj kilku innych odpowiedzi, ale zdaje się, że milage bardzo zależy na tym, czym jest obiekt leżący u podstaw.

Jednak znalazłem sposób na uzyskanie nazwy klasy Object-C dla obiektu, wykonując następujące czynności:

now?.superclass as AnyObject! //replace now with the object you are trying to get the class name for

Oto przykład tego, jak byś go używał:

let now = NSDate()
println("what is this = \(now?.superclass as AnyObject!)")

W takim przypadku wydrukuje NSDate w konsoli.

James Jones
źródło
4

Znalazłem to rozwiązanie, które, mam nadzieję, może zadziałać dla kogoś innego. Stworzyłem metodę klasy, aby uzyskać dostęp do wartości. Pamiętaj, że będzie to działać tylko dla podklasy NSObject. Ale przynajmniej jest to czyste i uporządkowane rozwiązanie.

class var className: String!{
    let classString : String = NSStringFromClass(self.classForCoder())
    return classString.componentsSeparatedByString(".").last;
}
DennyLou
źródło
4

W najnowszym XCode 6.3 z Swift 1.2 znalazłem jedyny sposób:

if view.classForCoder.description() == "UISegment" {
    ...
}
Joel Kopelioff
źródło
UWAGA: description () zwraca nazwę klasy w formacie <swift module name>.<actual class name>, więc chcesz podzielić ciąg za pomocą a .i uzyskać ostatni token.
Matthew Quiros
4

Wiele odpowiedzi tutaj nie działa z najnowszym Swift (Xcode 7.1.1 w momencie pisania).

Obecnym sposobem uzyskania informacji jest utworzenie Mirrori przesłuchanie tego. W przypadku nazwy klasy jest to tak proste, jak:

let mirror = Mirror(reflecting: instanceToInspect)
let classname:String = mirror.description

Dodatkowe informacje o obiekcie można również pobrać z Mirror. Szczegółowe informacje można znaleźć na stronie http://swiftdoc.org/v2.1/type/Mirror/ .

Joseph Lord
źródło
Co jest nie tak z odpowiedziami stackoverflow.com/a/25345480/1187415 i stackoverflow.com/a/32087449/1187415 ? Oba wydają się działać całkiem dobrze z Swift 2. (Nie sprawdziłem pozostałych.)
Martin R
Podoba mi się to jako ogólne rozwiązanie, ale uzyskanie „Mirror for ViewController” (zewnętrzne „Mirror for”) - poczekaj, wygląda na to, że użycie „.subjectType” załatwia sprawę!
David H
3

W lldb od wersji beta 5 możesz zobaczyć klasę obiektu za pomocą polecenia:

fr v -d r shipDate

który wyprowadza coś takiego:

(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940

Rozbudowane polecenie oznacza coś takiego:

Frame Variable(wydrukuj zmienną ramki) -d run_target(rozwiń typy dynamiczne)

Warto wiedzieć, że użycie „Frame Variable” do wyprowadzania wartości zmiennych gwarantuje, że kod nie zostanie wykonany.

Kendall Helmstetter Gelner
źródło
3

Znalazłem rozwiązanie dla samodzielnie opracowanych klas (lub takich, do których masz dostęp).

Umieść następującą właściwość obliczoną w definicji klasy obiektów:

var className: String? {
    return __FILE__.lastPathComponent.stringByDeletingPathExtension
}

Teraz możesz po prostu wywołać nazwę klasy na swoim obiekcie w następujący sposób:

myObject.className

Pamiętaj, że zadziała to tylko wtedy, gdy twoja definicja klasy zostanie utworzona w pliku o nazwie dokładnie takiej , jak klasa, której nazwa ma mieć nazwę.

Ponieważ często tak jest, powyższa odpowiedź powinna zrobić to w większości przypadków . Ale w niektórych szczególnych przypadkach może być konieczne znalezienie innego rozwiązania.


Jeśli potrzebujesz nazwy klasy w samej klasie (pliku) , możesz po prostu użyć tego wiersza:

let className = __FILE__.lastPathComponent.stringByDeletingPathExtension

Może ta metoda pomaga niektórym ludziom.

Jeehut
źródło
3

W oparciu o odpowiedzi i komentarze Klassa i Kevina Ballarda powyżej wybrałbym:

println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!)

println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!)

który wydrukuje:

"NSDate"
"ImplicitlyUnwrappedOptional"
"Optional"
"NSDate"

"NSString"
"PureSwiftClass"
"Int"
"Double"
Vince O'Sullivan
źródło
Myślę, że to lepsza odpowiedź.
maschall
W Swift 1.2 skończyło się na tym, że: toString(self.dynamicType).componentsSeparatedByString(".").last!oczywiście byłem w kontekście obiektowym i mogłem się do niego odwoływać self.
Joe
3
let i: Int = 20


  func getTypeName(v: Any) -> String {
    let fullName = _stdlib_demangleName(_stdlib_getTypeName(i))
    if let range = fullName.rangeOfString(".") {
        return fullName.substringFromIndex(range.endIndex)
    }
    return fullName
}

println("Var type is \(getTypeName(i)) = \(i)")
Alex Burla
źródło
3

Szybka wersja 4:

print("\(type(of: self)) ,\(#function)")
// within a function of a class

Dzięki @Joshua Dance

dengApro
źródło
3

Swift 4:

// "TypeName"
func stringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(describing: some) : String(describing: type(of: some))
    return string
}

// "ModuleName.TypeName"
func fullStringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(reflecting: some) : String(reflecting: type(of: some))
    return string
}

Stosowanie:

print(stringType(of: SomeClass()))     // "SomeClass"
print(stringType(of: SomeClass.self))  // "SomeClass"
print(stringType(of: String()))        // "String"
print(fullStringType(of: String()))    // "Swift.String"
Desmond Hume
źródło
2

Wydaje się, że nie ma ogólnego sposobu na wydrukowanie nazwy typu dowolnego typu wartości. Jak zauważyli inni, dla instancji klas można drukować, value.classNameale dla prymitywnych wartości wydaje się, że w czasie wykonywania informacje o typie znikają.

Na przykład wygląda na to, że nie ma sposobu na wpisanie: 1.something()i skorzystaj z Intdowolnej wartości something. (Można, jak inna odpowiedź zasugerował użycie i.bridgeToObjectiveC().classNamedać podpowiedź, ale __NSCFNumberto nie faktycznie typ i. - tylko to, co zostanie skonwertowana do kiedy przecina granicę wywołania funkcji Objective-C)

Byłbym szczęśliwy, gdybym udowodnił, że się mylę, ale wygląda na to, że sprawdzanie typu odbywa się w czasie kompilacji i podobnie jak C ++ (z wyłączonym RTTI) większość informacji o typie jest usuwana w czasie wykonywania.

ipmcc
źródło
Czy możesz podać przykład użycia className do wypisania „NSDate” dla zmiennej „now” w moim przykładzie, który działa na placu zabaw Xcode6? O ile mi wiadomo, nazwa klasy nie jest zdefiniowana na obiektach Swift, nawet tych, które są podklasami NSObject.
Matt Bridges
Wygląda na to, że „className” jest dostępny dla obiektów pochodzących z NSObject, ale tylko podczas programowania dla systemu Mac, a nie dla systemu iOS. Wygląda na to, że nie ma żadnego obejścia dla iOS.
Matt Bridges,
1
Tak, naprawdę na wynos wydaje się, że w ogólnym przypadku informacja o typie jest szybko usuwana w czasie wykonywania.
ipmcc
Ciekawi mnie jednak, w jaki sposób REPL może drukować typy wartości.
Matt Bridges,
REPL jest prawie na pewno interpretowane i
nieskompilowane
2

W ten sposób otrzymujesz ciąg znaków swojego obiektu lub typu, który jest spójny i uwzględnia moduł, do którego należy definicja obiektu lub do której jest zagnieżdżona. Działa w Swift 4.x.

@inline(__always) func typeString(for _type: Any.Type) -> String {
    return String(reflecting: type(of: _type))
}

@inline(__always) func typeString(for object: Any) -> String {
    return String(reflecting: type(of: type(of: object)))
}

struct Lol {
    struct Kek {}
}

// if you run this in playground the results will be something like
typeString(for: Lol.self)    //    __lldb_expr_74.Lol.Type
typeString(for: Lol())       //    __lldb_expr_74.Lol.Type
typeString(for: Lol.Kek.self)//    __lldb_expr_74.Lol.Kek.Type
typeString(for: Lol.Kek())   //    __lldb_expr_74.Lol.Kek.Type
Igor Muzyka
źródło
2

Aby uzyskać typ obiektu lub klasę obiektu w Swift , musisz użyć typu (of: yourObject)

type (of: yourObject)

Rahul Panzade
źródło
1

Nie do końca to, czego szukasz, ale możesz także sprawdzić typ zmiennej względem typów Swift, takich jak:

let object: AnyObject = 1

if object is Int {
}
else if object is String {
}

Na przykład.

PersuitOfPerfection
źródło
1

Xcode 7.3.1, Swift 2.2:

String(instanceToPrint.self).componentsSeparatedByString(".").last

leanne
źródło