如何在Swift语言中实现反思?
我如何实例化一个类
[[NSClassFromString(@"Foo") alloc] init];
Rigel Chen.. 52
这是我通过类名初始化UIViewController的方式
var className = "YourAppName.TestViewController" let aClass = NSClassFromString(className) as! UIViewController.Type let viewController = aClass()
更多信息在这里
在iOS 9中
var className = "YourAppName.TestViewController" let aClass = NSClassFromString(className) as! UIViewController.Type let viewController = aClass.init()
如果应用名称包含" - ",则应将其替换为"_" (9认同)
小智.. 51
你必须把@objc(SwiftClassName)
你的快速课程放在上面.
喜欢:
@objc(SubClass) class SubClass: SuperClass {...}
`NSClassFromString()`函数需要由`@objc`属性指定的名称. (2认同)
Kevin Delord.. 36
这里不太讨厌的解决方案:https://stackoverflow.com/a/32265287/308315
请注意,Swift类现在是命名空间,因此它不是"MyViewController"而是"AppName.MyViewController"
自XCode6-beta 6/7后不再使用
使用XCode6-beta 3开发的解决方案
感谢Edwin Vermeer的回答,我能够构建一些东西,通过这样做将Swift类实例化为Obj-C类:
// 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 }
编辑
你也可以用纯粹的obj-c来做:
- (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); }
我希望这会对某人有所帮助!
这里不太讨厌的解决方案:https://stackoverflow.com/a/32265287/308315
请注意,Swift类现在是命名空间,因此它不是"MyViewController"而是"AppName.MyViewController"
自XCode6-beta 6/7后不再使用
使用XCode6-beta 3开发的解决方案
感谢Edwin Vermeer的回答,我能够构建一些东西,通过这样做将Swift类实例化为Obj-C类:
// 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 }
编辑
你也可以用纯粹的obj-c来做:
- (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); }
我希望这会对某人有所帮助!
你必须把@objc(SwiftClassName)
你的快速课程放在上面.
喜欢:
@objc(SubClass) class SubClass: SuperClass {...}
这是我通过类名初始化UIViewController的方式
var className = "YourAppName.TestViewController" let aClass = NSClassFromString(className) as! UIViewController.Type let viewController = aClass()
更多信息在这里
在iOS 9中
var className = "YourAppName.TestViewController" let aClass = NSClassFromString(className) as! UIViewController.Type let viewController = aClass.init()
更新:从beta 6开始NSStringFromClass将返回您的包名称加上以点分隔的类名.所以它会像MyApp.MyClass
Swift类将具有由以下部分构成的构造内部名称:
它将从_TtC开始,
后跟一个数字,即应用程序名称的长度,
然后是您的应用程序名称,
下面是一个数字,即你的班级名称的长度,
然后是你的班级名字.
所以你的类名将是_TtC5MyApp7MyClass
您可以通过执行以下命令将此名称作为字符串:
var classString = NSStringFromClass(self.dynamicType)
更新在Swift 3中,这已更改为:
var classString = NSStringFromClass(type(of: self))
使用该字符串,您可以通过执行以下命令来创建Swift类的实例:
var anyobjectype : AnyObject.Type = NSClassFromString(classString) var nsobjectype : NSObject.Type = anyobjectype as NSObject.Type var rec: AnyObject = nsobjectype()
它几乎是一样的
func NSClassFromString(_ aClassName: String!) -> AnyClass!
检查此文档:
https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/#//apple_ref/c/func/NSClassFromString
我能够动态地实例化一个对象
var clazz: NSObject.Type = TestObject.self var instance : NSObject = clazz() if let testObject = instance as? TestObject { println("yes!") }
我还没有找到一种方式来创建AnyClass
从一个String
(不使用的OBJ-C).我认为他们不希望你这样做,因为它基本上打破了类型系统.
对于swift2,我创建了一个非常简单的扩展来更快地执行此操作 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() } }
在我的情况下,我这样做加载我想要的ViewController:
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) }
这将为您提供要实例化的类的名称.然后,您可以使用Edwins的答案来实例化您的类的新对象.
从beta 6开始,_stdlib_getTypeName
获取变量的错位类型名称.将其粘贴到空的操场上:
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))")
输出是:
TypeName0 = NSString TypeName1 = _TtC13__lldb_expr_014PureSwiftClass TypeName2 = _TtSi TypeName3 = _TtSS
Ewan Swick的博客文章有助于破译这些字符串:http://www.eswick.com/2014/06/inside-swift/
例如_TtSi
代表Swift的内部Int
类型.
xcode 7 beta 5:
class MyClass { required init() { print("Hi!") } } if let classObject = NSClassFromString("YOURAPPNAME.MyClass") as? MyClass.Type { let object = classObject.init() }
let vcName = "HomeTableViewController" let ns = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String // Convert string to class let anyobjecType: AnyObject.Type = NSClassFromString(ns + "." + vcName)! if anyobjecType is UIViewController.Type { // vc is instance let vc = (anyobjecType as! UIViewController.Type).init() print(vc) }