type pass parameter objetos metatype swift typechecking

pass - swift class type



¿Cómo averiguas el tipo de un objeto(en Swift)? (11)

Cuando se trata de entender un programa, o en algunos casos, es útil poder averiguar qué tipo es algo. Sé que el depurador puede mostrarle cierta información de tipo y, por lo general, puede confiar en la inferencia de tipos para no especificar el tipo en esas situaciones, pero aún así, realmente me gustaría tener algo como el type() de Python type()

dynamicType (ver esta pregunta )

Actualización: esto se ha modificado en una versión reciente de Swift, obj.dynamicType ahora le proporciona una referencia al tipo y no a la instancia del tipo dinámico.

Este parece el más prometedor, pero hasta ahora no he podido averiguar el tipo real

class MyClass { var count = 0 } let mc = MyClass() # update: this now evaluates as true mc.dynamicType === MyClass.self

También intenté usar una referencia de clase para crear una instancia de un nuevo objeto, que funciona, pero extrañamente me dio un error diciendo que debo agregar un inicializador required :

trabajos:

class MyClass { var count = 0 required init() { } } let myClass2 = MyClass.self let mc2 = MyClass2()

Sin embargo, solo es un pequeño paso para descubrir realmente el tipo de un objeto determinado.

edición : he eliminado una cantidad sustancial de detalles irrelevantes ahora - mira el historial de edición si estás interesado :)


A partir de Xcode 6.0.1 (al menos, no estoy seguro de cuándo lo agregaron), su ejemplo original ahora funciona:

class MyClass { var count = 0 } let mc = MyClass() mc.dynamicType === MyClass.self // returns `true`

Actualizar:

Para responder a la pregunta original, puede utilizar el tiempo de ejecución de Obj-C con objetos Swift sin problemas con éxito.

Intenta lo siguiente:

import Foundation class MyClass { } class SubClass: MyClass { } let mc = MyClass() let m2 = SubClass() // Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground String.fromCString(class_getName(m2.dynamicType)) String.fromCString(object_getClassName(m2)) // Returns .Some("__lldb_expr_42.MyClass") String.fromCString(object_getClassName(mc))


Aquí hay 2 maneras en que recomiendo hacerlo:

if let thisShape = aShape as? Square

O:

aShape.isKindOfClass(Square)

Aquí hay un ejemplo detallado:

class Shape { } class Square: Shape { } class Circle: Shape { } var aShape = Shape() aShape = Square() if let thisShape = aShape as? Square { println("Its a square") } else { println("Its not a square") } if aShape.isKindOfClass(Square) { println("Its a square") } else { println("Its not a square") }


Depende del caso de uso. Pero supongamos que desea hacer algo útil con sus tipos de "variable". La instrucción Swift switch es muy poderosa y puede ayudarlo a obtener los resultados que está buscando ...

let dd2 = ["x" : 9, "y" : "home9"] let dds = dd2.filter { let eIndex = "x" let eValue:Any = 9 var r = false switch eValue { case let testString as String: r = $1 == testString case let testUInt as UInt: r = $1 == testUInt case let testInt as Int: r = $1 == testInt default: r = false } return r && $0 == eIndex }

En este caso, tenga un diccionario simple que contenga pares clave / valor que puedan ser UInt, Int o String. En el método .filter() en el diccionario, debo asegurarme de probar los valores correctamente y solo probar una Cadena cuando es una cadena, etc. ¡La declaración de cambio hace que esto sea simple y seguro! Al asignar 9 a la variable de tipo Cualquiera, hace que el interruptor para Int ejecute. Intenta cambiarlo a:

let eValue:Any = "home9"

..y vuelve a intentarlo. Esta vez ejecuta el caso as String .


El código "dynamicType.printClassName" proviene de un ejemplo en el libro Swift. No conozco ninguna forma de capturar directamente un nombre de clase personalizado, pero puede verificar un tipo de instancias usando la palabra clave "es" como se muestra a continuación. Este ejemplo también muestra cómo implementar una función de nombre de clase personalizada, si realmente desea el nombre de clase como una cadena.

class Shape { class func className() -> String { return "Shape" } } class Square: Shape { override class func className() -> String { return "Square" } } class Circle: Shape { override class func className() -> String { return "Circle" } } func getShape() -> Shape { return Square() // hardcoded for example } let newShape: Shape = getShape() newShape is Square // true newShape is Circle // false newShape.dynamicType.className() // "Square" newShape.dynamicType.className() == Square.className() // true

Tenga en cuenta que las subclases de NSObject ya implementan su propia función className. Si está trabajando con Cocoa, puede utilizar esta propiedad.

class MyObj: NSObject { init() { super.init() println("My class is /(self.className)") } } MyObj()


En Swift 2.0, la forma correcta de hacer este tipo de introspección de tipo sería con la estructura Mirror ,

let stringObject:String = "testing" let stringArrayObject:[String] = ["one", "two"] let viewObject = UIView() let anyObject:Any = "testing" let stringMirror = Mirror(reflecting: stringObject) let stringArrayMirror = Mirror(reflecting: stringArrayObject) let viewMirror = Mirror(reflecting: viewObject) let anyMirror = Mirror(reflecting: anyObject)

Luego, para acceder al tipo en sí desde la estructura Mirror , usaría la propiedad subjectType así:

// Prints "String" print(stringMirror.subjectType) // Prints "Array<String>" print(stringArrayMirror.subjectType) // Prints "UIView" print(viewMirror.subjectType) // Prints "String" print(anyMirror.subjectType)

Entonces puedes usar algo como esto:

if anyMirror.subjectType == String.self { print("anyObject is a string!") } else { print("anyObject is not a string!") }


Esto funciona en swift 3.

if unknownType is MyClass { //unknownType is of class type MyClass }


Para Swift 3.0

String(describing: <Class-Name>.self)

Para Swift 2.0 - 2.3

String(<Class-Name>)


Si recibe una advertencia de "siempre verdadero / falla", es posible que tenga que convertir a Cualquiera antes de usar.

(foo as Any) is SomeClass


Si simplemente necesita verificar si la variable es de tipo X, o si se ajusta a algún protocolo, entonces puede usar is , o as? como en el siguiente

var unknownTypeVariable = … if unknownTypeVariable is <ClassName> { //the variable is of type <ClassName> } else { //variable is not of type <ClassName> }

Esto es equivalente a isKindOfClass en Obj-C.

Y esto es equivalente a conformsToProtocol , o isMemberOfClass

var unknownTypeVariable = … if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> { //unknownTypeVarible is of type <ClassName or ProtocolName> } else { //unknownTypeVariable is not of type <ClassName or ProtocolName> }


Versión Swift 3:

type(of: yourObject)


//: Playground - noun: a place where people can play import UIKit class A { class func a() { print("yeah") } func getInnerValue() { self.dynamicType.a() } } class B: A { override class func a() { print("yeah yeah") } } B.a() // yeah yeah A.a() // yeah B().getInnerValue() // yeah yeah A().getInnerValue() // yeah