transportation the significado programming programación lenguaje language español descargar swift

the - swift(lenguaje de programación)



Obtener el nombre de clase del objeto como cadena en Swift (23)

Swift 3.1

Aquí está la extensión para obtener el className como una variable (tanto para la instancia como para el objeto de clase).

extension NSObject { var className: String { return String(describing: type(of: self)) } class var className: String { return String(describing: self) } }

Cómo utilizar:

print(self.className) print(ViewController.className)

Obtener el nombre de clase de un objeto como cadena usando

object_getClassName(myViewController)

devuelve algo como esto

_TtC5AppName22CalendarViewController

Estoy buscando la versión pura : "CalendarViewController". ¿Cómo consigo una cadena limpia del nombre de la clase?

Encontré algunos intentos de preguntas sobre esto, pero no una respuesta real. ¿No es posible?


A veces, las otras soluciones le darán un nombre no útil dependiendo del objeto que está tratando de mirar. En ese caso, puede obtener el nombre de la clase como una cadena utilizando lo siguiente.

String(cString: object_getClassName(Any!))

⌘ haga clic en la función en xcode para ver algunos métodos relacionados que son bastante útiles. o consulte aquí https://developer.apple.com/reference/objectivec/objective_c_functions


Cadena de una instancia :

String(describing: YourType.self)

Cadena de un tipo :

String(describing: self)

Ejemplo:

struct Foo { // Instance Level var typeName: String { return String(describing: Foo.self) } // Instance Level - Alternative Way var otherTypeName: String { let thisType = type(of: self) return String(describing: thisType) } // Type Level static var typeName: String { return String(describing: self) } } Foo().typeName // = "Foo" Foo().otherTypeName // = "Foo" Foo.typeName // = "Foo"

Probado con class , struct y enum .


En Swift 4.1 y ahora Swift 4.2 :

import Foundation class SomeClass { class InnerClass { let foo: Int init(foo: Int) { self.foo = foo } } let foo: Int init(foo: Int) { self.foo = foo } } class AnotherClass : NSObject { let foo: Int init(foo: Int) { self.foo = foo super.init() } } struct SomeStruct { let bar: Int init(bar: Int) { self.bar = bar } } let c = SomeClass(foo: 42) let s = SomeStruct(bar: 1337) let i = SomeClass.InnerClass(foo: 2018) let a = AnotherClass(foo: 1<<8)

Si no tienes una instancia alrededor:

String(describing: SomeClass.self) // Result: SomeClass String(describing: SomeStruct.self) // Result: SomeStruct String(describing: SomeClass.InnerClass.self) // Result: InnerClass String(describing: AnotherClass.self) // Result: AnotherClass

Si tienes una instancia en torno a:

String(describing: type(of: c)) // Result: SomeClass String(describing: type(of: s)) // Result: SomeStruct String(describing: type(of: i)) // Result: InnerClass String(describing: type(of: a)) // Result: AnotherClass


En mi caso, String (describiendo: self) devolvió algo como:

<My_project.ExampleViewController: 0x10b2bb2b0>

Pero me gustaría tener algo como getSimpleName en Android.

Así que he creado una pequeña extensión:

extension UIViewController { func getSimpleClassName() -> String { let describing = String(describing: self) if let dotIndex = describing.index(of: "."), let commaIndex = describing.index(of: ":") { let afterDotIndex = describing.index(after: dotIndex) if(afterDotIndex < commaIndex) { return String(describing[afterDotIndex ..< commaIndex]) } } return describing } }

Y ahora vuelve:

ExampleViewController

La extensión de NSObject en lugar de UIViewController también debería funcionar. La función anterior también es a prueba de fallos :)


He estado buscando esta respuesta de vez en cuando. Utilizo GKStateMachine y me gusta observar los cambios de estado y quería una forma fácil de ver solo el nombre de la clase. No estoy seguro de si es solo iOS 10 o Swift 2.3, pero en ese entorno, lo siguiente hace exactamente lo que quiero:

let state:GKState? print("Class Name: /(String(state.classForCoder)") // Output: // Class Name: GKState


Intenté type(of:...) en Playground con Swift 3. Este es mi resultado. Esta es la versión en formato de código.

print(String(describing: type(of: UIButton.self))) print(String(describing: type(of: UIButton()))) UIButton.Type UIButton


Intente reflect().summary en la clase auto o instancia de tipo dinámico. Desenvuelva las opciones antes de obtener dynamicType; de ​​lo contrario, el dynamicType es el contenedor opcional.

class SampleClass { class InnerClass{} } let sampleClassName = reflect(SampleClass.self).summary; let instance = SampleClass(); let instanceClassName = reflect(instance.dynamicType).summary; let innerInstance = SampleClass.InnerClass(); let InnerInstanceClassName = reflect(innerInstance.dynamicType).summary.pathExtension; let tupleArray = [(Int,[String:Int])](); let tupleArrayTypeName = reflect(tupleArray.dynamicType).summary;

El resumen es una ruta de clase con los tipos genéricos descritos. Para obtener un nombre de clase simple del resumen, pruebe este método.

func simpleClassName( complexClassName:String ) -> String { var result = complexClassName; var range = result.rangeOfString( "<" ); if ( nil != range ) { result = result.substringToIndex( range!.startIndex ); } range = result.rangeOfString( "." ); if ( nil != range ) { result = result.pathExtension; } return result; }


Las soluciones anteriores no funcionaron para mí. Producido en su mayoría los temas mencionados en varios comentarios

MyAppName.ClassName

o

MyFrameWorkName.ClassName

Estas soluciones funcionaron en XCode 9, Swift 3.0:

Lo nombré classNameCleaned para que sea más fácil de acceder y no entre en conflicto con futuros cambios de className() :

extension NSObject { static var classNameCleaned : String { let className = self.className() if className.contains(".") { let namesArray = className.components(separatedBy: ".") return namesArray.last ?? className } else { return self.className() } }

}

Uso:

NSViewController.classNameCleaned MyCustomClass.classNameCleaned


Lo uso en Swift 2.2

guard let currentController = UIApplication.topViewController() else { return } currentController.classForCoder.description().componentsSeparatedByString(".").last!


Para obtener el nombre de la clase como String declara tu clase como sigue

@objc(YourClassName) class YourClassName{}

Y obtenga el nombre de la clase usando la siguiente sintaxis

NSStringFromClass(YourClassName)


Para obtener el nombre del tipo como una cadena en Swift 4 (no he revisado las versiones anteriores), solo use la interpolación de cadenas:

"/(type(of: myViewController))"

Puede usar .self en un tipo en sí mismo, y la función type(of:_) en una instancia:

// Both constants will have "UIViewController" as their value let stringFromType = "/(UIViewController.self)" let stringFromInstance = "/(type(of: UIViewController()))"


Puede extender NSObjectProtocol en Swift 4 de la siguiente manera:

import Foundation extension NSObjectProtocol { var className: String { return String(describing: Self.self) } }

Esto hará que la variable calculada className esté disponible para TODAS las clases. Al usar esto dentro de un print() en CalendarViewController se imprimirá "CalendarViewController" en la consola.


Puede usar la función de la biblioteca estándar de Swift llamada _stdlib_getDemangledTypeName esta manera:

let name = _stdlib_getDemangledTypeName(myViewController)


Puedes intentarlo de esta manera:

self.classForCoder.description()


Si no te gusta el nombre destrozado, puedes dictar tu propio nombre:

@objc(CalendarViewController) class CalendarViewController : UIViewController { // ... }

Sin embargo, sería mejor a largo plazo aprender a analizar el nombre mutilado. El formato es estándar y significativo y no cambiará.


Si tiene el tipo Foo , el siguiente código le dará "Foo" en Swift 3 y Swift 4:

let className = String(describing: Foo.self) // Gives you "Foo"

El problema con la mayoría de las respuestas aquí es que le dan "Foo.Type" como la cadena resultante cuando no tiene ninguna instancia del tipo, cuando lo que realmente quiere es simplemente "Foo" . Lo siguiente le da "Foo.Type" , como se menciona en un montón de las otras respuestas.

let className = String(describing: type(of: Foo.self)) // Gives you "Foo.Type"

El type(of:) parte es innecesario si solo quieres "Foo" .


Sugiero tal enfoque ( muy Swifty ):

// Swift 3 func typeName(_ some: Any) -> String { return (some is Any.Type) ? "/(some)" : "/(type(of: some))" } // Swift 2 func typeName(some: Any) -> String { return (some is Any.Type) ? "/(some)" : "/(some.dynamicType)" }

No utiliza ni introspección ni desmantelamiento manual (¡ no hay magia! ).

Aquí hay una demostración:

// Swift 3 import class Foundation.NSObject func typeName(_ some: Any) -> String { return (some is Any.Type) ? "/(some)" : "/(type(of: some))" } class GenericClass<T> { var x: T? = nil } protocol Proto1 { func f(x: Int) -> Int } @objc(ObjCClass1) class Class1: NSObject, Proto1 { func f(x: Int) -> Int { return x } } struct Struct1 { var x: Int } enum Enum1 { case X } print(typeName(GenericClass<Int>.self)) // GenericClass<Int> print(typeName(GenericClass<Int>())) // GenericClass<Int> print(typeName(Proto1.self)) // Proto1 print(typeName(Class1.self)) // Class1 print(typeName(Class1())) // Class1 print(typeName(Class1().f)) // (Int) -> Int print(typeName(Struct1.self)) // Struct1 print(typeName(Struct1(x: 1))) // Struct1 print(typeName(Enum1.self)) // Enum1 print(typeName(Enum1.X)) // Enum1


Swift 3.0 (macOS 10.10 y versiones posteriores), puede obtenerlo de className

self.className.components(separatedBy: ".").last!


Swift 3.0

String(describing: MyViewController.self)


También se pueden usar espejos:

let vc = UIViewController() String(Mirror(reflecting: vc).subjectType)

NB: este método también se puede utilizar para Estructuras y Enums. Hay un displayStyle que da una indicación de qué tipo de estructura:

Mirror(reflecting: vc).displayStyle

El regreso es una enumeración para que puedas:

Mirror(reflecting: vc).displayStyle == .Class


ACTUALIZADO A SWIFT 3

Podemos obtener descripciones bonitas de los nombres de tipo utilizando la variable de instancia a través del inicializador de String y crear nuevos objetos de una clase determinada

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 , etc.

Debido a que NSObject es la clase raíz de la mayoría de las jerarquías de clases de Objective-C, puede intentar hacer una extensión para que NSObject obtenga el nombre de clase de cada subclase de NSObject . Me gusta esto:

extension NSObject { var theClassName: String { return NSStringFromClass(type(of: self)) } }

O podría hacer una función estática cuyo parámetro sea de tipo Any (el protocolo al que todos los tipos cumplen implícitamente) y devuelve el nombre de la clase como Cadena. Me gusta esto:

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

Ahora puedes hacer algo como esto:

class ClassOne : UIViewController{ // some code here } class ClassTwo : ClassOne{ // some code here } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Get the class name as String let dictionary: [String: CGFloat] = [:] let array: [Int] = [] let int = 9 let numFloat: CGFloat = 3.0 let numDouble: Double = 1.0 let classOne = ClassOne() let classTwo: ClassTwo? = ClassTwo() let now = NSDate() let lbl = UILabel() print("diccionary: [String: CGFloat] = [:] -> /(Utility.classNameAsString(diccionary))") print("array: [Int] = [] -> /(Utility.classNameAsString(array))") print("int = 9 -> /(Utility.classNameAsString(int))") print("numFloat: CGFloat = 3.0 -> /(Utility.classNameAsString(numFloat))") print("numDouble: Double = 1.0 -> /(Utility.classNameAsString(numDouble))") print("classOne = ClassOne() -> /((ClassTwo?).self)") //we use the Extension if classTwo != nil { print("classTwo: ClassTwo? = ClassTwo() -> /(Utility.classNameAsString(classTwo!))") //now we can use a Forced-Value Expression and unwrap the value } print("now = Date() -> /(Utility.classNameAsString(now))") print("lbl = UILabel() -> /(String(describing: type(of: lbl)))") // we use the String initializer directly } }

Además, una vez que podamos obtener el nombre de la clase como String, podemos crear una instancia de los nuevos objetos de esa clase :

// Instanciate a class from a String print("/nInstaciate a class from a String") let aClassName = classOne.theClassName let aClassType = NSClassFromString(aClassName) as! NSObject.Type let instance = aClassType.init() // we create a new object print(String(cString: class_getName(type(of: instance)))) print(instance.self is ClassOne)

Tal vez esto ayude a alguien por ahí !.


Swift 3.0: puedes crear una extensión como esta ... Devuelve el nombre de la clase sin el nombre del proyecto

extension NSObject { var className: String { return NSStringFromClass(self as! AnyClass).components(separatedBy: ".").last ?? "" } public class var className: String { return NSStringFromClass(self).components(separatedBy: ".").last ?? "" } }