答案 0 :(得分:51)
这是我通过类名
初始化UIViewController的方式var className = "YourAppName.TestViewController"
let aClass = NSClassFromString(className) as! UIViewController.Type
let viewController = aClass()
更多信息是here
在iOS 9中
var className = "YourAppName.TestViewController"
let aClass = NSClassFromString(className) as! UIViewController.Type
let viewController = aClass.init()
答案 1 :(得分:49)
你必须把@objc(SwiftClassName)
放在你的快速课程之上
喜欢:
@objc(SubClass)
class SubClass: SuperClass {...}
答案 2 :(得分:35)
此处不太苛刻的解决方案: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);
}
我希望这会对某人有所帮助!
答案 3 :(得分:26)
更新:从测试版6开始NSStringFromClass将返回您的包名称加上以点分隔的类名。所以它会像MyApp.MyClass
Swift类将具有由以下部分构成的构造内部名称:
所以你的类名将是_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()
答案 4 :(得分:10)
几乎相同
func NSClassFromString(_ aClassName: String!) -> AnyClass!
检查此文档:
答案 5 :(得分:9)
我能够动态实例化一个对象
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!")
}
我还没有找到从AnyClass
创建String
的方法(不使用Obj-C)。我认为他们不希望你这样做,因为它基本上打破了类型系统。
答案 6 :(得分:7)
对于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)
}
答案 7 :(得分:6)
这将为您提供要实例化的类的名称。然后,您可以使用Edwins answer来实例化类的新对象。
从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/
e.g。 _TtSi
代表Swift的内部Int
类型。
答案 8 :(得分:6)
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)
}
答案 9 :(得分:5)
xcode 7 beta 5:
class MyClass {
required init() { print("Hi!") }
}
if let classObject = NSClassFromString("YOURAPPNAME.MyClass") as? MyClass.Type {
let object = classObject.init()
}
答案 10 :(得分:3)
来自班级
的字符串let classString = NSStringFromClass(TestViewController.self)
或
let classString = NSStringFromClass(TestViewController.classForCoder())
从字符串中初始化UIViewController类:
let vcClass = NSClassFromString(classString) as! UIViewController.Type
let viewController = vcClass.init()
答案 11 :(得分:2)
显然,当只在运行时知道类的名称时,不可能(再)在Swift中实例化一个对象。对于NSObject的子类,可以使用Objective-C包装器。
至少你可以在没有Objective-C包装器的情况下实例化与运行时给出的另一个对象相同的类(使用xCode版本6.2 - 6C107a):
class Test : NSObject {}
var test1 = Test()
var test2 = test1.dynamicType.alloc()
答案 12 :(得分:2)
在Swift 2.0中(在Xcode 7的beta2中测试)它的工作原理如下:
NSClassFromString
确保来自className
的类型必须实现此init协议。
我希望很清楚,init
是一个包含该类的Obj-C运行时名称的字符串,默认情况下不仅仅是" Foo",但这个讨论是恕我直言,不是主要的你问题的主题。
您需要此协议,因为默认情况下,所有Swift类都不会实现{{1}}方法。
答案 13 :(得分:2)
看起来正确的咒语会......
func newForName<T:NSObject>(p:String) -> T? {
var result:T? = nil
if let k:AnyClass = NSClassFromString(p) {
result = (k as! T).dynamicType.init()
}
return result
}
...其中“p”代表“打包” - 一个独特的问题。
但是从AnyClass到T的关键演员目前会导致编译器崩溃,所以在此期间必须将k的初始化破坏成一个单独的闭包,编译得很好。
答案 14 :(得分:2)
我认为我说你不能,至少不是当前的beta(2)。希望这将在未来版本中发生变化。
您可以使用NSClassFromString
来获取类型为AnyClass
的变量,但似乎没有办法在Swift中实例化它。您可以使用bridge to Objective C and do it there或 - 如果适用于您的情况 - fall back to using a switch statement。
答案 15 :(得分:2)
我使用不同的目标,在这种情况下找不到swift类。您应该用CFBundleExecutable替换CFBundleName。我还修正了警告:
- (Class)swiftClassFromString:(NSString *)className {
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"];
NSString *classStringName = [NSString stringWithFormat:@"_TtC%lu%@%lu%@", (unsigned long)appName.length, appName, (unsigned long)className.length, className];
return NSClassFromString(classStringName);
}
答案 16 :(得分:2)
我在Swift 3中使用此类别:
//
// String+AnyClass.swift
// Adminer
//
// Created by Ondrej Rafaj on 14/07/2017.
// Copyright © 2017 manGoweb UK Ltd. All rights reserved.
//
import Foundation
extension String {
func convertToClass<T>() -> T.Type? {
return StringClassConverter<T>.convert(string: self)
}
}
class StringClassConverter<T> {
static func convert(string className: String) -> T.Type? {
guard let nameSpace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String else {
return nil
}
guard let aClass: T.Type = NSClassFromString("\(nameSpace).\(className)") as? T.Type else {
return nil
}
return aClass
}
}
使用方法是:
func getViewController(fromString: String) -> UIViewController? {
guard let viewController: UIViewController.Type = "MyViewController".converToClass() else {
return nil
}
return viewController.init()
}
答案 17 :(得分:1)
Swift 5 ,易于使用,这要归功于@Ondrej Rafaj的
源代码:
extension String {
fileprivate
func convertToClass<T>() -> T.Type? {
return StringClassConverter<T>.convert(string: self)
}
var controller: UIViewController?{
guard let viewController: UIViewController.Type = convertToClass() else {
return nil
}
return viewController.init()
}
}
class StringClassConverter<T> {
fileprivate
static func convert(string className: String) -> T.Type? {
guard let nameSpace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String, let aClass = NSClassFromString("\(nameSpace).\(className)") as? T.Type else {
return nil
}
return aClass
}
}
像这样打电话:
guard let ctrl = "ViewCtrl".controller else {
return
}
// ctrl do sth
答案 18 :(得分:1)
难道解决方案不是这么简单吗?
// Given the app/framework/module named 'MyApp'
let className = String(reflecting: MyClass.self)
// className = "MyApp.MyClass"
答案 19 :(得分:1)
我已经实现了这样,
if let ImplementationClass: NSObject.Type = NSClassFromString(className) as? NSObject.Type{
ImplementationClass.init()
}
答案 20 :(得分:1)
试试这个。
let className: String = String(ControllerName.classForCoder())
print(className)
答案 21 :(得分:1)
同样在Swift 2.0中(可能在之前?)您可以使用dynamicType
属性
即
class User {
required init() { // class must have an explicit required init()
}
var name: String = ""
}
let aUser = User()
aUser.name = "Tom"
print(aUser)
let bUser = aUser.dynamicType.init()
print(bUser)
输出
aUser: User = {
name = "Tom"
}
bUser: User = {
name = ""
}
适用于我的用例
答案 22 :(得分:0)
此处显示的页面跳转示例,希望对您有所帮助!
let vc:UIViewController = (NSClassFromString("SwiftAutoCellHeight."+type) as! UIViewController.Type).init()
self.navigationController?.pushViewController(vc, animated: true)
// Click the Table response
tableView.deselectRow(at: indexPath, animated: true)
let sectionModel = models[(indexPath as NSIndexPath).section]
var className = sectionModel.rowsTargetControlerNames[(indexPath as NSIndexPath).row]
className = "GTMRefreshDemo.\(className)"
if let cls = NSClassFromString(className) as? UIViewController.Type {
let dvc = cls.init()
self.navigationController?.pushViewController(dvc, animated: true)
}
答案 23 :(得分:0)
<强> Swift3 + 强>
extension String {
var `class`: AnyClass? {
guard
let dict = Bundle.main.infoDictionary,
var appName = dict["CFBundleName"] as? String
else { return nil }
appName.replacingOccurrences(of: " ", with: "_")
let className = appName + "." + self
return NSClassFromString(className)
}
}
答案 24 :(得分:-6)
这是一个很好的例子:
class EPRocks {
@require init() { }
}
class EPAwesome : EPRocks {
func awesome() -> String { return "Yes"; }
}
var epawesome = EPAwesome.self();
print(epawesome.awesome);