Swift: Custom ViewController initializers
IosObjective CSwiftUiviewcontrollerInitializationIos Problem Overview
How do you add custom initializers to UIViewController
subclasses in Swift?
I've created a sub class of UIViewController
that looks something like this:
class MyViewController : UIViewController
{
init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
self.leftVC = leftVC;
self.rightVC = rightVC;
self.gap = gap;
super.init();
setupScrollView();
setupViewControllers();
}
}
When I run it I get a fatal error:
> fatal error: use of unimplemented initializer 'init(nibName:bundle:)' for class 'MyApp.MyViewController'
I've read elewhere that when adding a custom initializer one has to also override init(coder aDecoder:NSCoder)
so let's override that init
and see what happens:
override init(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder);
}
If I add this, Xcode complains that self.leftVC is not initialized at super.init call
. So I guess that can't be the solution either. So I wonder how can I add custom initializers properly to a ViewController
subclass in Swift (since in Objective-C this seems not to be a problem)?
Ios Solutions
Solution 1 - Ios
Solved it! One has to call the designated initializer which in this case is the init with nibName, obviously ...
init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
self.leftVC = leftVC
self.rightVC = rightVC
self.gap = gap
super.init(nibName: nil, bundle: nil)
setupScrollView()
setupViewControllers()
}
Solution 2 - Ios
For a more generic UIViewController you can use this as of Swift 2.0
init() {
super.init(nibName: nil, bundle: nil)
}
Solution 3 - Ios
Swift 5
If you want to write custom initializer to UIViewController
which is initialized with storyBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")
You can write custom initializer for only Optional
properties.
class MyFooClass: UIViewController {
var foo: Foo?
init(with foo: Foo) {
self.foo = foo
super.init(nibName: nil, bundle: nil)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.foo = nil
}
}
Solution 4 - Ios
Not sure if you managed to fully solve this... but depending on how you want your class's interface to look and whether or not you actually need the coder functionality, you can also use the below:
convenience required init(coder aDecoder: NSCoder)
{
//set some defaults for leftVC, rightVC, and gap
self.init(leftVC, rightVC, gap)
}
Since init:leftVC:rightVC:gap
is a designated initializer, you can fulfill the requirement of implementing init:coder
by making it a convenience initializer that calls your designated initializer.
This could be better than
override init(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder);
}
because if you need to initialize some properties, then you would need to rewrite them.