How do I make a custom initializer for a UIViewController subclass in Swift? How do I make a custom initializer for a UIViewController subclass in Swift? swift swift

How do I make a custom initializer for a UIViewController subclass in Swift?


class ViewController: UIViewController {            var imageURL: NSURL?        // this is a convenient way to create this view controller without a imageURL    convenience init() {        self.init(imageURL: nil)    }        init(imageURL: NSURL?) {        self.imageURL = imageURL        super.init(nibName: nil, bundle: nil)    }        // if this view controller is loaded from a storyboard, imageURL will be nil        required init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder)    }}


For those who write UI in code

class Your_ViewController : UIViewController {    let your_property : String    init(your_property: String) {        self.your_property = your_property        super.init(nibName: nil, bundle: nil)    }    override func viewDidLoad() {        super.viewDidLoad()    }    required init?(coder: NSCoder) {        fatalError("init(coder:) is not supported")    }}


This is very similar to the other answers, but with some explanation. The accepted answer is misleading because its property is optional and doesn't expose the fact that your init?(coder: NSCoder) MUST initialize each and every property and the only solution to that is having a fatalError(). Ultimately you could get away by making your properties optionals, but that doesn't truly answer the OP’s question.

// Think more of a OnlyNibOrProgrammatic_NOTStoryboardViewControllerclass ViewController: UIViewController {    let name: String    override func viewDidLoad() {        super.viewDidLoad()    }    // I don't have a nib. It's all through my code.    init(name: String) {        self.name = name        super.init(nibName: nil, bundle: nil)    }    // I have a nib. I'd like to use my nib and also initialze the `name` property    init(name: String, nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle? ) {        self.name = name        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)    }    // when you do storyboard.instantiateViewController(withIdentifier: "ViewController")    // The SYSTEM will never call this!    // it wants to call the required initializer!    init?(name: String, coder aDecoder: NSCoder) {        self.name = "name"        super.init(coder: aDecoder)    }    // when you do storyboard.instantiateViewController(withIdentifier: "ViewController")    // The SYSTEM WILL call this!    // because this is its required initializer!    // but what are you going to do for your `name` property?!    // are you just going to do `self.name = "default Name" just to make it compile?!    // Since you can't do anything then it's just best to leave it as `fatalError()`    required init?(coder aDecoder: NSCoder) {        fatalError("I WILL NEVER instantiate through storyboard! It's impossible to initialize super.init?(coder aDecoder: NSCoder) with any other parameter")    }}

You basically have to ABANDON loading it from storyboard. Why?

Because when you call a viewController storyboard.instantiateViewController(withIdentifier: "viewController") then UIKit will do its thing and call

required init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder)}

You can never redirect that call to another init method.

Docs on instantiateViewController(withIdentifier:):

Use this method to create a view controller object to present programmatically. Each time you call this method, it creates a new instance of the view controller using the init(coder:) method.

Yet for programmatically created viewController or nib created viewControllers you can redirect that call as shown above.