Swift
UIViewController
super.init()
iOS Development
Programming

Why can't I call the default super.init on UIViewController in Swift?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When you subclass UIViewController, a plain zero-argument super.init() is not the initializer UIKit wants you to call. UIViewController has designated initialization paths built around init(nibName:bundle:) and required init?(coder:), and Swift enforces those rules through its initializer system.

Why super.init() is not the right call

Swift classes follow designated-initializer chaining. A subclass must ultimately call one of its superclass's designated initializers.

For UIViewController, the important initializer paths are:

  • 'init(nibName:bundle:) for programmatic or nib-based creation'
  • 'init?(coder:) for storyboard and archive decoding'

That is why a custom programmatic initializer usually ends like this:

swift
1import UIKit
2
3final class ProfileViewController: UIViewController {
4    private let userID: String
5
6    init(userID: String) {
7        self.userID = userID
8        super.init(nibName: nil, bundle: nil)
9    }
10
11    required init?(coder: NSCoder) {
12        fatalError("init(coder:) has not been implemented")
13    }
14}

The subclass initializes its own stored properties first and then calls the correct designated initializer on UIViewController.

What if the controller comes from a storyboard

If the view controller is created from a storyboard, UIKit initializes it through init?(coder:). In that path, you do not get to replace the initialization flow with a custom plain initializer.

A storyboard-based controller therefore often looks like this:

swift
1import UIKit
2
3final class SettingsViewController: UIViewController {
4    required init?(coder: NSCoder) {
5        super.init(coder: coder)
6    }
7}

If you need dependency injection with storyboards, you usually inject after instantiation or use newer storyboard creator APIs rather than inventing an unsupported super.init() path.

Why UIKit is designed this way

UIViewController is tied to view loading, nibs, storyboards, state restoration, and internal UIKit lifecycle behavior. UIKit needs specific initialization entry points so it can set up that machinery correctly.

A generic zero-argument superclass initializer would not express whether the controller comes from a nib, from a storyboard archive, or from a fully programmatic configuration.

So the restriction is not arbitrary. It reflects how UIKit constructs controller objects safely.

Initialization is not where view setup belongs

Another source of confusion is trying to use init for work that really belongs in loadView or viewDidLoad. Initializers should establish dependencies and basic state, while view hierarchy setup usually happens later in the controller lifecycle.

That separation is one more reason UIKit keeps controller initialization narrow and explicit.

Another programmatic pattern

Some developers try to create a convenience initializer that still funnels through the proper designated initializer. That is valid as long as the chain eventually reaches init(nibName:bundle:).

swift
1final class HelpViewController: UIViewController {
2    convenience init() {
3        self.init(topic: "general")
4    }
5
6    init(topic: String) {
7        super.init(nibName: nil, bundle: nil)
8        print(topic)
9    }
10
11    required init?(coder: NSCoder) {
12        fatalError("init(coder:) has not been implemented")
13    }
14}

The important point is that even this style does not call a bare super.init(). It still goes through the initializer UIKit expects.

Common Pitfalls

A common mistake is assuming every superclass has a meaningful plain init() available to subclasses. Swift only lets you call initializers that actually exist and are valid for the type.

Another issue is mixing storyboard creation with a custom required dependency initializer without planning how that dependency will be provided.

It is also easy to forget that subclass properties must be initialized before calling the superclass designated initializer. Swift's two-phase initialization rules are strict here.

Summary

  • 'UIViewController does not expose a plain superclass initialization path that replaces init(nibName:bundle:) or init?(coder:).'
  • Programmatic view controllers usually call super.init(nibName:nil, bundle:nil).
  • Storyboard-created view controllers are initialized through super.init(coder:).
  • The initializer you call depends on how the controller is created.
  • Swift enforces this to preserve UIKit's required initialization lifecycle.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.