我尝试过多次使用字符串创建一个类的实例,但没有一个在Swift 3 中工作。
以下是我尝试过的无法正常使用的Swift 3解决方案
- 将课程设为目标-c课程
@objc(customClass)
class customClass {
...
}
//Error here: cannot convert value of type 'AnyClass?' to expected argument type 'customClass'
let c: customClass = NSClassFromString("customClass")
- 使用NSString值指定类(使用和不使用@objc属性)
@objc(customClass)
class customClass {
...
}
//Error here: cannot convert value of type 'String' to expected argument type 'AnyClass' (aka 'AnyObject.Type')
var className = NSStringFromClass("customClass")
let c: customClass = NSClassFromString(className)
我没有做对,但没有在网上找到任何解决方案。
如何在Swift 3中使用字符串创建类的实例?
答案 0 :(得分:23)
你可以试试这个:
func stringClassFromString(_ className: String) -> AnyClass! {
/// get namespace
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String;
/// get 'anyClass' with classname and namespace
let cls: AnyClass = NSClassFromString("\(namespace).\(className)")!;
// return AnyClass!
return cls;
}
像这样使用func:
class customClass: UITableView {
}
let myclass = stringClassFromString("customClass") as! UITableView.Type
let instance = myclass.init()
答案 1 :(得分:4)
如果您的项目包含空间,则应将空间替换为'_'
类似这样的东西
let namespace = (Bundle.main.infoDictionary!["CFBundleExecutable"] as! String).replacingOccurrences(of: " ", with: "_")
let cls = NSClassFromString("\(namespace).\(className)")! as! AnyClass
答案 2 :(得分:2)
Apple提供了一种无需使用NSClassFromString
即可实现这一目标的方法。
Bundle.main.classNamed("MyClassName")
https://developer.apple.com/documentation/foundation/bundle/1407299-classnamed
答案 3 :(得分:1)
您可以从类似以下的字符串中输入类型的类:
let loadedClass = try! Bundle.main.class(ofType: MyClass.self)
使用此简单扩展名:
extension Bundle {
func `class`<T: AnyObject>(ofType type: T.Type, named name: String? = nil) throws -> T.Type {
let name = name ?? String(reflecting: type.self)
guard name.components(separatedBy: ".").count > 1 else { throw ClassLoadError.moduleNotFound }
guard let loadedClass = Bundle.main.classNamed(name) else { throw ClassLoadError.classNotFound }
guard let castedClass = loadedClass as? T.Type else { throw ClassLoadError.invalidClassType(loaded: name, expected: String(describing: type)) }
return castedClass
}
}
extension Bundle {
enum ClassLoadError: Error {
case moduleNotFound
case classNotFound
case invalidClassType(loaded: String, expected: String)
}
}
您当然可以try
catch
error
;)
答案 4 :(得分:0)
我在这里添加了我的类别来转换类: https://stackoverflow.com/a/45112622/182551