GoldenJoe
GoldenJoe

Reputation: 8012

Is there a way to initialize a class in swift by using a variable which contains the name of the class?

Suppose I have a simple factory which returns various subclasses of a custom ModelObject class like:

class func testModelObject(className: String) -> ModelObject
{
   let obj = // instance of the subclass of ModelObject specified by className
   return obj
}

Is there a way to do this? Will Swift freak out when I try to call any methods of that object? Should I have something else for my return type?

Upvotes: 1

Views: 852

Answers (1)

kennytm
kennytm

Reputation: 523764

For best type safety, you should let testModalObject to accept a meta-type like:

class ModelObject {
    required init() {}
}

class Subclass: ModelObject {
    required init() { super.init() }
}

func testModalObject(_ type: ModelObject.Type) -> ModelObject {
    return type.init()
}

testModalObject(Subclass.self)

If you really need a string input, you will need to rely on the Objective-C runtime and do some casting (see how to create instance of a class from a string in swift 3):

@objc
class ModelObject: NSObject {     // <---
    required override init() {}
}

@objc(MOSubclass)    // <-- tell ObjC the name is "MOSubclass" instead of "????.Subclass".
class Subclass: ModelObject {
    required init() { super.init() }
}

func testModalObject(_ typeName: String) -> ModelObject? {
    let cls = NSClassFromString("MO\(typeName)") as? ModelObject.Type
    return cls?.init()
}

testModalObject("Subclass")!

Upvotes: 3

Related Questions