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.
initWithCoder: is called and next is
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
After view is added to superview
awakeFromNib is called. I thought that
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
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 by
method, so it loads the view, decodes and set properties and those are ready to be used.
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
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
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.