Initialization process of a view loaded from a storyboard
This post is continuation of the “UIViewController’s view loading process demystified” post I’ve wrote some time ago. I’d like to cover how custom view is loaded when it is placed in a storyboard.
There are several ways to add view to a view controller. You can put it in storyboard or you can create it in code and add as subview of view controller’s view.
I sat down and spent some time on debugging, trying to maybe find something useful and to learn about entire process of creating and presenting view. And here are my findings.
View without subviews loaded from a storyboard
Let’s say there is a storyboard which has one view controller, and in the view
controller there is a view which is of some subclass of UIControl
, and has
some constraints set, and has few IBInspectable
properties defined so the
properties will be loaded and set after our view is loaded.
Here is how the flow look like:
I thought here will be some magic but didn’t find any. There are two or three private methods called between public ones but do nothing special.
At first initWithCoder:
is called and next is setNeedsDisplay
.
All constraints of this view are set by calling addConstraints:
. Here are set
constraints that not determine position of a view in its superview. So, only like
height and width. I thought that all constraints are set here but makes more
sense that not all are set in here, because position of this view is important
for its superview. When view has subviews, constraints that define position of
subviews will be added to the view that contains these subviews.
Next called method is awakeAfterUsingCoder:
and view is prepared to be added
to superview because willMoveToSuperview:
method is called and the next one
is didMoveToSuperview
.
After view is added to superview awakeFromNib
is called. I thought that awakeFromNib
is called right after awakeAfterUsingCoder
even before adding view to its superview,
but was wrong. awakeFromNib
is important method. This is a moment when you’ve
got your IBInspectable
properties and key-value pairs defined in a storyboard
set and ready to use. Those loaded values are available before super awakeFromNib
is called. awakeFromNib
is called by UINib
’s instantiateWithOwner:options:
method, so it loads the view, decodes and set properties and those are ready to be used.
Next willMoveToWindow
and didMoveToWindow
methods are called. I was a bit
confused why those are called (because view is added to its superview, not to a window directly)
but read documentation which says that default implementation of these
methods do nothing and this is useful if you want to do additional things
when view moves to another window.
When view is on screen the updateConstraints:
, layoutSublayersOfLayer:
and
layoutSubviews:
methods are called. That’s all for this case. Easy to remember.
View with subviews loaded from a storyboard
The flow is bit different because there are few subviews to add and layout.
First difference is that after initWithCoder:
method is called the next one
is adding subviews of this loaded view in _addSubviews:positioned:relativeTo:
method.
Other things to time when updateConstraints
method is called stays the same.
The second thing is, no matter how many views there are the setNeedsLayout
method is
called twice and layoutSublayersOfLayer:
is also called twice.
So… Yeah, I hope it helps in understanding the flow better.