user714223
user714223

Reputation: 31

Loading a instance of a class dynamically in swift

I would like to init an instance of a class specified at runtime. I have the following set up.

//MyClass1 & MyClass2 inherit from UIViewController
let arr = MyClass1.self,MyClass2.self] 

func didSelectRow(index:Int) {
    var controllerRef = arr[index] //This returns a .Type
    var controllerClass = controllerRef() //This returns “the class” MyClass1
    //This is where I'm stuck. How do I initialize controller??

    //Finally, push VC
    self.navigationController?.pushViewController(controller, animated: true)
}

To initialize the VC with Objective C, I was able to do this as follows:

UIViewController *controller = [((UIViewController *)[controllerClass alloc]) initWithNibName:class1Nib bundle:nil];

With Swift, I’m expecting something like the syntax below, but it doesn’t work

//Doesn’t work
var controller = (controllerClass as UIViewController)(nibName: class1Nib, bundle:nil) 

//Overriding the init method in MyClass1 and then calling the below doesn’t work
var controller = controllerClass(nibName: class1Nib, bundle:nil)

//The below works, but viewDidLoad() does not get called. It only loads the nib file

var controller = UIViewController(nibName: Class1Nib, bundle:nil)

Any help is appreciated. Thanks

Upvotes: 2

Views: 2027

Answers (1)

matt
matt

Reputation: 535247

Your question, with its repeated and meaningless "doesn't work" and "the below", is confused and confusing, so I will respond by assuming that what you want to do is instantiate and push a view controller given its class, and I will simply demonstrate in a few lines of code that this is possible.

Here is a function that returns a UIViewController subclass:

func provideVCClass() -> UIViewController.Type {
    return ViewController.self
}

And here are lines from a button's action handler where we call that function and use the class to instantiate that view controller and push it onto the current navigation controller:

let vcclass = provideVCClass()
let vc = vcclass(nibName: "View", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)

I assure you that this does work: the correct view controller subclass is instantiated, its nib is loaded, and its view does appear in the interface.

So all I can say in answer to your question, which I don't fully understand, is Go Ye And Do Likewise.

EDIT Here's a little postscript. If your code actually says:

let arr = [MyClass1.self, MyClass2.self]

I would suggest you try saying

let arr : [UIViewController] = [MyClass1.self, MyClass2.self]

...just in case Swift is not inferring the correct type here.

Upvotes: 3

Related Questions