Wie drucke ich den Typ oder die Klasse einer Variablen in Swift?

335

Gibt es eine Möglichkeit, den Laufzeittyp einer Variablen schnell zu drucken? Zum Beispiel:

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

Im obigen Beispiel suche ich nach einer Möglichkeit, um zu zeigen, dass die Variable "bald" vom Typ ist ImplicitlyUnwrappedOptional<NSDate>, oder zumindest NSDate!.

Matt Bridges
quelle
43
@JasonMArcher Sag mir, wie ist das ein Duplikat, wenn die von dir verlinkte Frage 4 Tage nach dieser gestellt wurde?
Akashivskyy
Es gibt eine Reihe von Fragen zum Testen des Typs eines Swift-Objekts oder zum Lesen des Typs eines Swift-Objekts. Wir finden gerade die besten Fragen, die wir als "Master" -Fragen für dieses Thema verwenden können. Das vorgeschlagene Duplikat hat eine viel gründlichere Antwort. Das soll nicht heißen, dass Sie etwas falsch gemacht haben, nur dass wir versuchen, die Unordnung zu reduzieren.
JasonMArcher
4
Das vorgeschlagene Duplikat beantwortet nicht dieselbe Frage. Type.self kann zum Debuggen nicht auf der Konsole gedruckt werden. Es soll verwendet werden, um es an andere Funktionen zu übergeben, die Types als Objekte verwenden.
Matt Bridges
2
OT: Sehr seltsam, dass Swift das nicht sofort anbietet und man mit so niedrigen C-Bibliotheken herumspielen muss. Einen Fehlerbericht wert?
QWERTY_SO
Leute, ich habe meine Antwort unten gegeben. Bitte schauen Sie und lassen Sie mich wissen, ob dies erwartet wird.
DILIP KOSURI

Antworten:

377

Update September 2016

Swift 3.0: Verwenden Sie type(of:)z. B. type(of: someThing)(da das dynamicTypeSchlüsselwort entfernt wurde)

Update Oktober 2015 :

Ich habe die folgenden Beispiele auf die neue Swift 2.0-Syntax aktualisiert (zB printlnwurde durch ersetzt print, toString()ist jetztString() ).

Aus den Versionshinweisen zu Xcode 6.3 :

@nschum weist in den Kommentaren darauf hin, dass die Xcode 6.3- Versionshinweise einen anderen Weg zeigen:

Typwerte werden jetzt als vollständig entwirrter Typname gedruckt, wenn sie mit println oder String-Interpolation verwendet werden.

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)")

Welche Ausgänge:

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>

Update für Xcode 6.3:

Sie können Folgendes verwenden _stdlib_getDemangledTypeName():

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

und erhalten Sie dies als Ausgabe:

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

Ursprüngliche Antwort:

Vor Xcode 6.3 _stdlib_getTypeNamewurde der verstümmelte Typname einer Variablen abgerufen. Der Blogeintrag von Ewan Swick hilft dabei, diese Zeichenfolgen zu entschlüsseln:

zB _TtSisteht für Swifts internen IntTyp.

Mike Ash hat einen großartigen Blogeintrag zum gleichen Thema .

Klaas
quelle
2
Wie haben Sie gefunden _stdlib_getTypeName()? Die integrierte REPL existiert nicht mehr, existiert swift-ide-testauch nicht, und Xcodes Druck des Swift-Moduls entfernt _vorfixierte Werte.
Lily Ballard
10
Sieht so aus, als könnte ich Symbole mit lldbleicht genug in der Antwort suchen. Es gibt auch _stdlib_getDemangledTypeName()und _stdlib_demangleName().
Lily Ballard
1
Oh, ordentlich, ich wusste nicht, dass imagees eine Abkürzung für ist target modules. target modules lookup -r -n _stdlib_image lookup -r -n _stdlib_ libswiftCore.dylib
Lily Ballard
1
Zu Ihrer Information - Es sieht so aus, als ob toString (...) durch String (...) ersetzt wurde.
Nick
6
Swift 3.0: Das dynamicTypeSchlüsselwort wurde aus Swift entfernt. An seiner Stelle wurde type(of:)der Sprache eine neue primitive Funktion hinzugefügt: github.com/apple/swift/blob/master/CHANGELOG.md
Szu
46

Bearbeiten: In Swift 1.2 (Xcode 6.3) wurde eine neue toStringFunktion eingeführt .

Sie können jetzt den entwirrten Typ eines beliebigen Typs mit .selfund einer beliebigen Instanz drucken mit .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

Versuchen Sie anzurufen YourClass.selfundyourObject.dynamicType .

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

akashivskyy
quelle
2
Ich habe auf diesen Thread geantwortet, aber ich werde meinen Kommentar hier hinzufügen. Diese Werte sind vom Typ "Metatyp", aber es scheint keine einfache Möglichkeit zu geben, herauszufinden, welchen Typ ein Metatyp-Objekt darstellt, wonach ich suche.
Matt Bridges
Sie sind vom Typ Metatyp und sie sind Klassen. Sie repräsentieren eine Klasse. Ich bin mir nicht sicher, was genau dein Problem damit ist. someInstance.dynamicType.printClassName()druckt den Namen der Klasse.
Analoge Datei
18
Die printClassName () -Methode ist nur eine Beispielmethode, die in einem der Beispiele in den Dokumenten erstellt wurde. Es handelt sich nicht um einen API-Aufruf, auf den Sie zugreifen können.
Dave Wood
4
Zu
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
quelle
1
Die Swift 2-Implementierung eignet sich besonders für Enum-Fälle. Weiß jemand, ob dieses Verhalten von Apple dokumentiert / garantiert wird? Die Standardbibliothek enthält lediglich einen Kommentar, dass dies zum Debuggen geeignet ist ...
milos
30

Ist es das, wonach du suchst?

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

Es wird "__NSDate" gedruckt.

UPDATE : Bitte beachten Sie, dass dies ab Beta05 nicht mehr zu funktionieren scheint

Haiku Oezu
quelle
2
Funktioniert nicht für schnelle Klassen. Gibt "UnsafePointer (0x7FBB18D06DE0)" zurück
aryaxt
4
Funktioniert auch nicht für ObjC-Klassen (zumindest in Beta5), für ein NSManagedObject bekomme ich nur "Builtin.RawPointer = address"
Kendall Helmstetter Gelner
23

Mein aktueller Xcode ist Version 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).")
    }
}

Ausgabe:

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
quelle
1
Gut, aber die Frage enthielt auch Optionals, die Ausgabe von Optionals ist eingestellt Optional(...), sodass Ihr Code nur Optionalals Typ zurückgegeben wird. Es sollte auch var optionalTestVar: Person? = Person(name:"Sarah")als Optional (Person) und var mit Person angezeigt werden! als ImplicitlyUnwrappedOptional (Person)
Binarian
18

Ab Xcode 6.3 mit Swift 1.2 können Sie einfach Typwerte in vollständig entwirrte konvertieren 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"
Kiding
quelle
Ist die andere Richtung in 1.2 möglich? So initialisieren Sie eine Instanz basierend auf dem Klassennamen?
user965972
@ user965972 Soweit ich weiß, glaube ich nicht, dass es welche gibt.
Kiding
17

Sie können weiterhin über className(was a zurückgibt String) auf die Klasse zugreifen .

Es gibt tatsächlich mehr Möglichkeiten , um die Klasse, zum Beispiel zu bekommen classForArchiver, classForCoder, classForKeyedArchiver(alle zurück AnyClass!).

Sie können den Typ eines Grundelements nicht ermitteln (ein Grundelement ist keine Klasse).

Beispiel:

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

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

Wenn Sie den Typ eines Grundelements erhalten möchten, müssen Sie verwenden bridgeToObjectiveC(). Beispiel:

var i = 1
i.bridgeToObjectiveC().className // __NSCFNumber
Leandros
quelle
Ich wette, es ist ein Primitiv. Leider kann man den Typ eines Grundelements nicht bekommen.
Leandros
Diese Beispiele scheinen auf dem Spielplatz nicht zu funktionieren. Ich erhalte den Fehler für Primitive und Nicht-Primitive gleichermaßen.
Matt Bridges
versuche es import Cocoa.
Leandros
9
className scheint nur für NSObjects verfügbar zu sein, wenn für OSX entwickelt wird. Es ist im iOS SDK weder für NSObjects noch für "normale" Objekte verfügbar
Matt Bridges
3
classNameist Teil der AppleScript-Unterstützung von Cocoa und sollte auf keinen Fall für die allgemeine Selbstbeobachtung verwendet werden. Offensichtlich ist es unter iOS nicht verfügbar.
Nikolai Ruhe
16

Sie können Reflect verwenden, um Informationen zum Objekt abzurufen.
Zum Beispiel Name der Objektklasse:

var classname = reflektiere (jetzt) ​​.summary
Stan
quelle
In Beta 6 bekam ich den App-Namen + Klassennamen in einer leicht verstümmelten Form, aber es ist ein Anfang. +1 für reflect(x).summary- danke!
Olie
hat nicht funktioniert, druckt eine leere Zeile in Swift 1.2 Xcode 6.4 und iOs 8.4
Juan Boero
13

Ich hatte Glück mit:

let className = NSStringFromClass(obj.dynamicType)
mxcl
quelle
@hdost Alter nichts hat funktioniert, aber classForCoder hat funktioniert.
Satheeshwaran
12

Xcode 8 Swift 3.0 verwendet Typ (von :)

let className = "\(type(of: instance))"
Hari Kunwar
quelle
10

In Xcode 8 Swift 3.0

Schritte:

1. Holen Sie sich den Typ:

Option 1:

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

Option 2:

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

2. Typ in String konvertieren:

let string : String = "\(type)" //String
user1046037
quelle
8

In Swift 3.0 können Sie verwenden type(of:), da das dynamicTypeSchlüsselwort entfernt wurde.

Bruno Serrano
quelle
7

SWIFT 5

Mit der neuesten Version von Swift 3 können wir über den StringInitialisierer hübsche Beschreibungen von Typnamen erhalten. Wie zum Beispiel print(String(describing: type(of: object))). Wo object kann eine Instanzvariable wie ein Array, ein Wörterbuch, eine Int, eine NSDate, eine Instanz einer benutzerdefinierten Klasse usw. sein?

Hier ist meine vollständige Antwort: Holen Sie sich den Klassennamen des Objekts als Zeichenfolge in Swift

Diese Frage sucht nach einer Möglichkeit, den Klassennamen eines Objekts als Zeichenfolge abzurufen, aber ich schlug auch eine andere Möglichkeit vor, den Klassennamen einer Variablen abzurufen, die keine Unterklasse von ist NSObject. Hier ist es:

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

Ich habe eine statische Funktion erstellt, die als Parameter ein Objekt vom Typ verwendet Anyund dessen Klassennamen als zurückgibtString :) .

Ich habe diese Funktion mit einigen Variablen getestet wie:

    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()

und die Ausgabe war:

  • diccionary ist vom Typ Dictionary
  • Array ist vom Typ Array
  • numInt ist vom Typ Int
  • numFloat ist vom Typ CGFloat
  • numDouble ist vom Typ Double
  • classOne ist vom Typ: ClassOne
  • classTwo ist vom Typ: ClassTwo
  • Jetzt ist vom Typ: Datum
  • lbl ist vom Typ: UILabel
mauricioconde
quelle
5

Wenn Sie Cocoa (nicht CocoaTouch) verwenden, können Sie das verwenden className Eigenschaft für Objekte verwenden, die Unterklassen von NSObject sind.

println(now.className)

Diese Eigenschaft ist nicht für normale Swift-Objekte verfügbar, die keine Unterklassen von NSObject sind (und tatsächlich gibt es in Swift keine Stamm-ID oder keinen Objekttyp).

class Person {
    var name: String?
}

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

In CocoaTouch gibt es derzeit keine Möglichkeit, eine Zeichenfolgenbeschreibung des Typs einer bestimmten Variablen abzurufen. Eine ähnliche Funktionalität gibt es auch für primitive Typen in Cocoa oder CocoaTouch nicht.

Die Swift REPL kann eine Zusammenfassung der Werte einschließlich ihres Typs ausdrucken, sodass diese Art der Selbstbeobachtung möglicherweise in Zukunft über eine API möglich sein wird.

EDIT : dump(object)scheint den Trick zu tun.

Matt Bridges
quelle
Auch ab Xcode 10 und Swift 4.2 dump(object)ist es wirklich mächtig. Vielen Dank.
Alex Zavatone
5

Die Top-Antwort enthält kein funktionierendes Beispiel für die neue Vorgehensweise type(of:. Um Anfängern wie mir zu helfen, finden Sie hier ein funktionierendes Beispiel, das hauptsächlich aus Apples Dokumenten hier stammt - 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
quelle
4

Ich habe einige der anderen Antworten hier ausprobiert, aber die Laufleistung scheint sehr darauf zu beruhen, was das untergeordnete Objekt ist.

Ich habe jedoch einen Weg gefunden, wie Sie den Object-C-Klassennamen für ein Objekt erhalten können, indem Sie Folgendes tun:

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

Hier ist ein Beispiel, wie Sie es verwenden würden:

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

In diesem Fall wird NSDate in der Konsole gedruckt.

James Jones
quelle
4

Ich habe diese Lösung gefunden, die hoffentlich für jemand anderen funktioniert. Ich habe eine Klassenmethode erstellt, um auf den Wert zuzugreifen. Bitte beachten Sie, dass dies nur für die NSObject-Unterklasse funktioniert. Aber zumindest ist eine saubere und ordentliche Lösung.

class var className: String!{
    let classString : String = NSStringFromClass(self.classForCoder())
    return classString.componentsSeparatedByString(".").last;
}
DennyLou
quelle
4

Im neuesten XCode 6.3 mit Swift 1.2 ist dies der einzige Weg, den ich gefunden habe:

if view.classForCoder.description() == "UISegment" {
    ...
}
Joel Kopelioff
quelle
HINWEIS: description () gibt den Klassennamen im Format zurück <swift module name>.<actual class name>, sodass Sie die Zeichenfolge mit a teilen .und das letzte Token erhalten möchten .
Matthew Quiros
4

Viele der Antworten hier funktionieren nicht mit dem neuesten Swift (Xcode 7.1.1 zum Zeitpunkt des Schreibens).

Der aktuelle Weg, um die Informationen zu erhalten, besteht darin, eine zu erstellen Mirrorund diese abzufragen. Für den Klassennamen ist es so einfach wie:

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

Zusätzliche Informationen zum Objekt können auch aus dem abgerufen werden Mirror. Weitere Informationen finden Sie unter http://swiftdoc.org/v2.1/type/Mirror/ .

Joseph Lord
quelle
Was ist falsch an den Antworten stackoverflow.com/a/25345480/1187415 und stackoverflow.com/a/32087449/1187415 ? Beide scheinen mit Swift 2 recht gut zu funktionieren. (Die anderen wurden nicht überprüft.)
Martin R
Ich mag dies als allgemeine Lösung, aber "Mirror for ViewController" (fremdes "Mirror for") zu bekommen - warte, es sieht so aus, als würde ".subjectType" verwendet!
David H
3

In lldb ab Beta 5 können Sie die Klasse eines Objekts mit dem folgenden Befehl anzeigen:

fr v -d r shipDate

welches etwas ausgibt wie:

(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940

Der erweiterte Befehl bedeutet ungefähr:

Frame Variable (eine Rahmenvariable drucken) -d run_target (dynamische Typen erweitern)

Es ist nützlich zu wissen, dass die Verwendung von "Frame Variable" zur Ausgabe von Variablenwerten garantiert, dass kein Code ausgeführt wird.

Kendall Helmstetter Gelner
quelle
3

Ich habe eine Lösung für selbst entwickelte Klassen gefunden (oder solche, auf die Sie Zugriff haben).

Platzieren Sie die folgende berechnete Eigenschaft in Ihrer Objektklassendefinition:

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

Jetzt können Sie einfach den Klassennamen für Ihr Objekt wie folgt aufrufen:

myObject.className

Bitte beachten Sie, dass dies nur funktioniert, wenn Ihre Klassendefinition in einer Datei erstellt wird, deren Name genau der Klasse entspricht, deren Namen Sie möchten.

Da dies üblicherweise der Fall ist, sollte die obige Antwort dies in den meisten Fällen tun . In einigen besonderen Fällen müssen Sie möglicherweise eine andere Lösung finden.


Wenn Sie den Klassennamen in der Klasse (Datei) selbst benötigen , können Sie einfach diese Zeile verwenden:

let className = __FILE__.lastPathComponent.stringByDeletingPathExtension

Vielleicht hilft diese Methode einigen Leuten da draußen.

Jeehut
quelle
3

Basierend auf den Antworten und Kommentaren von Klass und Kevin Ballard würde ich gehen mit:

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!)

welches ausgedruckt wird:

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

"NSString"
"PureSwiftClass"
"Int"
"Double"
Vince O'Sullivan
quelle
Ich denke, das ist die bessere Antwort.
Ultraschall
Am Ende habe ich in Swift 1.2 Folgendes verwendet: toString(self.dynamicType).componentsSeparatedByString(".").last!Offensichtlich befand ich mich in einem Objektkontext und konnte referenzieren 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
quelle
3

Schnelle Version 4:

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

Danke @Joshua Dance

dengApro
quelle
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
}

Verwendungszweck:

print(stringType(of: SomeClass()))     // "SomeClass"
print(stringType(of: SomeClass.self))  // "SomeClass"
print(stringType(of: String()))        // "String"
print(fullStringType(of: String()))    // "Swift.String"
Desmond Hume
quelle
2

Es scheint keine generische Möglichkeit zu geben, den Typnamen eines beliebigen Werttyps zu drucken. Wie andere angemerkt haben, können Sie für Klasseninstanzen druckenvalue.className aber für primitive Werte scheint es, dass zur Laufzeit die Typinformationen weg sind.

Zum Beispiel sieht es so aus, als gäbe es keine Möglichkeit zu tippen: 1.something()und Intfür einen Wert von rauszukommen something. (Sie können, wie eine andere Antwort vorgeschlagen, verwenden i.bridgeToObjectiveC().classNameSie einen Hinweis geben, aber __NSCFNumberist nicht wirklich die Art von i-. Genau das, was es zu konvertierenden wird , wenn er überquert die Grenze eines Objective-C - Funktionsaufruf)

Ich würde mich freuen, wenn ich mich als falsch erweisen würde, aber es sieht so aus, als ob die Typprüfung alle zur Kompilierungszeit durchgeführt wird und wie bei C ++ (mit deaktiviertem RTTI) sind viele der Typinformationen zur Laufzeit verschwunden.

ipmcc
quelle
Können Sie ein Beispiel für die Verwendung von className geben, um "NSDate" für die Variable "now" in meinem Beispiel zu drucken, das auf dem Xcode6-Spielplatz funktioniert? Soweit ich das beurteilen kann, ist className nicht für Swift-Objekte definiert, auch nicht für solche, die Unterklassen von NSObject sind.
Matt Bridges
Es scheint, dass 'className' für Objekte verfügbar ist, die von NSObject abstammen, jedoch nur bei der Entwicklung für Mac, nicht für iOS. Für iOS scheint es überhaupt keine Problemumgehung zu geben.
Matt Bridges
1
Ja, der eigentliche Vorteil hier scheint zu sein, dass im Allgemeinen die Typinformationen zur Laufzeit schnell verschwunden sind.
Ipmcc
Ich bin gespannt, wie die REPL die Wertetypen drucken kann.
Matt Bridges
Die REPL wird mit ziemlicher Sicherheit interpretiert und nicht kompiliert, was es leicht erklären würde
ipmcc
2

Auf diese Weise erhalten Sie eine Typzeichenfolge Ihres Objekts oder Typs, die konsistent ist und berücksichtigt, zu welchem Modul die Objektdefinition gehört oder in dem sie verschachtelt ist. Funktioniert in 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
quelle
2

Um einen Objekttyp oder eine Objektklasse in Swift abzurufen , müssen Sie einen Typ (von: yourObject) verwenden.

Typ (von: yourObject)

Rahul Panzade
quelle
1

Nicht genau das, wonach Sie suchen, aber Sie können den Typ der Variablen auch anhand der folgenden Swift-Typen überprüfen:

let object: AnyObject = 1

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

Zum Beispiel.

PersuitOfPerfection
quelle
1

Xcode 7.3.1, Swift 2.2:

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

Leanne
quelle