Search code examples
iosswiftswift5ipados

Why the call to super is the last thing on this method and not the first thing?


I am learning Swift as I go.

I found functions like this viewDidLoad() and many others are sometimes written like this:

override func viewDidLoad() {
  super.viewDidLoad()
  // Do any additional setup after loading the view, typically from a nib.
}

and sometimes written like this:

override func viewDidLoad() {
  // Do any additional setup after loading the view, typically from a nib.
  super.viewDidLoad()
}

I mean with the call to super.viewDidLoad() as the first thing or as the last thing inside the function?

What difference it makes to the program itself?


Solution

  • First off, the docs don't say that you need to call super. Contrast that to e.g. viewWillAppear(_:), whose docs state:

    If you override this method, you must call super at some point in your implementation.

    Thus, calling super is only needed if you have a custom subclass of UIViewController, let's call it BaseViewController, which does something in viewDidLoad().

    When you then inherit from BaseViewController, you probably need to call super to do the work of BaseViewController. Depending on the nature of it, you'd need to do it at the beginning, somewhere in the middle, or at the end of your subclass's viewDidLoad(). This is up to this BaseViewController to document it properly.

    Here's a contrived example:

    class ColorfulViewController: UIViewController {
        /// Defines background color of view. Override in subclass.
        var shinyColor: UIColor = .red
    
        /// Sets the background color. Make sure to call `super` in subclass.
        func viewDidLoad() {
            backgroundColor = shinyColor
        }
    }
    
    class PinkViewController: ColorfulViewController {
        override var shinyColor: UIColor = .systemPink
    
        func viewDidLoad() {
            super.viewDidLoad() // This one doesn't matter where it goes.
            // Additional work.
        }
    }
    

    Another contrived example where you'd want to call super at the end:

    class CountingViewController: UIViewController {
        var count: Int = 0
    
        /// Counts the subviews. When subclassing, make sure to call `super` *after*
        /// view is fully configured.
        func viewDidLoad() {
            count = view.subviews.count
        }
    }
    
    class FooViewController: CountingViewController {
        override var shinyColor: UIColor = .systemPink
    
        func viewDidLoad() {
            // Additional work.
            super.viewDidLoad()
        }
    }