Pregunta Swift language NSClassFromString


Como alcanzar reflexión en Swift Language?

¿Cómo puedo instanciar una clase?

[[NSClassFromString(@"Foo") alloc] init];

73
2018-06-04 06:48


origen


Respuestas:


Solución menos hacky aquí: https://stackoverflow.com/a/32265287/308315

Tenga en cuenta que las clases Swift están ahora espaciadas, por lo que en lugar de "MyViewController" sería "AppName.MyViewController".


Desaprobado desde XCode6-beta 6/7

Solución desarrollada usando XCode6-beta 3

Gracias a la respuesta de Edwin Vermeer, pude crear algo para crear instancias de clases Swift en una clase Obj-C haciendo esto:

// swift file
// extend the NSObject class
extension NSObject {
    // create a static method to get a swift class for a string name
    class func swiftClassFromString(className: String) -> AnyClass! {
        // get the project name
        if  var appName: String? = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName") as String? {
            // generate the full name of your class (take a look into your "YourProject-swift.h" file)
            let classStringName = "_TtC\(appName!.utf16count)\(appName)\(countElements(className))\(className)"
            // return the class!
            return NSClassFromString(classStringName)
        }
        return nil;
    }
}

// obj-c file
#import "YourProject-Swift.h"

- (void)aMethod {
    Class class = NSClassFromString(key);
    if (!class)
        class = [NSObject swiftClassFromString:(key)];
    // do something with the class
}

EDITAR

También puedes hacerlo en obj-c puro:

- (Class)swiftClassFromString:(NSString *)className {
    NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
    NSString *classStringName = [NSString stringWithFormat:@"_TtC%d%@%d%@", appName.length, appName, className.length, className];
    return NSClassFromString(classStringName);
}

¡Espero que esto ayude a alguien!


32
2017-07-17 15:58



Debes poner @objc(SwiftClassName) por encima de tu clase rápida.
Me gusta:

@objc(SubClass)
class SubClass: SuperClass {...}

44
2018-06-27 09:45



Esta es la forma en que inicié UIViewController por nombre de clase

var className = "YourAppName.TestViewController"
let aClass = NSClassFromString(className) as! UIViewController.Type
let viewController = aClass()

Más información es aquí

En iOS 9

var className = "YourAppName.TestViewController"
let aClass = NSClassFromString(className) as! UIViewController.Type
let viewController = aClass.init()

43
2017-08-28 07:11



ACTUALIZACIÓN: Comenzando con beta 6 NSStringFromClass devolverá el nombre de su paquete más el nombre de clase separado por un punto. Entonces será algo así como MyApp.MyClass

Las clases de Swift tendrán un nombre interno construido que consiste en la acumulación de las siguientes partes:

  • Comenzará con _TtC,
  • seguido por un número que es la longitud del nombre de su aplicación,
  • seguido de su nombre de aplicación,
  • seguido por un número que es la longitud de su nombre de clase,
  • seguido de tu nombre de clase.

Entonces, tu nombre de clase será algo así como _TtC5MyApp7MyClass

Puede obtener este nombre como una cadena ejecutando:

var classString = NSStringFromClass(self.dynamicType)

Actualizar En Swift 3 esto ha cambiado a:

var classString = NSStringFromClass(type(of: self))

Usando esa cadena, puedes crear una instancia de tu clase Swift ejecutando:

var anyobjectype : AnyObject.Type = NSClassFromString(classString)
var nsobjectype : NSObject.Type = anyobjectype as NSObject.Type
var rec: AnyObject = nsobjectype()

22
2017-07-02 06:13



Es casi lo mismo

func NSClassFromString(_ aClassName: String!) -> AnyClass!

Verifique este documento:

https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/#//apple_ref/c/func/NSClassFromString


10
2018-06-04 07:31



Pude crear una instancia de un objeto dinámicamente

var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()

if let testObject = instance as? TestObject {
    println("yes!")
}

No he encontrado una manera de crear AnyClass a partir de una String (sin usar Obj-C). Creo que no quieren que hagas eso porque básicamente rompe el sistema de tipos.


9
2018-06-05 13:21



Para swift2, creé una extensión muy simple para hacer esto más rápidamente https://github.com/damienromito/NSObject-FromClassName

extension NSObject {
    class func fromClassName(className : String) -> NSObject {
        let className = NSBundle.mainBundle().infoDictionary!["CFBundleName"] as! String + "." + className
        let aClass = NSClassFromString(className) as! UIViewController.Type
        return aClass.init()
    }
}

En mi caso, hago esto para cargar ViewController que quiero:

override func viewDidLoad() {
    super.viewDidLoad()
    let controllers = ["SettingsViewController", "ProfileViewController", "PlayerViewController"]
    self.presentController(controllers.firstObject as! String)

}

func presentController(controllerName : String){
    let nav = UINavigationController(rootViewController: NSObject.fromClassName(controllerName) as! UIViewController )
    nav.navigationBar.translucent = false
    self.navigationController?.presentViewController(nav, animated: true, completion: nil)
}

7
2017-11-03 15:05



Esto te dará el nombre de la clase a la que quieres crear una instancia. Entonces puedes usar Respuesta de Edwins para crear una instancia de un nuevo objeto de tu clase.

A partir de beta 6 _stdlib_getTypeName obtiene el nombre de tipo mutilado de una variable. Pega esto en un patio vacío:

import Foundation

class PureSwiftClass {
}

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

println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")

El resultado es:

TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS

La entrada del blog de Ewan Swick ayuda a descifrar estas cadenas: http://www.eswick.com/2014/06/inside-swift/

p.ej. _TtSi representa el interno de Swift Int tipo.


6
2017-08-17 01:07