{"id":192,"date":"2018-07-17T17:45:04","date_gmt":"2018-07-17T15:45:04","guid":{"rendered":"http:\/\/www.cocoaminers.com\/?p=192"},"modified":"2018-07-17T17:45:04","modified_gmt":"2018-07-17T15:45:04","slug":"how-to-make-the-uiviewcontroller-containment-easier","status":"publish","type":"post","link":"https:\/\/www.cocoaminers.com\/?p=192","title":{"rendered":"How to make the UIViewController containment easier"},"content":{"rendered":"<p>Hopefully most of you are familiar with the concept of the Container View Controller. It\u2019s a really useful Cocoa feature that I find myself using more and more lately. I won\u2019t go into its implementation details, though, since you can find it in <a href=\"https:\/\/developer.apple.com\/library\/archive\/featuredarticles\/ViewControllerPGforiPhoneOS\/TheViewControllerHierarchy.html#\/\/apple_ref\/doc\/uid\/TP40007457-CH33-SW1\">Apple&#8217;s doc<\/a>.<\/p>\n<p>Let&#8217;s dive into some scenarios where I find it super useful.<\/p>\n<ol>\n<li>\n<p>Embed <code>UITableViewController<\/code>. Everybody has been there. You have a table, and some other content around. Most people just add <code>UITableView<\/code> into their <code>UIViewController<\/code> subclass. But this way you throw away a lot of the functionality that you get for free via <code>UITableViewController<\/code>, such as:<\/p>\n<ul>\n<li>autoscroll to focused <code>UITextField<\/code> and <code>UITextView<\/code> so that they are not hidden behind keyboard<\/li>\n<li>default <code>UITableViewDatasource<\/code> and <code>UITableViewDelegate<\/code> implementations<\/li>\n<li>flawless pull to refresh<\/li>\n<\/ul>\n<p>to name a few. If you put <code>UITableViewController<\/code> into container you get best of both worlds &#8211; flexibility of your own <code>UIViewController<\/code> subclass for decorating content and built-in functionality of the <code>UITableViewController<\/code><\/p>\n<\/li>\n<li>\n<p>Shared screen portions &#8211; those which reappear in differents parts of the app. This is especially helpful if you use architectures such as <code>CleanSwift<\/code>. You can easily reuse complete scenes, with all of their helpers (interactors, routers, workers) already set up.<\/p>\n<\/li>\n<li>\n<p>Display error and empty states of the scene.<\/p>\n<\/li>\n<li>\n<p>Use it for animating controllers because it\u2019s easier to animate <code>UIView<\/code> with <code>UIViewPropertyAnimator<\/code> and <code>UIGestureRecognizer<\/code> than <code>UIViewController<\/code> using <a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/animation_and_haptics\/view_controller_transitions?changes=_9\">View Controller Transitions<\/a>. Make a container view with the embedded controller and animate it around as you would with any other view. You can see this approach in <a href=\"https:\/\/github.com\/inloop\/UIViewController-DisplayInDrawer\">DisplayInDrawer<\/a> lib.<\/p>\n<\/li>\n<\/ol>\n<p>And there are many more scenarios where <code>UIViewController<\/code> containment can simplify your programmer&#8217;s life. But &#8211; there is a caveat. Let&#8217;s say you have an embedded <code>UITableViewController<\/code>. You just got the data, so you create a controller, inject the data, embed it, and display. So far so good. New data arrives. Many times on many projects I have seen that the same routine is used. &#8220;so you <strong><em>create a controller<\/em><\/strong>, inject data, &#8230;&#8221;. <strong>Wrong<\/strong>. You needlessly instantiate a new controller although you already have one. Except this can be expensive (<code>viewDidLoad<\/code> tends to be quite busy, right?), you can bring in crazy bugs, e.g. register duplicate observers, completion handlers etc. This can get even worse if your controller is not deallocating properly. Although I am sure <em>your<\/em> controllers <em>do deallocate<\/em> &#x1f46e;, because you check that diligently, don&#8217;t you?<\/p>\n<p>The solution is to check every time, if the controller exists already, and if it does &#8211; just inject the data. Do not make a new instance.<\/p>\n<p>But this can get tedious and you can easily forget to make this check.<\/p>\n<p>Enter <a href=\"https:\/\/github.com\/inloop\/UIViewController-DisplayChild\"><code>UIViewController-DisplayChild<\/code><\/a> extension which mitigates this problem by embedding (displaying) the <em>type<\/em> instead of <em>instance<\/em>. You give it controller&#8217;s <em>type<\/em>, configuration closure and a container view. The extension decides whether the controller needs to be instantiated, makes an instance if needed, runs your configuration closure on it and embeds it to the specified container view.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hopefully most of you are familiar with the concept of the Container View Controller. It\u2019s a really useful Cocoa feature that I find myself using more and more lately. I won\u2019t go into its implementation details, though, since you can find it in Apple&#8217;s doc. Let&#8217;s dive into some scenarios where I find it super [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-192","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=\/wp\/v2\/posts\/192","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=192"}],"version-history":[{"count":3,"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=\/wp\/v2\/posts\/192\/revisions"}],"predecessor-version":[{"id":197,"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=\/wp\/v2\/posts\/192\/revisions\/197"}],"wp:attachment":[{"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=192"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cocoaminers.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}