如何在swift 3

时间:2016-11-02 05:27:15

标签: swift swift3

我尝试过多次使用字符串创建一个类的实例,但没有一个在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中使用字符串创建类的实例?

5 个答案:

答案 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