Managing Child View Controller in Scroll View
This article is based on parent-child relationship through scroll view. I will be talking about how UI communication is implemented between two. To keep it simple, I’ve shortened child view controller as child and parent view controller as parent.
We are all familiar with view controllers that have some responsibilities as taking user interactions, displaying associated content onscreen, handling UI logics.
As long as developing on the same object, they may hold more responsibilities. Furthermore, to incorporate all these into same view controller scene would compose a massive source file, end up with a hard maintainable code.
Today, let’s take a look at one approach that manages content of child through scroll view. After implementation of UI elements are fulfilled, we will first employ View Controller Containment then focused on content size of child’s view.
Implementing UI Objects
As above image indicates interface builder has nested objects. It has one scroll view lays out the views, in itself, to facilitate visibility of custom view there is a vertical stack view. Ultimately, we see one custom view—being stored a reference of itself and its height constraint— that waits for the new embedded view. User interface is now ready, let’s go one step further.
View Controller Containment
If you have practiced on Container View Controller, you might’ve heard about View Controller Containment. It’s basically to embed content of child(s) into parent programmatically and has the concept of parent-child relationship. To establish this containment, here we call four lines of code respectively.
- Add instantiated view controller to create parent-child relationship.
- Add child’s root view into custom view which is in currently stack view.
- Configure and activate required constraints.
- Let the child know that transition to the parent is complete.
We’ve walked through the way of displaying content of child using scroll view. One point to concern about is to get child’s content size and notify the parent. Let’s make a few adjustment.
Preferred Content Size
UIViewController
in itself, exposes one property named preferredContentSize
having a type of CGSize
. It turns out that notifying parent via this property is effortless. Since, once you assign a new value to preferredContentSize
in child, UIKit calls preferredContentSizeDidChange
named method — in UIContentContainer
protocol adopted by UIViewController
. Hence, overriding this method in parent keeps the size of embedded child’s view up to date as shown below.
Note: Each time you expect child’s view size is modified, you should update
preferredContentSize
value.
After we’ve taken this step, UIKit performs the data flow instead of implementing any communication pattern to get content size.
Things To Know
We’ve tackle this approach with static embedded view in interface builder, but there might be different scenarios where embedded views are dynamic. In this case, we can handle creating views programmatically.
Yet another scenario, if child contains, for example, UICollectionView
where all UICollectionViewCell
data items are required to invoke dequeueReusableCell
on scrolling, you need to call reloadData()
. Since with this approach, all cells are dequeued only once.
To Finalize
Well, all these things, using this approach gives a project reusability. We are free to use ChildViewController
where it’s needed. Each stand-alone component has its own responsibilities which means helps to reduce code complexity and provides a testable parts within itself.
There might be some interesting area of this article where your thoughts and ideas will be helpful, I would be appreciated if you share these with me.
You can access the source code here, there is one basic demo in it.
Thanks for your time!