<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Arkadiusz Holko</title>
    <description>Arkadiusz Holko</description>
    <link>https://holko.pl</link>
    <atom:link href="https://holko.pl/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Hiding Implementation Details Using internal Properties</title>
        <description>&lt;p&gt;Swift comes with &lt;a href=&quot;https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html&quot;&gt;five access-level modifiers&lt;/a&gt;: &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;internal&lt;/code&gt;, &lt;code&gt;fileprivate&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt;. The &lt;code&gt;internal&lt;/code&gt; modifier leads to entities being available for use only within their defining module. It’s a default modifier but it starts getting interesting only once we split our codebase into modules.&lt;/p&gt;

&lt;p&gt;In this article, we’ll see how to provide an ability to inject a framework’s data structure into the framework’s classes, while at the same time keeping its &lt;em&gt;internals&lt;/em&gt; hidden.&lt;/p&gt;

&lt;!-- break --&gt;

&lt;h2 id=&quot;problem-statement&quot;&gt;Problem Statement&lt;/h2&gt;

&lt;p&gt;Most apps these days need some kind of local persistence of data. There are many choices: &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/index.html&quot;&gt;Core Data&lt;/a&gt;, &lt;a href=&quot;https://realm.io&quot;&gt;Realm&lt;/a&gt;, &lt;a href=&quot;https://www.sqlite.org/index.html&quot;&gt;SQLite&lt;/a&gt; &lt;a href=&quot;https://github.com/groue/GRDB.swift&quot;&gt;with&lt;/a&gt; or without wrappers, etc. No matter what we choose, once our project exceeds 10K, 50K, or 100K lines of code we’ll inevitably start thinking about splitting it up into modules.&lt;/p&gt;

&lt;p&gt;One of the modules we can consider extracting from the main target would contain the database access code. Let’s call it PersistenceKit, following Apple’s naming convention. We can implement the module either as a &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/OverviewOfDynamicLibraries.html&quot;&gt;dynamic framework&lt;/a&gt; or a &lt;a href=&quot;https://www.bignerdranch.com/blog/it-looks-like-you-are-trying-to-use-a-framework/&quot;&gt;static library&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Let’s assume that PersistenceKit will contain many &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_access_object&quot;&gt;repositories&lt;/a&gt;, such as: &lt;code&gt;ArticleRepository&lt;/code&gt;, &lt;code&gt;UserRepository&lt;/code&gt;, etc that we’ll use to fetch and store data. A repository can be implemented as follows:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Article&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleID&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleRepository&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// finds a row in the database and maps it to a struct&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// missing implementation&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// other methods...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To be able to perform an actual database access in implementations of repositories’ methods, we need some kind of reference to the database, be it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core Data: &lt;a href=&quot;https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext&quot;&gt;NSManagedObjectContext&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Realm: &lt;a href=&quot;https://realm.io/docs/swift/latest/#opening-realms&quot;&gt;Realm object&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SQLite in C: &lt;a href=&quot;https://www.sqlite.org/c3ref/sqlite3.html&quot;&gt;sqlite3 pointer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GRDB.swift: &lt;a href=&quot;https://github.com/groue/GRDB.swift/blob/6c7ac25fb8a75396774260b96e3a149d4ba92310/GRDB/Core/DatabasePool.swift&quot;&gt;DatabasePool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being good engineers we strive to be, we want to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoid keeping any of these references in a singleton or as a shared global variable.&lt;/li&gt;
&lt;li&gt;Don’t let users of PersistenceKit know about its implementation details, i.e. we want the fact that we use &lt;code&gt;NSManagedObjectContext&lt;/code&gt; or &lt;code&gt;DatabasePool&lt;/code&gt; internally stay hidden.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;

&lt;p&gt;I recently spent some time thinking about these two goals and came up with an approach that I’m happy with. It’s based on a mix of public and internal modifiers. Let’s introduce a new struct:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DatabasePool&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;This way &lt;code&gt;Connection&lt;/code&gt; struct is accessible outside of PersistenceKit but &lt;code&gt;pool&lt;/code&gt; property isn’t. It’s not even possible to initialize this struct outside of PersistenceKit because its &lt;a href=&quot;https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html#ID21&quot;&gt;memberwise initializer is in this case internal&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, since users of our framework won’t be able to initialize &lt;code&gt;Connection&lt;/code&gt;, we have to provide them with an instance. We can do that in an entry point to PersistenceKit:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AppDatabase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// performs the setup and returns a connection instance&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s left, is injecting &lt;code&gt;Connection&lt;/code&gt; to our &lt;code&gt;ArticleRepository&lt;/code&gt;, by changing its implementation to:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleRepository&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// we can access `pool` property here because it’s accessible in this module&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Article&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetchOne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Users can now set up PersistenceKit as follows:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AppCoordinator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PersistenceKit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Connection&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AppDatabase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;database&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, when they want to fetch something, they can simply pass &lt;code&gt;connection&lt;/code&gt; to &lt;code&gt;ArticleRepository&lt;/code&gt;’s methods:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;repository&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleRepository&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repository&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even if users of our framework wanted to access &lt;code&gt;Connection.pool&lt;/code&gt; here directly, they couldn’t because it’s not accessible outside of PersistenceKit. We can be sure that database access code stays in &lt;code&gt;PersistenceKit&lt;/code&gt; leading to &lt;a href=&quot;https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html&quot;&gt;a cleaner overall architecture&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Public types with internal properties are a powerful tool. We showed how to allow users to own and pass an object we need – as the framework’s authors – without exposing any of the internals. Are you aware of any other cool uses of &lt;code&gt;public&lt;/code&gt; types with &lt;code&gt;internal&lt;/code&gt; properties?&lt;/p&gt;
</description>
        <pubDate>Mon, 08 Oct 2018 16:25:37 +0200</pubDate>
        
        <link>https://holko.pl/2018/10/08/internal-modifier/</link>
        
        <guid isPermaLink="false">http://holko.pl//2018/10/08/internal-modifier/</guid>
      </item>
    
      <item>
        <title>Why #if DEBUG Conditional Should Be Avoided in Library Code</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://docs.swift.org/swift-book/ReferenceManual/Statements.html#ID539&quot;&gt;&lt;em&gt;Conditional Compilation&lt;/em&gt;&lt;/a&gt; along with &lt;a href=&quot;https://fdp.io/blog/2018/03/18/active-compilation-conditions-for-xcode/&quot;&gt;&lt;em&gt;Active Compilation Conditions&lt;/em&gt;&lt;/a&gt; is a way to alter the app’s behavior depending on the build configuration. For example for the code to compile only in the Debug configuration, we can do:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#if DEBUG&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;performAdditionalChecks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this article, I’ll show why these kinds of conditional blocks shouldn’t be used directly in the source code of libraries distributed to other developers.&lt;/p&gt;

&lt;!-- break --&gt;

&lt;h2 id=&quot;problem&quot;&gt;Problem&lt;/h2&gt;

&lt;p&gt;Around a week ago I noticed that my &lt;a href=&quot;https://github.com/fastred/DeallocationChecker&quot;&gt;DeallocationChecker&lt;/a&gt; library didn’t catch a leaking view controller in a project I help with. At the time the main entry method in that library &lt;a href=&quot;https://github.com/fastred/DeallocationChecker/blob/df2fb2188d5a0e51f286dd8e13372d035e32d080/Sources/DeallocationChecker.swift&quot;&gt;looked like this&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dch_checkDeallocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;afterDelay&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;TimeInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;#if DEBUG&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Real logic can be ignored for this article&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isLeaked&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;assertionFailure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After a short debugging session I noticed that even though the app is running in the Debug configuration, the code within this &lt;code&gt;#if DEBUG&lt;/code&gt; block isn’t compiled at all! It confused me because that code was running fine just a few months ago.&lt;/p&gt;

&lt;p&gt;Here’s a summary of the situation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Active Compilation Conditions&lt;/em&gt; were set up correctly in the main project because the code in &lt;code&gt;#if DEBUG&lt;/code&gt; blocks inside the project was being compiled and executed.&lt;/li&gt;
&lt;li&gt;DeallocationChecker was included through &lt;a href=&quot;https://github.com/Carthage/Carthage&quot;&gt;Carthage&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, there was something wrong with conditional compilation using &lt;code&gt;DEBUG&lt;/code&gt; flag specifically in the project included through Carthage.&lt;/p&gt;

&lt;h2 id=&quot;carthage&quot;&gt;Carthage&lt;/h2&gt;

&lt;p&gt;In contrast to libraries imported through &lt;a href=&quot;https://cocoapods.org&quot;&gt;CocoaPods&lt;/a&gt; or as subprojects, Carthage operates in a two-step way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, when we add or update a dependency, Carthage builds it and produces a binary framework.&lt;/li&gt;
&lt;li&gt;Then, going forward we use that prebuilt framework in the project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;This means, that when Carthage builds a framework, it doesn’t know whether the framework will be used in Debug, Release or any other configuration!&lt;/strong&gt; So, it defaults to the Release configuration, causing that &lt;code&gt;#if DEBUG&lt;/code&gt; block to not be compiled. We end up with our app’s code running in the Debug configuration, yet the library’s code is at the same time running in its Release configuration.&lt;/p&gt;

&lt;p&gt;Technically speaking, we can instruct &lt;a href=&quot;https://github.com/Carthage/Carthage/issues/2370#issuecomment-372116902&quot;&gt;Carthage to use the Debug configuration&lt;/a&gt; but that complicates the workflow significantly. We would have to build both configurations and make sure to not ship a non-optimized Debug version to our users.&lt;/p&gt;

&lt;p&gt;Also, the same rule applies to libraries distributed only in a binary form, e.g. &lt;a href=&quot;https://fabric.io/kits/ios/crashlytics/install&quot;&gt;Fabric&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;

&lt;p&gt;A better approach to conditioning the execution depending on a configuration is to get the current configuration from a library’s user. It can be as simple as:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#if DEBUG&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;YourAwesomeLibrary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;useDebugChecks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#else&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;YourAwesomeLibrary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;useDebugChecks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This way, as a library’s author we stop being dependent on the exact way a user builds it. The intention gets explicit.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;We learned how a subtle difference in a build process can break an otherwise sound code. What’s worse in this case, due to the nature of DeallocationChecker, which is invisible unless there’s a leak, the bug went unnoticed for some time.&lt;/p&gt;

&lt;p&gt;As to why the conditional check stopped working for us just in recent months? We switched from CocoaPods to Carthage in the meantime. So, DeallocationChecker didn’t suddenly break, it just never worked correctly with Carthage.&lt;/p&gt;
</description>
        <pubDate>Mon, 24 Sep 2018 14:55:00 +0200</pubDate>
        
        <link>https://holko.pl/2018/09/24/compilation-directives-in-libraries/</link>
        
        <guid isPermaLink="false">http://holko.pl//2018/09/24/compilation-directives-in-libraries/</guid>
      </item>
    
      <item>
        <title>Future-Proof Dependency Injection for Storyboard-Based View Controllers</title>
        <description>&lt;p&gt;One of the issues introduced by storyboards is that they &lt;a href=&quot;http://holko.pl/2016/03/29/storyboards-and-alternatives/&quot;&gt;make it impossible to pass dependencies&lt;/a&gt; to view controllers in initializers. I &lt;a href=&quot;http://holko.pl/2016/12/14/storyboards-dependency-injection/&quot;&gt;proposed an API modification&lt;/a&gt; in past that would allow for exactly that, but alas, it doesn’t seem to be high on the priority list for UIKit. I recently came up with a new approach leveraging code generation which I’m excited to show you today.&lt;/p&gt;

&lt;!-- break --&gt;

&lt;h2 id=&quot;initialization-recap&quot;&gt;Initialization Recap&lt;/h2&gt;

&lt;p&gt;Since it’s not possible to use initializers to pass dependencies, in most cases developers rely on implicitly unwrapped optionals to indicate properties that should be set immediately after a view controller was created, e.g.:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then at a call site, a view controller is initialized as follows:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;storyboard&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Profile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storyboard&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instantiateViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;withIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;profileViewController&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as!&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can use a third-party tool like &lt;a href=&quot;https://github.com/SwiftGen/SwiftGen&quot;&gt;SwiftGen&lt;/a&gt; to get rid of strings, leaving us with:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardScene&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instantiateProfileViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;While observing a lifetime of a few codebases relying on storyboards I  noticed that at a time a new view controller is added everything is fine, no bugs here. &lt;strong&gt;The bugs start appearing when a view controller is modified and not all dependencies are set properly in each call site.&lt;/strong&gt; In case of implicitly unwrapped optionals (IUO), that leads to runtime crashes.&lt;/p&gt;

&lt;p&gt;We can leverage the Swift compiler to warn us about those issues if we make a few assumptions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Properties defined as implicitly unwrapped optionals (excluding &lt;code&gt;@IBOutlet&lt;/code&gt;s) are dependencies that should be passed in from the outside.&lt;/li&gt;
&lt;li&gt;We’re fine with code generation.&lt;/li&gt;
&lt;li&gt;We’ll always use the same generated methods to initialize or set up (in case of segues) view controllers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Knowing these assumptions it becomes clear (maybe only when you’re standing under a shower, though 😀) that all we need is an additional method that accepts all objects we need to initialize IUO properties. So for our &lt;code&gt;ProfileViewController&lt;/code&gt; we should have:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;makeFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// magic here&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s important, if we add a new dependency to our view controller, e.g.:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;analyticsManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnalyticsManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;that method should be automatically updated to:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;makeFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;analyticsManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnalyticsManager&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// magic here&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We definitely don’t want to have to update this method manually each time we change a view controller. Code generation to the rescue!&lt;/p&gt;

&lt;h2 id=&quot;code-generation&quot;&gt;Code Generation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/apple/swift/tree/master/tools/SourceKit&quot;&gt;SourceKit&lt;/a&gt; provides us with metadata about types in our Swift project. Based on that metadata we can generate additional code each time our project changes. There’s already a good tool doing exactly that – &lt;a href=&quot;https://github.com/krzysztofzablocki/Sourcery&quot;&gt;Sourcery&lt;/a&gt; – that we’ll use.&lt;/p&gt;

&lt;p&gt;Let’s start by declaring a new protocol:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardInitializable&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instantiateFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and mark our &lt;code&gt;ProfileViewController&lt;/code&gt; as conforming to it. &lt;code&gt;instantiateFromStoryboard()&lt;/code&gt; is a method using &lt;code&gt;instantiateViewController(withIdentifier:)&lt;/code&gt;  under the hood:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardInitializable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instantiateFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;storyboard&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Profile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storyboard&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instantiateViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;withIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;profileViewController&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as!&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, for this view controller we want the following methods to be generated:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// MARK: - ProfileViewController - StoryboardDependencyInjection&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;makeFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instantiateFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I prepared a template for Sourcery which does exactly that (it&amp;#39;s also &lt;a href=&quot;https://github.com/fastred/StoryboardDependencyInjectionTemplates/blob/master/StoryboardDependencyInjection.ejs&quot;&gt;on GitHub&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;implementing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;StoryboardInitializable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// MARK: - &amp;lt;%= type.name -%&amp;gt; - StoryboardDependencyInjection&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;allProperties&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;allProperties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;allProperties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;storedVariables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;currentType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;supertype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;allProperties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isImplicitlyUnwrappedOptional&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;IBOutlet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;writeAccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;makeFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unwrappedTypeName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;viewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;instantiateFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;viewController&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unwrappedTypeName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-%&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Having these methods, each time we want to create &lt;code&gt;ProfileViewController&lt;/code&gt;, we should do it this way:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;profileViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;If we add a new IUO property to &lt;code&gt;ProfileViewController&lt;/code&gt;, the build will fail with an error&lt;/strong&gt; because there will be a new parameter in &lt;code&gt;makeFromStoryboard()&lt;/code&gt; method:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ProfileViewController.swift:19:98: Missing argument for parameter &amp;#39;analyticsManager&amp;#39; in call  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✨&lt;/p&gt;

&lt;h2 id=&quot;even-better-code-generation&quot;&gt;Even Better Code Generation&lt;/h2&gt;

&lt;p&gt;What we have here is nice and will help us avoid bugs when we modify our view controllers in the future.  We can go a step further, though.&lt;/p&gt;

&lt;p&gt;If we use SwiftGen, it will generate a file with constants for us, e.g.:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardScene&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardSceneType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;storyboardName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Profile&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;profileViewControllerScene&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;profileViewController&quot;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;instantiateProfileViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardScene&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;profileViewControllerScene&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ViewController 'profileViewController' is not of the expected class ProfileViewController.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vc&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Instead of implementing &lt;code&gt;instantiateFromStoryboard()&lt;/code&gt; in each view controller, we can let Sourcery analyze the contents of &lt;code&gt;StoryboardScene&lt;/code&gt; enum and put a correct initialization in our generated file:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;makeFromStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewModel&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProfileViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StoryboardScene&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instantiateProfileViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setDependencies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We got rid both of stringly-typed API and future-proofed our code. You can find this template &lt;a href=&quot;https://github.com/fastred/StoryboardDependencyInjectionTemplates/blob/master/StoryboardDependencyInjectionWithSwiftGen.ejs&quot;&gt;on GitHub here&lt;/a&gt;. I think this is pretty cool!&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Bridging external resources  with code is hard. Code generation seems to be a temporarily approved way (see code generation for &lt;code&gt;NSManagedObject&lt;/code&gt; subclasses or &lt;code&gt;Codable&lt;/code&gt; protocol) of working around the design issues in iOS APIs. We showed how to use code generation to create a safer API for view controllers when using storyboards.  You can find templates described in this article on &lt;a href=&quot;https://github.com/fastred/StoryboardDependencyInjectionTemplates&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 06 Dec 2017 16:05:00 +0100</pubDate>
        
        <link>https://holko.pl/2017/12/06/future-proof-dependency-injection/</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/12/06/future-proof-dependency-injection/</guid>
      </item>
    
      <item>
        <title>Stop Xcode from constantly rebuilding your project because of @IBDesignable</title>
        <description>&lt;p&gt;If you use Interface Builder along with &lt;code&gt;@IBDesignable&lt;/code&gt; attribute you may have noticed that Xcode sometimes builds your project even though you didn’t trigger a build. This is because it needs to compile views marked with &lt;code&gt;@IBDesignable&lt;/code&gt; to be able to render them in Interface Builder. What&amp;#39;s problematic is that these builds seem to occur a bit too often.&lt;/p&gt;

&lt;!-- break --&gt;

&lt;p&gt;After closer inspection, I managed to notice what happens without having to disassemble Xcode. Xcode can be in two states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Default state:

&lt;ul&gt;
&lt;li&gt;You can edit all source files and save them, without Xcode triggering builds needed for IB rendering.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Once you open any XIB or storyboard file that references a view marked as &lt;code&gt;@IBDesignable&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Saving any source file (not even a view) associated with the same target will now cause an automatic rebuild of the project.&lt;/li&gt;
&lt;li&gt;What’s more, &lt;strong&gt;even after you’ve closed all Interface Builder tabs, the behavior will persist until you reopen the project.&lt;/strong&gt; I think this is a bug (reported as &lt;a href=&quot;http://www.openradar.me/35558659&quot;&gt;rdar://35558659&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thankfully, you can disable these automatic rebuilds by opening any file in Interface Builder, going to &lt;em&gt;Editor&lt;/em&gt; menu and unchecking &lt;em&gt;Automatically Refresh Views&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/automatically_refresh_views.png&quot; width=&quot;322&quot; class=&quot;center&quot;&gt;
&lt;div class=&quot;image-caption&quot;&gt;Deselect &amp;quot;Automatically Refresh Views&amp;quot; if Xcode rebuilds your project too often&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;After this change, you’ll now have to manually trigger an IB-specific build when you want to see the preview of your &lt;code&gt;@IBDesignable&lt;/code&gt; views. I recommend setting up a key binding for &lt;em&gt;Refresh All Views&lt;/em&gt; option if you use &lt;code&gt;@IBDesignable&lt;/code&gt; often.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/barefeettom/status/930913393581613057&quot;&gt;Tom Brodhurst-Hill mentions on Twitter&lt;/a&gt; that some of these issues got fixed/improved in Xcode 9.2 beta 2.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Nov 2017 15:30:00 +0100</pubDate>
        
        <link>https://holko.pl/2017/11/15/rebuilding-ibdesignables/</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/11/15/rebuilding-ibdesignables/</guid>
      </item>
    
      <item>
        <title>Optimizing Swift build times →</title>
        <description>&lt;p&gt;I spent some time recently trying to optimize build times of a project I contribute to.
To my surprise, the knowledge needed to do that was scattered around many blog posts and tweets.
So, I decided to do something about that by putting everything I knew and learned in a single document.
It&amp;#39;s available on &lt;a href=&quot;https://github.com/fastred/Optimizing-Swift-Build-Times&quot;&gt;GitHub here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hope you learn something new!&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Nov 2017 20:20:00 +0100</pubDate>
        
        <link>https://github.com/fastred/Optimizing-Swift-Build-Times</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/11/08/optimizing-swift-build-times/</guid>
      </item>
    
      <item>
        <title>Surprising behavior of non-optional @NSManaged properties</title>
        <description>&lt;p&gt;Core Data is not a first-class citizen in the Swift world. Its inherently dynamic nature is lurking at us through an attribute created specifically for it: &lt;code&gt;@NSManaged&lt;/code&gt;. Let me show you how this dynamic nature caught me off guard. &lt;strong&gt;I ended up with a property having a value I’d never assigned to it!&lt;/strong&gt;&lt;/p&gt;

&lt;!-- break --&gt;

&lt;h2 id=&quot;nsmanaged-means-dynamic&quot;&gt;@NSManaged means dynamic&lt;/h2&gt;

&lt;p&gt;Imagine we’re starting a new project and need a way to represent a user. We’ve got:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which doesn’t yet compile in this form. We have to either 1) add an initial value to the &lt;code&gt;name&lt;/code&gt; property, or 2) add an initializer that sets the value of that property. Another option is to store the user’s data with Core Data. If we just inherit from &lt;code&gt;NSManagedObject&lt;/code&gt; and add &lt;code&gt;@NSManaged&lt;/code&gt; attribute, the code will … compile cleanly:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSManagedObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@NSManaged&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is Core Data’s way of saying &lt;em&gt;I’ll take it from here.&lt;/em&gt; Getter and setter for  &lt;code&gt;name&lt;/code&gt; are created dynamically by &lt;code&gt;NSManagedObject&lt;/code&gt; class. We can confirm that fact by using &lt;code&gt;@NSManaged&lt;/code&gt; on a class not inheriting from &lt;code&gt;NSManagedObject&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FakeUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@NSManaged&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fakeUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FakeUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fakeUser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;leading to &lt;code&gt;-[FakeUser setName:]: unrecognized selector sent to instance 0x608000009fb0&lt;/code&gt; exception. With all the safety Swift brings, we can hit a runtime error with as little as 5 lines of code, as long as it uses Core Data.&lt;/p&gt;

&lt;h2 id=&quot;peculiar-non-optionals&quot;&gt;Peculiar non-optionals&lt;/h2&gt;

&lt;p&gt;Let’s go back on track, though. We initialize a user, passing an  &lt;code&gt;NSManagedObjectContext&lt;/code&gt; instance to it:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// =&amp;gt; &quot;John&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So far, so good. We add a method responsible for creating users, to make sure a user always has a name and forget about this code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSManagedObjectContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withName&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;precondition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One day though, we notice that in some parts of the app, the user’s name is equal to an empty string:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// =&amp;gt; &quot;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s weird: &lt;code&gt;precondition&lt;/code&gt; call makes sure that the name is initially never set to an empty string. It’s also never changed by other parts of the codebase!&lt;/p&gt;

&lt;p&gt;A few minutes (or &lt;em&gt;more honestly&lt;/em&gt; hours) of debugging later, we notice that the &lt;code&gt;name&lt;/code&gt; is an empty string only on instances that were deleted from a context and the context was saved. (Deletion of managed objects is unrelated to ARC, so we have objects living in memory even though they are already treated as deleted.)&lt;/p&gt;

&lt;p&gt;Because the &lt;code&gt;name&lt;/code&gt; property is dynamic, we can’t check who changes its value to &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;. Let’s attack from a different angle by changing its type to optional:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;@NSManaged&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, after a &lt;code&gt;User&lt;/code&gt; object was deleted and a context was saved, the value of &lt;code&gt;name&lt;/code&gt; is correct: &lt;code&gt;nil&lt;/code&gt;, not an empty string. Which leads us to the conclusion: &lt;strong&gt;returned value depends on the way the property is declared.&lt;/strong&gt; &lt;strike&gt;When it’s non-optional, &lt;code&gt;NSManagedObject&lt;/code&gt; does what it can to never return &lt;code&gt;nil&lt;/code&gt;, substituting a &lt;em&gt;default&lt;/em&gt; value instead.&lt;/strike&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(UPDATE: Sep 20, 2017: As &lt;a href=&quot;https://www.reddit.com/r/iOSProgramming/comments/70vp58/surprising_behavior_of_nonoptional_nsmanaged/dn7n99s/&quot;&gt;pointed out on Reddit&lt;/a&gt; replacement of &lt;code&gt;nil&lt;/code&gt; with an empty string is actually caused by &lt;a href=&quot;https://github.com/apple/swift/blob/5c4fe26aba4cc0fc19a8cc811a4f3d30cbd4cea7/stdlib/public/SDK/Foundation/String.swift#L53-L60&quot;&gt;bridging from &lt;code&gt;NSString&lt;/code&gt; to &lt;code&gt;String&lt;/code&gt;&lt;/a&gt;.)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The same silent substitution happens for these types too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;numeric types use a value equal to &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Data&lt;/code&gt; uses an empty &lt;code&gt;Data&lt;/code&gt; instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The substitution doesn’t happen for other types. In these three cases we get &lt;code&gt;nil&lt;/code&gt;s when the type system doesn’t expect them, often causing crashes somewhere inside stdlib:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UUID&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;URI&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s worth mentioning, that the substitution happens even when there’s no default value set for an attribute in the  &lt;code&gt;xcdatamodel&lt;/code&gt; file.&lt;/p&gt;

&lt;h2 id=&quot;relationships&quot;&gt;Relationships&lt;/h2&gt;

&lt;p&gt;This behavior spans relationships too. Let’s say we also have an &lt;code&gt;Event&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSManagedObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@NSManaged&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@NSManaged&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and run this code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Can you guess what happens? We didn’t set up the  &lt;code&gt;user&lt;/code&gt; relationship, so we should get either a &lt;code&gt;nil&lt;/code&gt; or a fatal error, right? Well, we don’t. An empty string is printed in this case too!&lt;/p&gt;

&lt;p&gt;This is completely counter-intuitive when compared to the normal Swift code: &lt;strong&gt;&lt;code&gt;event.user&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;, yet &lt;code&gt;event.user.name&lt;/code&gt; isn’t.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;possible-solution&quot;&gt;Possible solution&lt;/h2&gt;

&lt;p&gt;The safest approach is to make all &lt;code&gt;@NSManaged&lt;/code&gt; properties optional but it’s not great as far as a codebase’s readability goes.&lt;/p&gt;

&lt;p&gt;The specific approach I’m considering switching to is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Optionals for &lt;code&gt;@NSManaged&lt;/code&gt; properties which are optional in the regular Swift sense.&lt;/li&gt;
&lt;li&gt;Implicitly unwrapped optionals for &lt;code&gt;@NSManaged&lt;/code&gt; properties which should be &lt;code&gt;nil&lt;/code&gt; only twice in their lives:

&lt;ul&gt;
&lt;li&gt;before the first time their value is set&lt;/li&gt;
&lt;li&gt;after a managed object they belong to was deleted&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Implicitly unwrapped optionals will make some call-sites look worse but they’ll allow us to fail early with the familiar:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;fatal error: unexpectedly found nil while unwrapping an Optional value
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;instead of having an unexpected value propagating through the program.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In cases like this, it becomes clear that Core Data predates Swift. There are some really rough edges around it. If breaking changes were possible on the framework level, I’d propose for Core Data to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trap on reads when a value behind a non-optional attribute/relationship is &lt;code&gt;nil&lt;/code&gt;, at least in the debug configuration, or&lt;/li&gt;
&lt;li&gt;don&amp;#39;t allow &lt;code&gt;@NSManaged&lt;/code&gt; properties to be declared as non-optional&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 18 Sep 2017 16:20:00 +0200</pubDate>
        
        <link>https://holko.pl/2017/09/18/surprising-non-optional-nsmanaged/</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/09/18/surprising-non-optional-nsmanaged/</guid>
      </item>
    
      <item>
        <title>Catching Leaky View Controllers Without Instruments</title>
        <description>&lt;p&gt;One of the well-known techniques for finding memory leaks caused by &lt;a href=&quot;https://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/&quot;&gt;retain cycles&lt;/a&gt; is &lt;a href=&quot;https://medium.com/@kazmiekr/what-every-ios-developer-should-be-doing-with-instruments-d1661eeaf64f#b228&quot;&gt;checking if all view controllers&lt;/a&gt; get deallocated when they’re not on screen anymore. This is a process that should be manually repeated before each release but it’s both unpleasant and error-prone. &lt;strong&gt;Wouldn’t it be cool if we could learn about &lt;code&gt;UIViewController&lt;/code&gt; leaks earlier in the process, during the day-to-day development?&lt;/strong&gt;&lt;/p&gt;

&lt;!-- break --&gt;

&lt;p&gt;Turns out it’s possible thanks to two not-so-well-known &lt;code&gt;UIViewController&lt;/code&gt; properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isBeingDismissed&lt;/code&gt; – it’s &lt;code&gt;true&lt;/code&gt; when a presented modally view controller is being dismissed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isMovingFromParentViewController&lt;/code&gt; – &lt;code&gt;true&lt;/code&gt;  when a view controller is being removed from a parent view controller. This includes removal from system containers such as popping a view controller from &lt;code&gt;UINavigationController&lt;/code&gt;’s stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If one of these properties is true, we know that the view controller should get deallocated promptly. We don’t know how long exactly it will take a view controller to finish all its internal state cleaning and &lt;a href=&quot;http://clang.llvm.org/docs/AutomaticReferenceCounting.html#object-liveness&quot;&gt;ARC to deallocate it&lt;/a&gt;, though. For the simplicity’s sake, let’s assume that it will be no more than 2 seconds.&lt;/p&gt;

&lt;p&gt;Putting everything together we get:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dch_checkDeallocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;afterDelay&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;TimeInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rootParentViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dch_rootParentViewController&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// We don’t check `isBeingDismissed` simply on this view controller because it’s common&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// to wrap a view controller in another view controller (e.g. in UINavigationController)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// and present the wrapping view controller instead.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isMovingFromParentViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rootParentViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isBeingDismissed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;disappearanceSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isMovingFromParentViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;removed from its parent&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dismissed&quot;&lt;/span&gt;

            &lt;span class=&quot;kt&quot;&gt;DispatchQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;asyncAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;deadline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
                &lt;span class=&quot;nf&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; not deallocated after being &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disappearanceSource&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dch_rootParentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The interesting bits happen in &lt;code&gt;asyncAfter(deadline:execute:)&lt;/code&gt; call. First, we weakify self (&lt;code&gt;[weak self]&lt;/code&gt;), so that it’s not retained by the delayed closure. Then, we assert that &lt;code&gt;self&lt;/code&gt; (the &lt;code&gt;UIViewController&lt;/code&gt; instance) is &lt;code&gt;nil&lt;/code&gt;. &lt;strong&gt;It’s not &lt;code&gt;nil&lt;/code&gt; only if we have a retain cycle keeping the view controller alive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, all we need to do is call &lt;code&gt;dch_checkDeallocation()&lt;/code&gt; from &lt;code&gt;viewDidDisappear(_:)&lt;/code&gt; in all view controllers (except for those that we keep alive after they’re removed from their parents or dismissed):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidDisappear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewDidDisappear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;dch_checkDeallocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If there’s a leak, we’ll see an assertion failure (only in &lt;code&gt;-Onone&lt;/code&gt; builds):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/deallocation_checker@2x.png&quot; class=&quot;wide center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At this point, we can simply open the (awesome) &lt;a href=&quot;https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/debugging_with_xcode/chapters/special_debugging_workflows.html#//apple_ref/doc/uid/TP40015022-CH9-DontLinkElementID_1&quot;&gt;Memory Graph Debugger&lt;/a&gt; to investigate and fix the reason of a cycle.&lt;/p&gt;

&lt;p&gt;I think it’s really cool how quickly we can learn about newly introduced retain cycles with this approach. I hope you’ll enjoy using it too! The production-ready code (with more comments and &lt;code&gt;#if DEBUG&lt;/code&gt; check) is available on &lt;a href=&quot;https://github.com/fastred/DeallocationChecker&quot;&gt;GitHub: DeallocationChecker&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Mon, 26 Jun 2017 15:40:00 +0200</pubDate>
        
        <link>https://holko.pl/2017/06/26/checking-uiviewcontroller-deallocation/</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/06/26/checking-uiviewcontroller-deallocation/</guid>
      </item>
    
      <item>
        <title>Avoiding Third-Party UI Libraries</title>
        <description>&lt;p&gt;There’s been &lt;a href=&quot;http://martiancraft.com/blog/2017/04/analyzing-third-party-libraries/&quot;&gt;some discussion recently in the iOS community&lt;/a&gt; about pros and cons (OK, mostly cons) of using third-party dependencies. Many arguments I saw were rather generic — grouping all third-party libraries into one basket. As with most things, though, it’s not that simple. So, let’s try to focus on a single case today: &lt;strong&gt;should we avoid using third-party UI libraries?&lt;/strong&gt;&lt;/p&gt;

&lt;!-- break --&gt;

&lt;h2 id=&quot;reasons-to-consider-third-party-libraries&quot;&gt;Reasons to consider third-party libraries&lt;/h2&gt;

&lt;p&gt;There seem to be two main reasons developers consider using a third party library:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Lack of skill or knowledge.&lt;/strong&gt; Let’s say, you’re working on a photo sharing app. You don’t start by &lt;a href=&quot;https://motherboard.vice.com/en_us/article/why-you-dont-roll-your-own-crypto&quot;&gt;rolling your own crypto&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lack of time or interest to build something.&lt;/strong&gt; Unless you have an unlimited amount of time (&lt;a href=&quot;https://en.m.wikipedia.org/wiki/Mind_uploading&quot;&gt;which no human has yet&lt;/a&gt;) you have to prioritize.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most UI libraries (&lt;a href=&quot;https://pspdfkit.com&quot;&gt;not all!&lt;/a&gt;) tend to fall into the second category. This stuff is no rocket science, but it takes time to build it right.&lt;/p&gt;

&lt;h2 id=&quot;what-to-outsource&quot;&gt;What to “outsource”&lt;/h2&gt;

&lt;p&gt;So, how do we actually decide what code to write ourselves and what to delegate to a third-party component? The famous &lt;a href=&quot;https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-invented-here-syndrome/&quot;&gt;Joel’s advice&lt;/a&gt; applies really well here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If it’s a core business function — do it yourself, no matter what.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;em&gt;(possibly hard)&lt;/em&gt; truth is that most iOS apps are skewed towards being frontend- rather than backend-heavy. &lt;a href=&quot;https://developer.apple.com/design/awards/&quot;&gt;The look matters&lt;/a&gt;. It follows that we should consider doing as much UI development as possible in-house. One could argue that it’s just &lt;a href=&quot;https://www.youtube.com/watch?v=pWdd6_ZxX8c&quot;&gt;one person’s opinion&lt;/a&gt;, so let’s go through specific reasons you should rethink your usage of third-party UI libraries.&lt;/p&gt;

&lt;h2 id=&quot;problems-with-ui-libraries&quot;&gt;Problems with UI libraries&lt;/h2&gt;

&lt;h3 id=&quot;generic-vs-specific&quot;&gt;Generic vs. specific&lt;/h3&gt;

&lt;p&gt;There are pretty much two types of controls/views:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Generic&lt;/strong&gt;, allowing you to use them in many different contexts not even thought of by their creators, e.g. &lt;code&gt;UICollectionView&lt;/code&gt; from UIKit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specific&lt;/strong&gt;, designed for a single use-case, e.g. &lt;code&gt;UIPickerView&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most third-party libraries tend to fall into the second category. What’s more, they’re often extracted from an existing codebase for which they were optimized.&lt;/p&gt;

&lt;p&gt;As an example, that cool-looking pull to refresh control you saw last month? Yeah, it probably won’t fit your app’s design or use cases, like view controller containment or &lt;code&gt;contentInset&lt;/code&gt; value being modified.&lt;/p&gt;

&lt;h3 id=&quot;inheritance-as-a-way-to-personalize&quot;&gt;Inheritance as a way to personalize&lt;/h3&gt;

&lt;p&gt;As far as OOP goes, there’s an industry-wide move from subclassing to composition. Make sure you’re not going against the flow when choosing a library. In most cases &lt;strong&gt;you let someone else do the composition for you, leaving you with only subclassing or direct code modification&lt;/strong&gt; at your disposal.&lt;/p&gt;

&lt;p&gt;(Delegate pattern is one of the approaches to composition.)&lt;/p&gt;

&lt;h3 id=&quot;too-customized-look&quot;&gt;Too customized look&lt;/h3&gt;

&lt;p&gt;This may seem counterintuitive but the less visible UI there is in a library, the better. The problem with highly customized controls/views is that &lt;strong&gt;it’s not possible to specify their requirements in a way that will fit all use cases&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If there’s a lot of custom UI, you may not be able to contribute back to the upstream, because your ideas about the look or feel may be different than those of the maintainer. You’ll have to either maintain a fork or use some ugly hacks on the app’s side just to remove that one shadow.&lt;/p&gt;

&lt;p&gt;On the other end of the spectrum are libraries that operate on the UI level but don’t provide any or almost any look by themselves, think &lt;a href=&quot;https://github.com/rs/SDWebImage&quot;&gt;SDWebImage&lt;/a&gt; or my &lt;a href=&quot;https://github.com/fastred/SloppySwiper&quot;&gt;SloppySwiper&lt;/a&gt;. These have a higher chance of not needing to be modified just to fit into your project.&lt;/p&gt;

&lt;h3 id=&quot;unknown-early-assumptions&quot;&gt;Unknown early assumptions&lt;/h3&gt;

&lt;p&gt;Many teams do code reviews of their internal code but may be taking third-party source code’s quality for granted. It’s worth spending a bit of time just browsing a library’s code. You may end up being surprised to see some red flags, e.g. swizzling used where it’s not needed.&lt;/p&gt;

&lt;p&gt;Try to get a glimpse of the architecture. Will you be able to adjust the library to your future needs or will you have to rewrite it after your MVP ships?&lt;/p&gt;

&lt;p&gt;You should assess the general health of the project too. How many commits, pull requests and issues have there been lately? Are there any unit or UI tests? Ignore the GitHub stars, though – they’re mostly meaningless.&lt;/p&gt;

&lt;h3 id=&quot;idea-gt-code&quot;&gt;Idea &amp;gt; code?&lt;/h3&gt;

&lt;p&gt;I like open-source because it allows me to see how other people think and design their solutions. &lt;strong&gt;Often learning the idea is more beneficial than obtaining the resulting code itself.&lt;/strong&gt; If a library touches UI and is small, it’s often better to get inspired by its code and develop a component yourself to suit your needs perfectly.&lt;/p&gt;

&lt;h3 id=&quot;can-t-hide-it&quot;&gt;Can’t hide it&lt;/h3&gt;

&lt;p&gt;Because of the way UIKit is designed you most probably won’t be able to hide the third-party UI library, e.g. behind an adapter. A library will intertwine with your UI code becoming a de-facto first-class citizen of your project.&lt;/p&gt;

&lt;h3 id=&quot;future-time-cost&quot;&gt;Future time cost&lt;/h3&gt;

&lt;p&gt;UIKit changes with each iOS release. Things will break. Your third-party dependency won’t be as maintenance-free as you may expect.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As it’s often the case in programming, it’s hard to provide general rules. We have to consider every chunk of code we add to our codebase on a piece-by-piece basis. From my personal experience, most uses of third-party UI code boil down to exchanging smaller flexibility for some time gain.&lt;/p&gt;

&lt;p&gt;We leverage ready-made code to ship our current release faster. Sooner or later, though, we hit the limits of the library and stand before a hard decision: what to do next?&lt;/p&gt;
</description>
        <pubDate>Wed, 31 May 2017 15:50:00 +0200</pubDate>
        
        <link>https://holko.pl/2017/05/31/avoiding-ui-libraries/</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/05/31/avoiding-ui-libraries/</guid>
      </item>
    
      <item>
        <title>Introducing IBAnalyzer</title>
        <description>&lt;p&gt;I&amp;#39;m happy to announce the release of my new tool called &lt;a href=&quot;https://github.com/fastred/IBAnalyzer&quot;&gt;IBAnalyzer&lt;/a&gt;.
Its aim is to allow you to catch common xib and storyboard-related issues without running an app or writing unit tests.&lt;/p&gt;

&lt;!-- break --&gt;

&lt;p&gt;With IBAnalyzer, you&amp;#39;re currently able to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Find unimplemented outlets &amp;amp; actions in classes. Avoid crashes caused by exceptions, like a dreadful:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '
[&amp;lt;Sample.TwitterViewController 0x7fa84630a370&amp;gt; setValue:forUndefinedKey:]: this
 class is not key value coding-compliant for the key twitterImageView.'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find &lt;code&gt;@IBOutlet&lt;/code&gt;s and &lt;code&gt;@IBAction&lt;/code&gt;s defined in code but not connected to from nibs. No more:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/unnecessary-action@2x.png&quot; width=&quot;474&quot; alt=&quot;Unnecessary action&quot;&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/unnecessary-outlet@2x.png&quot; width=&quot;474&quot; alt=&quot;Unnecessary outlet&quot;&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All that thanks to its output, an example of which you can see below:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-&quot; data-lang=&quot;&quot;&gt;$ ./ibanalyzer ~/code/Sample/

TwitterViewController doesn't implement a required @IBAction named: loginButtonPressed:
TwitterViewController doesn't implement a required @IBOutlet named: twitterImageView
LoginViewController contains unused @IBAction named: onePasswordButtonTapped:
MessageCell contains unused @IBOutlet named: unreadIndicatorView
MessagesViewController contains unused @IBAction named: infoButtonPressed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;IBAnalyzer is in an early stage of life but I hope it will continue to get new types of warnings and become a useful tool for developers relying on Interface Builder.
You should give it a go. Its source is &lt;a href=&quot;https://github.com/fastred/IBAnalyzer&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 31 Jan 2017 15:00:00 +0100</pubDate>
        
        <link>https://holko.pl/2017/01/31/ibanalyzer/</link>
        
        <guid isPermaLink="false">http://holko.pl//2017/01/31/ibanalyzer/</guid>
      </item>
    
      <item>
        <title>Imagining Dependency Injection via Initializer with Storyboards</title>
        <description>&lt;p&gt;Storyboards, both their good and bad parts, are something I already &lt;a href=&quot;/2016/03/29/storyboards-and-alternatives/&quot;&gt;analyzed in the past&lt;/a&gt;. To recap, they just don’t feel like the first class citizen in the Swift world. Third party tools can help but only with &lt;em&gt;some&lt;/em&gt; of the issues, e.g. &lt;a href=&quot;https://github.com/AliSoftware/SwiftGen&quot;&gt;SwiftGen&lt;/a&gt; allows us to minimize the usage of “stringly typed” APIs.&lt;/p&gt;

&lt;p&gt;At the end of the day though &lt;a href=&quot;https://www.dzombak.com/blog/2016/09/Fixing-Storyboard-Segues--Only-Apple-Can-Do-This.html&quot;&gt;storyboards can be completely fixed only by Apple&lt;/a&gt;. So, let’s see how Apple could improve the biggest pain point there is – the lack of dependency injection via initializer.&lt;/p&gt;

&lt;!-- break --&gt;

&lt;h2 id=&quot;why-dependency-injection-via-initializer-is-important&quot;&gt;Why Dependency Injection via Initializer Is Important&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_injection&quot;&gt;Dependency Injection&lt;/a&gt; (or &lt;em&gt;passing stuff between objects&lt;/em&gt;) is a commonly used design pattern. There are two popular ways of injecting dependencies in Swift:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Initializer Injection&lt;/strong&gt; – dependencies are passed to an initializer. Properties using them can be declared as non-optional constants:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;let dependency: SomeType&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Setter Injection&lt;/strong&gt; – dependencies are provided after the initialization time. Properties storing them have to be variables, either optional or with an implicitly unwrapped optional attribute:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;var dependency: SomeType?&lt;/code&gt; or&lt;/li&gt;
&lt;li&gt;&lt;code&gt;var dependency: SomeType!&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest advantage of the initializer injection is that it’s possible to confirm at the compile-time that all dependencies are set up properly. No need to run the app or tests to check that all the assumptions are met. This turns out to be a huge benefit in a large codebase!&lt;/p&gt;

&lt;p&gt;All is good except that we &lt;em&gt;can’t&lt;/em&gt; use initializer injection with storyboards. A view controller with a view defined in a storyboard is initialized this way:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;storyboard&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIStoryboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storyboard&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instantiateViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;withIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;detailsViewController&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We don’t call a view controller’s initializer directly, its instance is created for us by a &lt;code&gt;UIStoryboard&lt;/code&gt; object. We can only pass data to it after the initialization time.&lt;/p&gt;

&lt;h2 id=&quot;idea&quot;&gt;Idea&lt;/h2&gt;

&lt;p&gt;This problem has been bugging me for a long time. I recently came up to the conclusion that it can be divided into two cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;View controllers that are the destination of at least one segue&lt;/li&gt;
&lt;li&gt;View controllers being initialized only through &lt;code&gt;instantiateViewController(withIdentifier:)&lt;/code&gt; and &lt;code&gt;instantiateInitialViewController()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There’s not much that can be done about the first case. View controllers can be initialized and presented without any of our code being called, as it’s not mandatory to do anything in or even implement at all &lt;code&gt;prepare(for segue: UIStoryboardSegue, sender: Any?)&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So, let’s focus on the second case – the view controller initialization from code. What happens, in that case, is UIKit simply calling &lt;code&gt;init(coder:)&lt;/code&gt; on our view controller passing an &lt;code&gt;NSCoder&lt;/code&gt; instance to it. Seems like a dead end too. We can’t pass any instances along that path anyway, right?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/storyboard_view_controller_initialization@2x.png&quot; style=&quot;width: 100%; max-width:461px;&quot; class=&quot;center&quot; /&gt;
&lt;div class=&quot;image-caption&quot;&gt;Stack trace of the initialization triggered by &lt;code&gt;instantiateViewController(withIdentifier:)&lt;/code&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Well, what if we could reverse things a bit. &lt;strong&gt;Instead of letting a &lt;code&gt;UIStoryboard&lt;/code&gt; instance initialize a view controller for us, we could get an &lt;code&gt;NSCoder&lt;/code&gt; instance from it.&lt;/strong&gt; So, we would have something like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Hypothetical method, not present in UIKit. `decoder` has the type `NSCoder`.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storyboard&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;forViewControllerIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;detailsViewController&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, in our view controller we could have a new initializer:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DetailsViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dependency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SomeType&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coder&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dependency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SomeType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependency&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependency&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and initialize our view controller by calling that initializer directly (!)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;detailsViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DetailsViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dependency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dependency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That one initializer is not enough to satisfy the compiler, though. We would have to implement &lt;code&gt;init(coder:)&lt;/code&gt; too. If we simply called &lt;code&gt;super.init(coder: aDecoder)&lt;/code&gt; from within it, the compiler would now note that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Property &amp;#39;self.dependency&amp;#39; not initialized at super.init call&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we were sure that our view controller will not be used with segues, we could silence the error by putting &lt;code&gt;fatalError()&lt;/code&gt; in that initializer. Otherwise, we would have to set the value of the &lt;code&gt;dependency&lt;/code&gt; property without it being passed from the outside. That’s not always possible, though.&lt;/p&gt;

&lt;p&gt;If we were to tie the code with storyboards closer, we could introduce a protocol for view controllers that can’t be initialized through segues, e.g. &lt;code&gt;NotSegueInitializable&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;We presented a simple addition to &lt;code&gt;UIStoryboard&lt;/code&gt; class that could improve an important downside of that API. We weren’t able to confirm – not having access to UIKit’s source code – that this addition is indeed as simple as it seems.&lt;/p&gt;

&lt;p&gt;With that API and with avoidance of segues we would have storyboards that don’t exercise most of the issues pointed out in &lt;a href=&quot;/2016/03/29/storyboards-and-alternatives/&quot;&gt;“Storyboards and Their (Better) Alternatives.”&lt;/a&gt; Let’s hope that this is something Apple is currently working on and that we’ll see better APIs for storyboards soon.&lt;/p&gt;
</description>
        <pubDate>Wed, 14 Dec 2016 16:15:00 +0100</pubDate>
        
        <link>https://holko.pl/2016/12/14/storyboards-dependency-injection/</link>
        
        <guid isPermaLink="false">http://holko.pl//2016/12/14/storyboards-dependency-injection/</guid>
      </item>
    
  </channel>
</rss>
