data basics swift types

basics - ¿Cómo imprimo el tipo o la clase de una variable en Swift?



swift syntax (30)

¿Hay una manera de imprimir el tipo de tiempo de ejecución de una variable en swift? Por ejemplo:

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

En el ejemplo anterior, estoy buscando una manera de mostrar que la variable "pronto" es de tipo ImplicitlyUnwrappedOptional<NSDate> , o al menos NSDate! .


En Xcode 8, Swift 3.0

Pasos:

1. Obtener el tipo:

Opción 1:

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

Opcion 2:

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

2. Convertir Tipo a Cadena:

let string : String = "/(type)" //String


¿Es esto lo que estás buscando?

println("/(object_getClassName(now))");

Imprime "__NSDate"

ACTUALIZACIÓN : Tenga en cuenta que esto ya no parece funcionar a partir de Beta05


A partir de Xcode 6.3 con Swift 1.2, simplemente puede convertir los valores de tipo en la String completamente enredada.

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"


Aún puede acceder a la clase, a través de className (que devuelve una String ).

En realidad, hay varias formas de obtener la clase, por ejemplo, classForCoder , classForKeyedArchiver , classForKeyedArchiver (¡todos devuelven AnyClass! ).

No puede obtener el tipo de un primitivo (un primitivo no es una clase).

Ejemplo:

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

Si desea obtener el tipo de una primitiva, tiene que usar bridgeToObjectiveC() . Ejemplo:

var i = 1 i.bridgeToObjectiveC().className // __NSCFNumber


Así es como se obtiene una cadena de tipo de su objeto o Tipo que es consistente y tiene en cuenta a qué módulo pertenece o está anidada la definición del objeto. Funciona en 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


Basado en las respuestas y comentarios dados por Klass y Kevin Ballard arriba, me gustaría ir con:

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

que se imprimirá:

"NSDate" "ImplicitlyUnwrappedOptional" "Optional" "NSDate" "NSString" "PureSwiftClass" "Int" "Double"


Cuando use Cocoa (no CocoaTouch), puede usar la propiedad className para los objetos que son subclases de NSObject.

println(now.className)

Esta propiedad no está disponible para los objetos Swift normales, que no son subclases de NSObject (y de hecho, no hay id de raíz o tipo de objeto en Swift).

class Person { var name: String? } var p = Person() println(person.className) // <- Compiler error

En CocoaTouch, en este momento no hay una manera de obtener una descripción de cadena del tipo de una variable dada. Tampoco existe una funcionalidad similar para los tipos primitivos en Cocoa o CocoaTouch.

El Swift REPL puede imprimir un resumen de valores, incluido su tipo, por lo que es posible que esta forma de introspección sea posible a través de una API en el futuro.

EDIT : dump(object) parece hacer el truco.


Edición: Se ha introducido una nueva función toString en Swift 1.2 (Xcode 6.3) .

Ahora puede imprimir el tipo desmangrado de cualquier tipo usando .self y cualquier instancia usando .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

Intente llamar a YourClass.self y yourObject.dynamicType .

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


En Swift 3.0, puede usar type(of:) , ya que la palabra clave dynamicType se ha eliminado.


En el último XCode 6.3 con Swift 1.2, esta es la única forma que encontré:

if view.classForCoder.description() == "UISegment" { ... }


En lldb a partir de la versión beta 5, puede ver la clase de un objeto con el comando:

fr v -d r shipDate

que produce algo como:

(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940

El comando expandido significa algo como:

Frame Variable (imprimir una variable de marco) -d run_target (expandir tipos dinámicos)

Algo útil es saber que el uso de "Variable de marco" para generar valores de variables garantiza que no se ejecute ningún código.


Encontré esta solución que, con suerte, podría funcionar para otra persona. He creado un método de clase para acceder al valor. Tenga en cuenta que esto solo funcionará para la subclase NSObject. Pero al menos es una solución limpia y ordenada.

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


Esto también es útil cuando se comprueba si un objeto es un tipo de clase:

if someObject is SomeClass { //someObject is a type of SomeClass }


He encontrado una solución para las clases de desarrollo propio (o para las que tienes acceso).

Coloque la siguiente propiedad calculada dentro de la definición de su clase de objetos:

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

Ahora puedes simplemente llamar el nombre de la clase en tu objeto así:

myObject.className

Tenga en cuenta que esto solo funcionará si su definición de clase se realiza dentro de un archivo cuyo nombre es exactamente igual al de la clase de la que desea el nombre.

Como suele ser el caso, la respuesta anterior debería hacerlo en la mayoría de los casos . Pero en algunos casos especiales es posible que necesite encontrar una solución diferente.

Si necesita el nombre de la clase dentro de la clase (archivo), simplemente puede usar esta línea:

let className = __FILE__.lastPathComponent.stringByDeletingPathExtension

Tal vez este método ayuda a algunas personas por ahí.


He intentado algunas de las otras respuestas aquí, pero Milage parece muy en lo que es el objeto subyacente.

Sin embargo, encontré una forma de obtener el nombre de la clase Object-C para un objeto haciendo lo siguiente:

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

Aquí está un ejemplo de cómo lo usarías:

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

En este caso imprimirá NSDate en la consola.


La respuesta principal no tiene un ejemplo práctico de la nueva forma de hacerlo usando type(of: Entonces, para ayudar a los novatos como yo, aquí hay un ejemplo práctico, tomado principalmente de los documentos de Apple aquí: 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''


Mi Xcode actual es la versión 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).") } }

Salida:

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.


Muchas de las respuestas aquí no funcionan con el último Swift (Xcode 7.1.1 en el momento de la escritura).

La forma actual de obtener la información es crear un Mirror e interrogarlo. Para el nombre de clase es tan simple como:

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

También se puede recuperar información adicional sobre el objeto desde el Mirror . Consulte http://swiftdoc.org/v2.1/type/Mirror/ para obtener más información.


No es exactamente lo que está buscando, pero también puede verificar el tipo de la variable con tipos Swift como:

let object: AnyObject = 1 if object is Int { } else if object is String { }

Por ejemplo.


Parece que no hay una forma genérica de imprimir el nombre de tipo de un tipo de valor arbitrario. Como han señalado otros, para las instancias de clase puede imprimir value.className pero para valores primitivos parece que en el tiempo de ejecución, la información de tipo desaparece.

Por ejemplo, parece que no hay una forma de escribir: 1.something() y salir de Int por cualquier valor de something . (Puede, como se sugiere en otra respuesta, usar i.bridgeToObjectiveC().className para darle una pista, pero __NSCFNumber no es realmente el tipo de i , exactamente a lo que se convertirá cuando cruce el límite de un Objective- Llamada a la función C)

Me encantaría que me demostraran que estoy equivocado, pero parece que la comprobación de tipos se realiza en tiempo de compilación, y como C ++ (con RTTI desactivado), gran parte de la información de tipos desaparece en el tiempo de ejecución.


Puedes usar reflect para obtener información sobre el objeto.
Por ejemplo, el nombre de la clase de objeto:

var classname = reflect(now).summary


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


Swift versión 4:

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

Gracias @Joshua Dance


Tuve suerte con:

let className = NSStringFromClass(obj.dynamicType)


Xcode 7.3.1, Swift 2.2:

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


Xcode 8 Swift 3.0 utiliza el tipo (de :)

let className = "/(type(of: instance))"


Actualización septiembre 2016

Swift 3.0: use type(of:) , eg type(of: someThing) (desde que se dynamicType palabra clave dynamicType )

Actualización de octubre de 2015 :

println los ejemplos a continuación a la nueva sintaxis de Swift 2.0 (por ejemplo, println se reemplazó con print , toString() ahora es String() ).

De las notas de lanzamiento de Xcode 6.3 :

@nschum señala en los comentarios que las notas de lanzamiento de Xcode 6.3 muestran otra manera:

Los valores de tipo ahora se imprimen como el nombre completo de tipo desmangrado cuando se utilizan con println o interpolación de cadenas.

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

Qué salidas:

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>

Actualización para Xcode 6.3:

Puede usar el _stdlib_getDemangledTypeName() :

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

y obtén esto como salida:

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

Respuesta original:

Antes de Xcode 6.3 _stdlib_getTypeName obtuvo el nombre de tipo mutilado de una variable. La entrada del blog de Ewan Swick ayuda a descifrar estas cadenas:

Por ejemplo, _TtSi significa el tipo interno de Swift.

Mike Ash tiene una gran entrada de blog que cubre el mismo tema .


SWIFT 3

Con la última versión de Swift 3 podemos obtener descripciones bonitas de nombres de tipos a través del inicializador de String . Como, por ejemplo, print(String(describing: type(of: object))) . Donde el object puede ser una variable de instancia como una matriz, un diccionario, un Int , un NSDate , una instancia de una clase personalizada, etc.

Aquí está mi respuesta completa: Obtener el nombre de clase del objeto como cadena en Swift

Esa pregunta está buscando una forma de obtener el nombre de clase de un objeto como una cadena, pero también propuse otra forma de obtener el nombre de clase de una variable que no es una subclase de NSObject . Aquí está:

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

Hice una función estática que toma como parámetro un objeto de tipo Any y devuelve su nombre de clase como String :).

He probado esta función con algunas variables como:

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

y la salida fue:

  • Diccionario es de tipo Diccionario
  • matriz es de tipo matriz
  • numInt es de tipo Int
  • numFloat es de tipo CGFloat
  • numDouble es de tipo doble
  • classOne es de tipo: ClassOne
  • classTwo es de tipo: ClassTwo
  • ahora es de tipo: fecha
  • lbl es de tipo: UILabel

Swift 3.0, Xcode 8

Con el siguiente código puedes pedir una instancia para su clase. También puede comparar dos instancias, ya sea teniendo la misma clase.

// CREATE pure SWIFT class class MySwiftClass { var someString : String = "default" var someInt : Int = 5 } // CREATE instances let firstInstance = MySwiftClass() let secondInstance = MySwiftClass() secondInstance.someString = "Donald" secondInstance.someInt = 24 // INSPECT instances if type(of: firstInstance) === MySwiftClass.self { print("SUCCESS with ===") } else { print("PROBLEM with ===") } if type(of: firstInstance) == MySwiftClass.self { print("SUCCESS with ==") } else { print("PROBLEM with ==") } // COMPARE CLASS OF TWO INSTANCES if type(of: firstInstance) === type(of: secondInstance) { print("instances have equal class") } else { print("instances have NOT equal class") }


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