类中的字符串
let classString = NSStringFromClass(TestViewController.self)
或者
let classString = NSStringFromClass(TestViewController.classForCoder())
从字符串初始化一个UIViewController类:
let vcClass = NSClassFromString(classString) as! UIViewController.Type
let viewController = vcClass.init()
//
// 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()
}
// Given the app/framework/module named 'MyApp'
let className = String(reflecting: MyClass.self)
// className = "MyApp.MyClass"
protocol Init {
init()
}
var type = NSClassFromString(className) as? Init.Type
let obj = type!.init()
当然,从NSClassFromString
返回的类型必须实现此初始化协议。
我希望你清楚,className
是一个包含类的Obj-C运行时名称的字符串,默认情况下不仅仅是"Foo",但我认为这不是你问题的主要话题。
你需要这个协议,因为默认情况下所有的Swift类都没有实现init
方法。
看起来正确的咒语应该是...
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的初始化分解为单独的闭包,这样可以成功编译。
显然,在Swift中,如果类的名称只在运行时才知道,则不可能(再次)实例化对象。对于NSObject的子类,可以使用Objective-C包装器。
至少,在不需要Objective-C包装器的情况下,可以使用给定的运行时另一个对象的相同类实例化对象(使用xCode版本6.2-6C107a):
class Test : NSObject {}
var test1 = Test()
var test2 = test1.dynamicType.alloc()
我认为目前的beta版本(2)不支持,至少目前是不行的。希望未来版本能够改进。
您可以使用NSClassFromString
来获取AnyClass
类型的变量,但似乎没有办法在Swift中实例化它。您可以使用Objective-C桥接并在那里进行操作,或者--如果在您的情况下起作用--回退到使用switch语句。
我使用不同的目标,但在这种情况下找不到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);
}
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 = ""
}
if let ImplementationClass: NSObject.Type = NSClassFromString(className) as? NSObject.Type{
ImplementationClass.init()
}