Question or problem with Swift language programming:
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?
How to solve the problem:
Solution 1:
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.
Solution 2:
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.
Solution 3:
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!
Solution 4:
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
Solution 5:
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
.