How to create an instance of a class from a String in Swift

前端 未结 4 1339
终归单人心
终归单人心 2020-12-08 19:47

I have tried creating an instance of a class using a string in numerous ways with none of them working in Swift 3.

Below are pre-Swift 3 sol

相关标签:
4条回答
  • 2020-12-08 20:04

    If you project contains space you should replace space with '_'

    Something like this

    let namespace = (Bundle.main.infoDictionary!["CFBundleExecutable"] as! String).replacingOccurrences(of: " ", with: "_")
    let cls = NSClassFromString("\(namespace).\(className)")! as! AnyClass
    
    0 讨论(0)
  • 2020-12-08 20:08

    Apple provides a way to achieve this without having to use NSClassFromString.

    Bundle.main.classNamed("MyClassName")

    https://developer.apple.com/documentation/foundation/bundle/1407299-classnamed

    0 讨论(0)
  • 2020-12-08 20:08

    Typed Extension

    You can have a typed class from a string like:

    let loadedClass = try! Bundle.main.class(ofType: MyClass.self)
    

    using this simple extension:

    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)
        }
    }
    

    Of course you can try catch the error ;)

    0 讨论(0)
  • 2020-12-08 20:13

    You can try this:

    func classFromString(_ 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
    }
    

    use the func like this:

    class customClass: UITableView {}   
    
    let myclass = classFromString("customClass") as! UITableView.Type
    let instance = myclass.init()
    
    0 讨论(0)
提交回复
热议问题