69

Everyone tells me "Use super.viewDidLoad() because it's just like that" or "I've been doing it always like that, so keep it", "It's wrong if you don't call super", etc.

override func viewDidLoad() {
    super.viewDidLoad()
    // other stuff goes here
}

I've only found a few topics about Objective-C cases and they were not so enlightening, but I'm developing in Swift 3, so can any expert give me a good detailed explanation on this?

Is it a case of just good practice or are there any hidden effects?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Andr3s4n
  • 750
  • 1
  • 7
  • 9
  • 2
    https://upload.wikimedia.org/wikipedia/commons/a/a2/Method_overriding_in_subclass.png If you need dog which moves not like animal you can do not call parent class. – Nikolay Krasnov Oct 20 '16 at 10:32
  • I understand the concept of overriding and inheritance. What I need to know is in this particular case, if there are any benefits of calling super? Would the code work anyway? – Andr3s4n Oct 20 '16 at 10:41
  • 1
    Note that your question is *independent of the language,* it is a question about the correct usage of the UIKit framework. Therefore older Q&As written for Objective-C (such as http://stackoverflow.com/questions/824695/do-i-always-have-to-call-super-viewdidload-in-the-viewdidload-method) are still valid for a Swift program. – Martin R Oct 20 '16 at 10:50
  • 1
    Appears to be a convention. Based on iOS documentation and some discussions on the Internet, it would appear that viewDidLoad is called after view is loaded into memory and it's purpose is to allow for some custom setup of views loaded from nib files (basically a quote from docs). Apple documentation does not mention that you should call super.viewDidLoad (which it does when that is deemed necessary), which leads me to assume that the default implementation does nothing. The could be some wisdom in calling super in case there is something important there in extended classes. – Baglan Oct 20 '16 at 10:56
  • @MartinR I did read that discussion, but what is the final answer over there? That we should call the super because Apple might decide to change it some day? Are there no other real reasons? – Andr3s4n Oct 20 '16 at 13:28
  • I have also same question. I read few ans but did not get exact ans, – Dnyaneshwar Wakchaure Apr 18 '17 at 05:39

6 Answers6

60

Usually it's a good idea to call super for all functions you override that don't have a return value.

You don't know the implementation of viewDidLoad. UIViewController could be doing some important setup stuff there and not calling it would not give it the chance to run it's own viewDidLoad code.

Same thing goes when inheriting from a UIViewController subclass.

Even if calling super.viewDidLoad doesn't do anything, always calling it is a good habit to get into. If you get into the habit of not calling it, you might forget to call it when it's needed. For example when subclassing a ViewController that depends on it from a 3rd party framework or from your own code base.

Take this contrived example:

class PrintingViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print("view has loaded")
    }
}

class UserViewController: PrintingViewController {
    override func viewDidLoad() {
    super.viewDidLoad()

     // do view setup here
    }

}

Not calling viewDidLoad here would never give PrintingViewController a chance to run its own viewDidLoad code

If you don't want to do anything in viewDidLoad just don't implement it. The super method will be called anyway.

tsp
  • 1,938
  • 18
  • 15
  • 4
    Your explanation made it a bit more clear in a generic way (thank you for that!). But I would like to go deeper then that in this case for the UIViewController. Doing it so that I don't forget to do it more times sounds like a tradition: someone started it long time ago and now no one know exactly why we keep doing it, but we still do it. Check the viewDidLoad on the standard UIVIewController...it's empty. Now, why are we calling an empty super method? Or am I making a wrong assumption here? Will my app (any) behave wrongly if I decide to implement my custom viewDidLoad and not call super? – Andr3s4n Oct 20 '16 at 13:24
  • 1
    I think it's unlikely that apple will change the implementation of viewDidLoad causing apps that don't call super to break in subtle ways. You assume that viewDidLoad has an empty implementation in UIViewController but how can you be sure? – tsp Oct 20 '16 at 13:36
  • 9
    Also, let's say you have some view controller that inherits from UIViewController and doesn't call super for viewDidLoad. A couple of months later you decide you want it to inherit from some different ViewController that does some stuff in viewDidLoad. Your code will break in mysterious ways. We don't call super so we don't forget to call it when needed, we call it to protect our code in case of change. – tsp Oct 20 '16 at 13:39
  • 3
    Check the documentation when unsure. For example, you're not supposed to call super in loadView(): https://developer.apple.com/reference/uikit/uiviewcontroller/1621454-loadview . In general the expectation is that the developer will call super unless told not to, not the other way around, so that's the right mindset to get into. – Aurast Oct 20 '16 at 17:56
35

I have a secret, when I worked at Apple I read the source code for UIKit, partly to answer questions I had like this, viewDidLoad is empty in all the UI*ViewController classes.

Naturally I am not there anymore, they may have changed this.

mxcl
  • 26,392
  • 12
  • 99
  • 98
11

I think calling super.viewDidLoad() is, first of all, a good practice.

The usual thing in iOS is to do all of your subclass setups after the superclass has completed the setup that it needs to do (initializing properties, laying things out, etc.). If you don't give the superclass a chance to handle all of its setups before you start changing things around, it's possible you'll encounter some strange bugs and behavior.

We can draw a parallel with Class Initialization: "A designated initializer must delegate up to a superclass initializer before assigning a value to an inherited property." We're doing this to be sure that all superclass properties have a value and based on that fact we could safely use them through inheritance in our subclass.

Rule of thumb:

  • When initializing/setting up, run the superclass' implementations first.
  • When tearing down/cleaning up, run the superclass' implementation last.

Assuming that viewDidLoad() is some sort of initialization we should call super.viewDidLoad() first to correctly set things up in the superclass.

If we check the implementation of viewDidLoad() in UIViewController base class, we can see that it's empty. So maybe the only one reason to calling super.viewDidLoad() from you child class is a good coding style :-) Lets follow it!

Vitya Shurapov
  • 2,200
  • 2
  • 27
  • 32
7

That depends on the implementation of viewDidLoad in the class UIViewController (from which all view controllers inherit). If it's empty than calling super.viewDidLoad() won't do much. However if it has some functionality regarding the view controller then you certainly would want to use it.

Since it's not in your hands regarding the implementation of a UIViewController you should always call this method

giorashc
  • 13,691
  • 3
  • 35
  • 71
3

When inheriting directly from UIViewController, call super when its documentation tells you to.

For example, viewWillAppear(Bool) says, "If you override this method, you must call super at some point in your implementation," whereas viewDidLoad() does not.

If you are not inheriting directly from UIViewController and the class you are inheriting from does not have reliable documentation, or may silently introduce a breaking change requiring that super be called, then always call super.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
0

if your class is been inherited from UIViewController directly then there is no need to invoke super.viewDidLoad. This definately make your code look bit consice but usually iOS community suggest to call it anyway.

if your class is been inherited from custom UIViewController which indeed has some functionality which your class can leverage then invoke super.viewDidLoad.

Chetan A
  • 73
  • 8