If you're using a UIStoryboard, will UIViewController call awakeFromNib? - ios

simple question,
If you're using a UIStoryboard, will UIViewController call awakeFromNib?
If not, what is the alternative method being called that we should use?
Cheers!

Yes, awakeFromNib will be called when using a UIStoryboard.
While a .storyboard file is a XML document, it will get converted to a set of traditional .nib files when you compile/package your app, so decoding those will be the same as in xib-based projects.

Yes, awakeFromNib is being called.
According to the documentation:
Initializing a View Controller Loaded from a Storyboard When you
create a view controller in a storyboard, the attributes you configure
in Interface Builder are stored in an archive. Later, when the view
controller is instantiated, this archive is loaded into memory and
processed. The result is a set of objects whose attributes match those
you set in Interface Builder. Here’s how that archive is loaded:
If your view controller implements an initWithCoder: method, that
method is called to process the information in the archive. If your
view controller does not implement an initWithCoder: method, your view
controller’s init method is called instead.
After the objects in the archive are loaded, iOS calls the awakeFromNib method on any objects
that implement such a method. You use this method to perform any
configuration steps that require other objects to already be
instantiated.

Yes awakeFromNib will be called when using a UIStoryboard.

Related

When to use viewDidLoad and when to use awakeFromNib

I've gotten pretty comfortable using the viewDidLoad method to execute things I want done at the beginning of a view, but reading one of Apple's tutorials they set the data controller for the class in the awakeFromNib method and did nothing in the awakeFromNib. I swapped it and it seemingly worked identically in my app, but I'm not sure if it was better to have it in awakeFromNib or viewDidLoad.
When should I use either one?
awakeFromNib is called when the associated nib file with a class is loaded . Any class that can own a nib can use it. viewDidLoad is used only by view controllers. It is usually called when loading from nib as well but it can also be called by a view created in memory (very rare circumstance.). If you are using controllers, then I would suggest you to use viewDidLoad
For more Refer this Answer
viewDidLoad is associated with the view controller. If you need to initialize another control unarchived from the nib (e.g. UITableViewCell prototype) you cannot overload viewDidLoad, you need to overload awakeFromNib.

How does a segue create the destination ViewController?

As the question suggests: how does a segue create the destination controller? To be specific, which method gets called? I want to init another ViewController from a nib when a segue creates him. How do I accomplish that?
Thanks a lot
Short answer: initWithCoder: is called.
Longer answer (from apple's docs on UIViewController):
If your app uses a storyboard to define a view controller and its
associated views, your app never initializes objects of that class
directly. Instead, view controllers are either instantiated by the
storyboard—either automatically by iOS when a segue is triggered or
programmatically when your app calls the storyboard object’s
instantiateViewControllerWithIdentifier: method. When instantiating a
view controller from a storyboard, iOS initializes the new view
controller by calling its initWithCoder: method instead. iOS
automatically sets the nibName property to a nib file stored inside
the storyboard.

On iPad, the initWithFrame of a new class based on UIView is not called?

For a single view app, a DrawView class is added, which is a subclass of the UIView class.
It is used as the main view for the app, so the drawRect method of this class works well, can draw things, for example, but the code generated by Xcode has a line "// Initialization code" to indicate putting init code right there, inside of initWithFrame, but I put some code in there and it is not called, and a break point is set there but it never stops there? I then added an init using the usual method and it is not called either?
Try overriding -(id)initWithCoder:(NSCoder*)coder. I believe when a view is loaded from a nib it uses this init method. See this question.
initWithCoder: -It is recommended that you Implement this method if you load your view from an Interface Builder nib file and your view requires custom initialization.The nib-loading code does not use the initWithFrame: method to instantiate new view objects. Instead, it uses the initWithCoder: method that is part of the NSCoding protocol.The nib-loading code does not use the initWithFrame: method to instantiate new view objects. Instead, it uses the initWithCoder: method that is part of the NSCoding protocol.apple's doc
initWithFrame: - The default initialization method for views,The new view object must be inserted into the view hierarchy of a window before it can be used. If you create a view object programmatically, this method is the designated initializer for the UIView class.
some more information here for :overriding methods
happy to help:)

Is it ok to call [super loadView]?

I thought that I should never call [super loadView] but something is confusing me.
In description of loadView (UIViewController Class Reference) it is said that "Your custom implementation of this method should not call super.",
but in ZoomingPDFViewer example that they gave, loadView implementation (ZoomingPDFViewerViewController) is calling [super loadView].
I have tried to call it from my loadView method and it works ok, but I just don't understand then what does it mean to not call super.
You definitely should not be calling [super loadView]. I'd say you found a bug in the ZoomingPDFViewer example.
You override loadView when you want to programatically create the view hierarchy for your view controller (not using a xib).
As you pointed out, the docs clearly state that you should not call super.
Your custom implementation of this method should not call super.
I assume this is to avoid loading both from a xib and programatically creating a view as this method is used by the base to load a view from a xib:
If the view controller has an associated nib file, this method loads
the view from the nib file.
Note also that even if during allocation of your UIViewController object you pass nil for the nibNameOrNil parameter that the UIViewController implementation of loadView will try to load any xib with the associated class name in it.
A view controller has an associated nib file if the nibName property
returns a non-nil value, which occurs if the view controller was
instantiated from a storyboard, if you explicitly assigned it a nib
file using the initWithNibName:bundle: method, or if iOS finds a nib
file in the app bundle with a name based on the view controller’s
class name. If the view controller does not have an associated nib
file, this method creates a plain UIView object instead.
The real intent of this method is to give you full control of building the view hierarchy without relying on the built in xib loading mechanism.:
You can override this method in order to create your views manually.
Personally, I override loadView if: 1.) The xib I would make for it is really trivial or 2.) The layout of the control is very dynamic, so creating a xib with a static layout has little benefit.
NSViewController tries to initialize a view from a nib in -loadView. Since your nib name is not set for your controller, it will just give you a self.view = nil; I would assume UIViewController works the same way.
So it should be safe, but you it's completely unnecessary.
If you dont have a view created in your IB, then you should call [super loadView] in your code to give a view to your program.
In case of your custom views, you are suppose to create a view with the interfaz builder, so you dont need to call it.
If you create your ViewController programmatically, you could call super.loadView() instead of self.view = UIView(frame: UIScreen.main.bounds) at the beginning of override func loadView().
However, do NOT call self.view before super.loadView(), since the former will trigger the latter if view did not been loaded.
I don't think it's a good idea to explain Apple's documentation like a robot.

Should [super loadView] be called from loadView or not?

In Programming iOS 4 by Matt Newburg he states:
“To provide a UIViewController with a view manually, implement its
loadView method… You must NOT call super”.
In the iOS 5 Developer's Cookbook by Erica Sadun she states:
“The loadView method allows you to set up the screen and layout any
subviews… Make sure to call [super loadView] whenever you inherit
from a specialized subclass such as UITableViewController or
UITabBarController.”
This, to me at least, is confusing.
Apple is the source of truth and they say NO super call.
If you override this method in order to create your views manually,
you should do so and assign the root view of your hierarchy to the
view property. (The views you create should be unique instances and
should not be shared with any other view controller object.) Your
custom implementation of this method should not call super.
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview
[edit]
Another important note scattered around in the UIViewController class reference:
The default loadView method attempts to load the view from the nib
file associated with the view controller (if any).
This is a very old question, but I find that it needs a better answer than the one it got.
Should [super loadView] be called from loadView or not?
It depends. The two sources you cite are talking about different situations, and they're both correct in the context they're describing.
The quote from Neuberg is talking about view controllers that inherit directly from UIViewController. That class has its own implementation of loadView that provides default behavior; specifically, it automatically loads the view hierarchy from a .xib (or storyboard) file that's associated with the view controller. If you call UIViewController's version of that method, the view hierarchy created in that method will either replace your own implementation's view hierarchy, or vice versa. Nine years after this question was posed, the documentation for UIViewController's -loadView method still warns against that:
You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the view property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not call super. [emphasis added]
The quote from Sadun is talking about a different situation, i.e. one in which your view controller is not a direct subclass of UIViewController, but is instead derived from UITableViewController, UITabBarController, etc. Those classes override -loadView themselves and need their versions called. At least in the case of UITableViewController, this is called out in the Overview section:
You may override loadView or any other superclass method, but if you do, be sure to invoke the superclass implementation of the method, usually as the first method call.
So, if you're subclassing UIViewController and providing your own -loadView implementation to generate the controller's views rather than using a .xib or storyboard to provide the views, don't call the superclass's -loadView method. On the other hand, if you're subclassing a class such as UITableView and doing the same thing, check the docs to see whether you need to call that class's -loadView method from your own override.

Resources