<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>devbits</title><link href="https://iankeen.tech/atom.xml" rel="self"/><link href="https://iankeen.tech/atom.xml"/><updated>2020-10-17T21:44:11-07:00</updated><id>https://iankeen.tech/</id><author><name>Ian Keen</name></author><entry><title>The missing Combine input type</title><link href="https://iankeen.tech/2020/08/03/the-missing-combine-input-type/index.html"/><updated>2020-08-02T17:00:00-07:00</updated><id>https://iankeen.tech/2020/08/03/the-missing-combine-input-type/index.html</id><content type="html"><![CDATA[ <p>Like most people I have been tinkering with SwiftUI and Combine lately. Mostly using the MVVM pattern since that's what I know best.One thing I miss from RxSwift that Combine doesn't seem to have is a dedicated <em>input only</em> type.In RxSwift there is a protocol called <code>Observer</code> with a provided concrete type of <code>AnyObserver<T></code>.An <code>Observer</code> only exposes ways to send values <em>in</em> but not subscribe to those changes elsewhere.</p><p>So why would this be useful? Well I'm a bit of a stickler for encapsulation.When I'm building, but more importantly debugging, my view models I like to know how data is flowing through them.With strict separation between inputs and outputs I know that any side effects are <em>only</em> triggered as a result of values coming out of the outputs.Likewise I also know that the only thing that could trigger those outputs are the <em>inputs</em> and reacting to the inputs is <em>only</em> able to happenfrom within the view model. This separation makes reasoning about the flow of data <em>much</em> easier, at least for me.</p><p>To dig into this concept, let's take a look at an example view model for authenticating a user:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="comment">//..</span><span class="none">

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="comment">//...</span><span class="none">
    }
}
</span></code></pre><h2>Outputs</h2><p>To represent outputs Combine gives us a <code>Publisher</code> type. We can subscribe to them and use them to make our apps do things.At the end of a <code>Publisher</code> you will eventually find one or more <code>.sink { ... }</code> calls, these are where our side effects live.This includes things like updating the UI or saving information to a database.</p><p>Let's add an output we can use to perform a side effect based on the success or failure of an authentication attempt</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt;

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="comment">//...</span><span class="none">
    }
}
</span></code></pre><p>Here we have <code>signInResult</code> using the <code>Result</code> type as its output. When authentication is successful it will emit a <code>.success(Token)</code> value,when it fails it will output a <code>.failure(Error)</code> value.</p><p>So how do we go about <em>triggering</em> the work and eventually get a value from this output? We need an input!</p><h2>Inputs… ?</h2><p>But didn't we already decide Combine doesn't have any input types? It <em>does</em> have ways to model inputs, they just come with some baggage.</p><p>The types Combine gives us to send values are called <code>Subject</code>s. <em>But</em>, they are <em>both</em> input <em>and</em> output (<code>Publisher</code>).This means that while we can use them to trigger our authentication attempt we need to be careful about how we use them if we care about encapsulation.</p><p>Let's introduce a <code>Subject</code> and get our view model actually doing something:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt;

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signIn</span><span class="none"> = </span><span class="identifier">PassthroughSubject</span><span class="none">&lt;(</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">), </span><span class="type">Never</span><span class="none">&gt;()

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="identifier">signInResult</span><span class="none"> = </span><span class="identifier">signIn</span><span class="none">
            .</span><span class="identifier">flatMap</span><span class="none"> { </span><span class="identifier">input</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">API</span><span class="none">
                    .</span><span class="identifier">authenticate</span><span class="none">(</span><span class="identifier">input</span><span class="none">.</span><span class="identifier">username</span><span class="none">, </span><span class="identifier">input</span><span class="none">.</span><span class="identifier">password</span><span class="none">)
                    .</span><span class="identifier">materialize</span><span class="none">()
            }
            .</span><span class="identifier">eraseToAnyPublisher</span><span class="none">()
    }
}
</span></code></pre><p>A <code>PassthroughSubject</code> does exactly what it  says on the label.  It <em>passes</em> values <em>through</em> that it receives via it's <code>send</code> function fulfilling its function as an <em>input</em>. It then uses those values as the source for its function as a <code>Publisher</code>, or <em>output</em>.</p><p>Now we have defined an input we can use it to attempt to authenticate and, finally, emit the result through our output. Let's take a look at what some code using our view model might look like:</p><pre><code class="language-swift"><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewModel</span><span class="none"> = </span><span class="identifier">AuthViewModel</span><span class="none">()

</span><span class="identifier">viewModel</span><span class="none">
    .</span><span class="identifier">signInResult</span><span class="none">
    .</span><span class="identifier">sink</span><span class="none"> { </span><span class="identifier">result</span><span class="none"> </span><span class="keyword">in</span><span class="none">
        </span><span class="identifier">print</span><span class="none">(</span><span class="identifier">result</span><span class="none">) </span><span class="comment">// output: success(Token(value: &quot;foobar&quot;))</span><span class="none">
    }
    .</span><span class="identifier">store</span><span class="none">(</span><span class="identifier">in</span><span class="none">: &amp;</span><span class="identifier">cancellables</span><span class="none">)

</span><span class="identifier">viewModel</span><span class="none">.</span><span class="identifier">signIn</span><span class="none">.</span><span class="identifier">send</span><span class="none">((</span><span class="identifier">username</span><span class="none">: </span><span class="literal">&quot;iankeen&quot;</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="literal">&quot;super_secret_password&quot;</span><span class="none">)) </span><span class="comment">// input</span><span class="none">
</span></code></pre><p>Not bad, however remember <code>Subject</code>s are both input <em>and</em> output. This means we have also left the door open for code like this:</p><pre><code class="language-swift"><span class="identifier">viewModel</span><span class="none">
    .</span><span class="identifier">signIn</span><span class="none">
    .</span><span class="identifier">sink</span><span class="none"> { </span><span class="identifier">result</span><span class="none"> </span><span class="keyword">in</span><span class="none">
        </span><span class="identifier">somethingUnexpected</span><span class="none">(</span><span class="identifier">with</span><span class="none">: </span><span class="identifier">result</span><span class="none">)
    }
    .</span><span class="identifier">store</span><span class="none">(</span><span class="identifier">in</span><span class="none">: &amp;</span><span class="identifier">cancellables</span><span class="none">)
</span></code></pre><p>Consider the situation where you happen to be tracking down a bug that occurs when your users attempt to authenticate.Because we have exposed a <code>Subject</code> we have to check all the subscriptions to the <code>signInResult</code> output <em>but also</em> any subscriptions to the <code>signIn</code> input!This makes things harder than they should be…</p><p>Let's take a look at a simple approach to get our encapsulation back:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt;

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signIn</span><span class="none"> = </span><span class="identifier">PassthroughSubject</span><span class="none">&lt;(</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">), </span><span class="type">Never</span><span class="none">&gt;()

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="identifier">signInResult</span><span class="none"> = </span><span class="identifier">signIn</span><span class="none">
            .</span><span class="identifier">flatMap</span><span class="none"> { </span><span class="identifier">input</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">API</span><span class="none">
                    .</span><span class="identifier">authenticate</span><span class="none">(</span><span class="identifier">input</span><span class="none">.</span><span class="identifier">username</span><span class="none">, </span><span class="identifier">input</span><span class="none">.</span><span class="identifier">password</span><span class="none">)
                    .</span><span class="identifier">materialize</span><span class="none">()
            }
            .</span><span class="identifier">eraseToAnyPublisher</span><span class="none">()
    }

    </span><span class="comment">// MARK: - Public Functions</span><span class="none">
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">signIn</span><span class="none">(</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">) {
        </span><span class="identifier">signIn</span><span class="none">.</span><span class="identifier">send</span><span class="none">((</span><span class="identifier">username</span><span class="none">, </span><span class="identifier">password</span><span class="none">))
    }
}
</span></code></pre><p>Much better! We now have closed off the ability for unintended side effects by giving <code>signIn</code> a <code>private</code> access level.Consumers of the view model can now use the <code>signIn(username:password:)</code> function to perform an authentication attempt.</p><p>Now we could stop here and it would be perfectly fine, but having to maintain a <code>Subject</code> <em>and</em> a function bothers me justenough to potentially over-engineer an alternative… strap yourself in.</p><h2>Inputs!… for real this time</h2><p>What we want is a type that exposes a way to <em>send</em> values publicly, but <em>derive</em> streams using them internally.My first thought was to try using PropertyWrappers since we can take advantage of the <code>_value</code> syntax to gain the encapsulation we want:</p><pre><code class="language-swift"><span class="keyword">@propertyWrapper</span><span class="none">
</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Input</span><span class="none">&lt;</span><span class="identifier">Parameters</span><span class="none">&gt; {
    </span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">SendProxy</span><span class="none"> {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">send</span><span class="none">: (</span><span class="type">Parameters</span><span class="none">) -&gt; </span><span class="type">Void</span><span class="none">
    }

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">wrappedValue</span><span class="none">: </span><span class="type">Parameters</span><span class="none"> { </span><span class="identifier">fatalError</span><span class="none">(</span><span class="literal">&quot;Send values via the $projectedValue&quot;</span><span class="none">) }
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">projectedValue</span><span class="none">: </span><span class="type">SendProxy</span><span class="none"> { .</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">send</span><span class="none">: </span><span class="identifier">subject</span><span class="none">.</span><span class="identifier">send</span><span class="none">) }

    </span><span class="keyword">init</span><span class="none">() { }

    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">subject</span><span class="none"> = </span><span class="identifier">PassthroughSubject</span><span class="none">&lt;</span><span class="type">Parameters</span><span class="none">, </span><span class="type">Never</span><span class="none">&gt;()
}
</span></code></pre><p>There's a fair bit going on in this little snippet so let's unpack it quickly…</p><p>The reason I first thought PropertyWrappers might be a good solution is because they allow us to expose things differently.We can use the publicly visible members (<code>wrappedValue</code> and <code>projectedValue</code>) to expose the parameters for the input and a way to send them.We can them use the restricted members (the <code>_underscore</code> accessor) to give the enclosing type exclusive access to the <code>Subject</code>.</p><p>We don't really want the <code>wrappedValue</code> here, it's just a means to expose a generic parameter.The <code>projectedValue</code> exposes a <code>SendProxy</code> which is just a way for use to provide <em>only</em> the <code>send</code> function to code outside the view model.</p><p>Clear as mud? Let's take a look at how we might use this in our view model and hopefully it'll make sense:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt;

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">@</span><span class="type">Input</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">signIn</span><span class="none">: (</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">)

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="identifier">signInResult</span><span class="none"> = </span><span class="identifier">_signIn</span><span class="none"> </span><span class="comment">// underscore accessor let&apos;s us use the `Subject` exclusively</span><span class="none">
            .</span><span class="identifier">subject</span><span class="none">
            .</span><span class="identifier">flatMap</span><span class="none"> { </span><span class="identifier">input</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">API</span><span class="none">
                    .</span><span class="identifier">authenticate</span><span class="none">(</span><span class="identifier">input</span><span class="none">.</span><span class="identifier">username</span><span class="none">, </span><span class="identifier">input</span><span class="none">.</span><span class="identifier">password</span><span class="none">)
                    .</span><span class="identifier">materialize</span><span class="none">()
            }
            .</span><span class="identifier">eraseToAnyPublisher</span><span class="none">()
    }
}
</span></code></pre><p>We can now sue the following syntax to send values:</p><pre><code class="language-swift"><span class="identifier">viewModel</span><span class="none">.</span><span class="identifier">$signIn</span><span class="none">.</span><span class="identifier">send</span><span class="none">((</span><span class="identifier">username</span><span class="none">: </span><span class="literal">&quot;...&quot;</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="literal">&quot;...&quot;</span><span class="none">))
</span></code></pre><p>The PropertyWrapper itself is a little crazy, but the view model and the call site is a little cleaner I think.Unfortunately there is actually a pretty big downside to this approach, PropertyWrappers can't be enforced in protocols.</p><p>Consider this:</p><pre><code class="language-swift"><span class="keyword">protocol</span><span class="none"> </span><span class="identifier">AuthViewModelType</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt; { </span><span class="keyword">get</span><span class="none"> }

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">@</span><span class="type">Input</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">signIn</span><span class="none">: (</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">) { </span><span class="keyword">get</span><span class="none"> } </span><span class="comment">// Property &apos;signIn&apos; declared inside a protocol cannot have a wrapper</span><span class="none">
}
</span></code></pre><p>Since we can't enforce <code>@Input</code> it means code that only knows about the <code>AuthViewModelType</code> wouldn't have visibility to call the <code>$signIn.send</code>  function.</p><p>This is a bit of a show stopper. I don't usually use protocols for view models but for other Combine friendly dependencies I might create I want to be able to enforce strict input/outputs.</p><p>Take two, let's try using a concrete type:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">AnyConsumer</span><span class="none">&lt;</span><span class="identifier">Output</span><span class="none">&gt; {
    </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">subject</span><span class="none"> = </span><span class="identifier">PassthroughSubject</span><span class="none">&lt;</span><span class="type">Output</span><span class="none">, </span><span class="type">Never</span><span class="none">&gt;()

    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">send</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">value</span><span class="none">: </span><span class="type">Output</span><span class="none">) {
        </span><span class="identifier">subject</span><span class="none">.</span><span class="identifier">send</span><span class="none">(</span><span class="identifier">value</span><span class="none">)
    }
}
</span></code></pre><p>I'm calling this <code>AnyConsumer</code> because it feels like a nice parallel with <code>AnyPublisher</code>.  This type allows us to expose <em>just</em> the <code>send</code> function making this type <em>input only</em> just like we want;however, if we make the subject <code>private</code> nothing is going to be able to access it. It feels like we are stuck in a catch 22.</p><p>Let's go with it for now and update the rest of our code; first let's make our protocol enforce our strict input:</p><pre><code class="language-swift"><span class="keyword">protocol</span><span class="none"> </span><span class="identifier">AuthViewModelType</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt; { </span><span class="keyword">get</span><span class="none"> }

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">signIn</span><span class="none">: </span><span class="type">AnyConsumer</span><span class="none">&lt;(</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">)&gt; { </span><span class="keyword">get</span><span class="none"> }
}
</span></code></pre><p>The next step is to update our view model to conform to these changes:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none">: </span><span class="type">AuthViewModelType</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt;

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signIn</span><span class="none"> = </span><span class="identifier">AnyConsumer</span><span class="none">&lt;(</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">)&gt;()

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="identifier">signInResult</span><span class="none"> = </span><span class="identifier">signIn</span><span class="none">
            .</span><span class="identifier">subject</span><span class="none"> </span><span class="comment">// &apos;subject&apos; is inaccessible due to &apos;private&apos; protection level</span><span class="none">
            .</span><span class="identifier">flatMap</span><span class="none"> { </span><span class="identifier">input</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">API</span><span class="none">
                    .</span><span class="identifier">authenticate</span><span class="none">(</span><span class="identifier">input</span><span class="none">.</span><span class="identifier">username</span><span class="none">, </span><span class="identifier">input</span><span class="none">.</span><span class="identifier">password</span><span class="none">)
                    .</span><span class="identifier">materialize</span><span class="none">()
            }
            .</span><span class="identifier">eraseToAnyPublisher</span><span class="none">()
    }
}
</span></code></pre><p>Just as we expected, while we gained the encapsulation benefits of a strict input type the view model isn't able to access the underlying <code>Subject</code> to use the values coming in.</p><p>We need a way to expose thee <code>Subject</code> but <em>only</em> to our view model. As it turns out we can actually use PropertyWrappers again to accomplish that!</p><p>We can bring back our <code>@Input</code> PropertyWrapper in a new form. This time it will work <em>with</em> <code>AnyConsumer</code> to expose the <code>Subject</code> to the enclosing type but will be hidden from everything else.</p><p>Lets update <code>AnyConsumer</code> and see what that looks like:</p><pre><code class="language-swift"><span class="keyword">@propertyWrapper</span><span class="none">
</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Input</span><span class="none">&lt;</span><span class="identifier">Output</span><span class="none">&gt; {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">wrappedValue</span><span class="none">: </span><span class="type">AnyConsumer</span><span class="none">&lt;</span><span class="type">Output</span><span class="none">&gt;

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">subject</span><span class="none">: </span><span class="type">PassthroughSubject</span><span class="none">&lt;</span><span class="type">Output</span><span class="none">, </span><span class="type">Never</span><span class="none">&gt; { </span><span class="identifier">wrappedValue</span><span class="none">.</span><span class="identifier">subject</span><span class="none"> }
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">AnyConsumer</span><span class="none">&lt;</span><span class="identifier">Output</span><span class="none">&gt; {
    </span><span class="keyword">fileprivate</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">subject</span><span class="none"> = </span><span class="identifier">PassthroughSubject</span><span class="none">&lt;</span><span class="type">Output</span><span class="none">, </span><span class="type">Never</span><span class="none">&gt;()

    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">send</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">value</span><span class="none">: </span><span class="type">Output</span><span class="none">) {
        </span><span class="identifier">subject</span><span class="none">.</span><span class="identifier">send</span><span class="none">(</span><span class="identifier">value</span><span class="none">)
    }
}
</span></code></pre><p>Now we can Combine (pun intended) our <code>@Input</code> PropertyWrapper with our <code>AnyConsumer</code> to restrict access to each side of the underlying <code>Subject</code>.</p><p>We have exclusive access for the view model to read the input:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">AuthViewModel</span><span class="none">: </span><span class="type">AuthViewModelType</span><span class="none"> {
    </span><span class="comment">// MARK: - Outputs</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">signInResult</span><span class="none">: </span><span class="type">AnyPublisher</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">Token</span><span class="none">, </span><span class="type">Error</span><span class="none">&gt;, </span><span class="type">Never</span><span class="none">&gt;

    </span><span class="comment">// MARK: - Inputs</span><span class="none">
    </span><span class="keyword">@</span><span class="type">Input</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">signIn</span><span class="none"> = </span><span class="identifier">AnyConsumer</span><span class="none">&lt;(</span><span class="identifier">username</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="type">String</span><span class="none">)&gt;()

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">init</span><span class="none">() {
        </span><span class="identifier">signInResult</span><span class="none"> = </span><span class="identifier">_signIn</span><span class="none">
            .</span><span class="identifier">subject</span><span class="none">
            .</span><span class="identifier">flatMap</span><span class="none"> { </span><span class="identifier">input</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">API</span><span class="none">
                    .</span><span class="identifier">authenticate</span><span class="none">(</span><span class="identifier">input</span><span class="none">.</span><span class="identifier">username</span><span class="none">, </span><span class="identifier">input</span><span class="none">.</span><span class="identifier">password</span><span class="none">)
                    .</span><span class="identifier">materialize</span><span class="none">()
            }
            .</span><span class="identifier">eraseToAnyPublisher</span><span class="none">()
    }
}
</span></code></pre><p>And, as before, anything using the view model can <em>only</em> see and call <code>.send</code>:</p><pre><code class="language-swift"><span class="identifier">viewModel</span><span class="none">.</span><span class="identifier">signIn</span><span class="none">.</span><span class="identifier">send</span><span class="none">((</span><span class="identifier">username</span><span class="none">: </span><span class="literal">&quot;...&quot;</span><span class="none">, </span><span class="identifier">password</span><span class="none">: </span><span class="literal">&quot;...&quot;</span><span class="none">))
</span></code></pre><h2>Wrap up</h2><p>So after all that we have ended up with something that allows us to nicely encapsulate access to two sides of a <code>Subject</code>.Is the extra abstraction worth it over our original private subject/function solution? There are a couple of nice advantages our final solution has that I can think of</p><p>Less typing: that's always a nice win. Using <code>AnyConsumer</code> we  don't have to maintain a private subject as well as an additional function to get into the <code>send</code> function.</p><p>An explicit type: having this not only draws a nice parallel with other output types like <code>AnyPublisher</code> but it gives us an anchor point for things like UI bindings.Think about how you might write a button binding today:</p><pre><code class="language-swift"><span class="identifier">someButton</span><span class="none">.</span><span class="identifier">combine</span><span class="none">.</span><span class="identifier">tap</span><span class="none"> </span><span class="comment">// example tap publisher</span><span class="none">
    .</span><span class="identifier">sink</span><span class="none"> { [</span><span class="identifier">unowned</span><span class="none"> </span><span class="keyword">self</span><span class="none">] </span><span class="keyword">in</span><span class="none">
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">viewModel</span><span class="none">.</span><span class="identifier">signIn</span><span class="none">()
    }
</span></code></pre><p>Using  <code>AnyConsumer</code> we could rewrite this subtly:</p><pre><code class="language-swift"><span class="identifier">someButton</span><span class="none">.</span><span class="identifier">combine</span><span class="none">.</span><span class="identifier">tap</span><span class="none">
    .</span><span class="identifier">bind</span><span class="none">(</span><span class="identifier">to</span><span class="none">: </span><span class="identifier">viewModel</span><span class="none">.</span><span class="identifier">signIn</span><span class="none">)
    .</span><span class="identifier">store</span><span class="none">(</span><span class="identifier">in</span><span class="none">: &amp;</span><span class="identifier">cancellables</span><span class="none">)
</span></code></pre><p>The change is minor but again it's slightly more concise and we can remove the burden of things like managing memory semantics and capture lists from our users.</p><p>That's all I have for now, but I'd love to hear any thoughts on this :)</p> ]]></content></entry><entry><title>Cross View Animations with matchedGeometryEffect</title><link href="https://iankeen.tech/2020/07/03/cross-view-animations-with-matchedgeometryeffect/index.html"/><updated>2020-07-02T17:00:00-07:00</updated><id>https://iankeen.tech/2020/07/03/cross-view-animations-with-matchedgeometryeffect/index.html</id><content type="html"><![CDATA[ <p>WWDC this year gave us a ton of new things to play with, SwiftUI being front and center.A number of new <code>@propertyWrapper</code>s were introduced, one I found particularly interesting was <code>@Namespace</code>.</p><p>This property wrapper can be used in conjunction with an identifier and the view modifier named <code>matchedGeometryEffect</code> to coordinate the animation of a part of the screen when updates occur.This was in <a href="https://developer.apple.com/videos/play/wwdc2020/10041/">Whats new in SwiftUI</a> around the 19minute mark.</p><p>Unfortunately the example was super brief and only showed moving an element from within the same view body.</p><p>Let's quickly recap with an example, firstly <em>without</em> <code>@Namespace</code> and <code>matchedGeometryEffect</code>:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">MyView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">State</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">left</span><span class="none"> = </span><span class="keyword">true</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">VStack</span><span class="none"> {
            </span><span class="identifier">Button</span><span class="none">(</span><span class="literal">&quot;Toggle&quot;</span><span class="none">, </span><span class="identifier">action</span><span class="none">: { </span><span class="identifier">withAnimation</span><span class="none"> { </span><span class="identifier">left</span><span class="none">.</span><span class="identifier">toggle</span><span class="none">() } })
            </span><span class="identifier">HStack</span><span class="none"> {
                </span><span class="keyword">if</span><span class="none"> </span><span class="identifier">left</span><span class="none"> {
                    </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">red</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                    </span><span class="identifier">Spacer</span><span class="none">()

                } </span><span class="keyword">else</span><span class="none"> {
                    </span><span class="identifier">Spacer</span><span class="none">()
                    </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">blue</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                }
            }
            .</span><span class="identifier">padding</span><span class="none">()
        }
    }
}
</span></code></pre><p>The result looks like this:</p><p><img title="" src="/Resources/cross_view_animations_with_matchedgeometryeffect/001.gif"></p><p>As you can see using <code>withAnimation</code> around the state change gives us a nice fade by default.Now let's see what happens when we add <code>@Namespace</code> and <code>matchedGeometryEffect</code>:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">MyView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">State</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">left</span><span class="none"> = </span><span class="keyword">true</span><span class="none">
    </span><span class="keyword">@</span><span class="type">Namespace</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none"> </span><span class="comment">// 1) Add namespace</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">VStack</span><span class="none"> {
            </span><span class="identifier">Button</span><span class="none">(</span><span class="literal">&quot;Toggle&quot;</span><span class="none">, </span><span class="identifier">action</span><span class="none">: { </span><span class="identifier">withAnimation</span><span class="none"> { </span><span class="identifier">left</span><span class="none">.</span><span class="identifier">toggle</span><span class="none">() } })
            </span><span class="identifier">HStack</span><span class="none"> {
                </span><span class="keyword">if</span><span class="none"> </span><span class="identifier">left</span><span class="none"> {
                    </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">red</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                        .</span><span class="identifier">matchedGeometryEffect</span><span class="none">(</span><span class="identifier">id</span><span class="none">: </span><span class="literal">&quot;box&quot;</span><span class="none">, </span><span class="identifier">in</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">) </span><span class="comment">// 2) Add `matchedGeometryEffect` inside namespace</span><span class="none">
                    </span><span class="identifier">Spacer</span><span class="none">()

                } </span><span class="keyword">else</span><span class="none"> {
                    </span><span class="identifier">Spacer</span><span class="none">()
                    </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">blue</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                        .</span><span class="identifier">matchedGeometryEffect</span><span class="none">(</span><span class="identifier">id</span><span class="none">: </span><span class="literal">&quot;box&quot;</span><span class="none">, </span><span class="identifier">in</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">) </span><span class="comment">// 3) Same here, making sure they use the same `id`</span><span class="none">
                }
            }
            .</span><span class="identifier">padding</span><span class="none">()
        }
    }
}
</span></code></pre><p>SwiftUI now animates between these 2 <em>different</em> boxes seamlessly as though you were simply moving the <em>same</em> box.</p><p><img title="" src="/Resources/cross_view_animations_with_matchedgeometryeffect/002.gif"></p><h2>Animating across Views</h2><p>One thing that was not shown was how to perform animations like this <em>across</em> different views. For example what happens if we refactor our example like this:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">MyView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">State</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">left</span><span class="none"> = </span><span class="keyword">true</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">VStack</span><span class="none"> {
            </span><span class="identifier">Button</span><span class="none">(</span><span class="literal">&quot;Toggle&quot;</span><span class="none">, </span><span class="identifier">action</span><span class="none">: { </span><span class="identifier">withAnimation</span><span class="none"> { </span><span class="identifier">left</span><span class="none">.</span><span class="identifier">toggle</span><span class="none">() } })
            </span><span class="keyword">if</span><span class="none"> </span><span class="identifier">left</span><span class="none"> { </span><span class="identifier">LeftView</span><span class="none">() }
            </span><span class="keyword">else</span><span class="none"> { </span><span class="identifier">RightView</span><span class="none">() }
        }
    }
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">LeftView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">HStack</span><span class="none"> {
            </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">red</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
            </span><span class="identifier">Spacer</span><span class="none">()
        }
        .</span><span class="identifier">padding</span><span class="none">()
    }
}
</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">RightView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">HStack</span><span class="none"> {
            </span><span class="identifier">Spacer</span><span class="none">()
            </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">blue</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
        }
        .</span><span class="identifier">padding</span><span class="none">()
    }
}
</span></code></pre><p>Turns out integrating <code>@Namespace</code> and <code>matchedGeometryEffect</code> it's not immediately obvious, my first instinct was to just pass the <code>@Namespace</code> along like so:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">MyView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">State</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">left</span><span class="none"> = </span><span class="keyword">true</span><span class="none">
    </span><span class="keyword">@</span><span class="type">Namespace</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">VStack</span><span class="none"> {
            </span><span class="identifier">Button</span><span class="none">(</span><span class="literal">&quot;Toggle&quot;</span><span class="none">, </span><span class="identifier">action</span><span class="none">: { </span><span class="identifier">withAnimation</span><span class="none"> { </span><span class="identifier">left</span><span class="none">.</span><span class="identifier">toggle</span><span class="none">() } })
            </span><span class="keyword">if</span><span class="none"> </span><span class="identifier">left</span><span class="none"> { </span><span class="identifier">LeftView</span><span class="none">(</span><span class="identifier">namespace</span><span class="none">: </span><span class="identifier">_namespace</span><span class="none">) }
            </span><span class="keyword">else</span><span class="none"> { </span><span class="identifier">RightView</span><span class="none">(</span><span class="identifier">namespace</span><span class="none">: </span><span class="identifier">_namespace</span><span class="none">) }
        }
    }
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">LeftView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">Namespace</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">HStack</span><span class="none"> {
            </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">red</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                .</span><span class="identifier">matchedGeometryEffect</span><span class="none">(</span><span class="identifier">id</span><span class="none">: </span><span class="literal">&quot;box&quot;</span><span class="none">, </span><span class="identifier">in</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">)
            </span><span class="identifier">Spacer</span><span class="none">()
        }
        .</span><span class="identifier">padding</span><span class="none">()
    }
}
</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">RightView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">Namespace</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">HStack</span><span class="none"> {
            </span><span class="identifier">Spacer</span><span class="none">()
            </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">blue</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                .</span><span class="identifier">matchedGeometryEffect</span><span class="none">(</span><span class="identifier">id</span><span class="none">: </span><span class="literal">&quot;box&quot;</span><span class="none">, </span><span class="identifier">in</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">)
        }
        .</span><span class="identifier">padding</span><span class="none">()
    }
}
</span></code></pre><p>However this just resulted in the default fade animation...</p><p><img title="" src="/Resources/cross_view_animations_with_matchedgeometryeffect/001.gif"></p><p>The reason is <code>@Namespace</code> only has a single <code>init()</code> and it's <code>wrappedValue</code> is read-only.So by using the <code>@Namespace</code> property wrapper we are actually creating different instances in the left/right views rather than using the one we pass in.</p><p>However for this to work we still need to pass in the namespace since <code>matchedGeometryEffect</code> needs one. If we look at the namespace parameter of <code>matchedGeometryEffect</code> it actually wants a <code>Namespace.ID</code> which happens to be the <code>wrappedValue</code> from <code>@Namespace</code>. This means we should be able to just pass the <code>Namespace.ID</code> instead, let's try:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">MyView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">@</span><span class="type">State</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">left</span><span class="none"> = </span><span class="keyword">true</span><span class="none">
    </span><span class="keyword">@</span><span class="type">Namespace</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">VStack</span><span class="none"> {
            </span><span class="identifier">Button</span><span class="none">(</span><span class="literal">&quot;Toggle&quot;</span><span class="none">, </span><span class="identifier">action</span><span class="none">: { </span><span class="identifier">withAnimation</span><span class="none"> { </span><span class="identifier">left</span><span class="none">.</span><span class="identifier">toggle</span><span class="none">() } })
            </span><span class="keyword">if</span><span class="none"> </span><span class="identifier">left</span><span class="none"> { </span><span class="identifier">LeftView</span><span class="none">(</span><span class="identifier">namespace</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">) }
            </span><span class="keyword">else</span><span class="none"> { </span><span class="identifier">RightView</span><span class="none">(</span><span class="identifier">namespace</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">) }
        }
    }
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">LeftView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none">: </span><span class="type">Namespace</span><span class="none">.</span><span class="type">ID</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">HStack</span><span class="none"> {
            </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">red</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                .</span><span class="identifier">matchedGeometryEffect</span><span class="none">(</span><span class="identifier">id</span><span class="none">: </span><span class="literal">&quot;box&quot;</span><span class="none">, </span><span class="identifier">in</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">)
            </span><span class="identifier">Spacer</span><span class="none">()
        }
        .</span><span class="identifier">padding</span><span class="none">()
    }
}
</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">RightView</span><span class="none">: </span><span class="type">View</span><span class="none"> {
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">namespace</span><span class="none">: </span><span class="type">Namespace</span><span class="none">.</span><span class="type">ID</span><span class="none">

    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">body</span><span class="none">: </span><span class="keyword">some</span><span class="none"> </span><span class="type">View</span><span class="none"> {
        </span><span class="identifier">HStack</span><span class="none"> {
            </span><span class="identifier">Spacer</span><span class="none">()
            </span><span class="identifier">Color</span><span class="none">.</span><span class="identifier">blue</span><span class="none">.</span><span class="identifier">frame</span><span class="none">(</span><span class="identifier">width</span><span class="none">: </span><span class="literal">100</span><span class="none">, </span><span class="identifier">height</span><span class="none">: </span><span class="literal">100</span><span class="none">)
                .</span><span class="identifier">matchedGeometryEffect</span><span class="none">(</span><span class="identifier">id</span><span class="none">: </span><span class="literal">&quot;box&quot;</span><span class="none">, </span><span class="identifier">in</span><span class="none">: </span><span class="identifier">namespace</span><span class="none">)
        }
        .</span><span class="identifier">padding</span><span class="none">()
    }
}
</span></code></pre><p><img title="" src="/Resources/cross_view_animations_with_matchedgeometryeffect/002.gif"></p><p>Success!</p><h2>Recap</h2><p>Using these features you can create some fantastic interactions with <em>very little code</em>. The same interactions with <code>UIKit</code> would involve <em>numerous</em> additional types and fairly complex code to create the same transitions.</p><p>Remember that to 'link' elements with  <code>matchedGeometryEffect</code> you need to:</p><ul><li>Ensure they are in the same <code>Namespace</code> by using the same instance.</li><li>Ensure they have the same <code>id</code>.</li></ul><p>And SwiftUI will take care of the rest!</p> ]]></content></entry><entry><title>Container Coordinators</title><link href="https://iankeen.tech/2020/05/11/container-coordinators/index.html"/><updated>2020-05-10T17:00:00-07:00</updated><id>https://iankeen.tech/2020/05/11/container-coordinators/index.html</id><content type="html"><![CDATA[ <p>SwiftUI is the new hotness right now, however not everyone is willing or able to go 'all in' on it just yet. For those of us still working away under UIKit, I wanted to share a technique I have been using for a while now to deal with constructing a UI hierarchy and managing navigation.</p><h2>Coordinators</h2><p>You've likely all heard about, and possibly tried, <a href="https://khanlou.com/2015/01/the-coordinator/">Coordinators</a>, a fantastic pattern by <a href="https://twitter.com/khanlou">Soroush Khanlou</a>. I used this pattern myself for a long time. It solved the problem of decoupling navigation from View Controllers so that they could potentially be reused under any number of different scenarios.</p><p>As I used this pattern more and more I would often feel some recurring, nagging, issues. I began to notice things like:</p><ul><li>I was never able to settle on a single abstraction that I liked to use the pattern across any application... there were always subtle differences.</li><li>There was often state to manage with regard to adding and removing children as they execute ("sub" Coordinators).</li><li>This often meant you needed to know when a child Coordinator would be finished so you could clean them up.</li></ul><p>The more I thought about this I began to realize that each Coordinator not only managed a specific <a href="https://developer.apple.com/documentation/uikit/view_controllers">Container Controller</a> but that it's behaviour ended up copying its Containers behaviour. It felt like I was reinventing something that already existed over and over. Navigation based Coordinators ended up mostly pushing things. Tab based Coordinators were mostly managing an array of child Coordinators.</p><p>I was essentially writing Coordinators to do the jobs that the UIKit Containers already do 🤔</p><h2>Container Controllers as Coordinators</h2><p>I decided to try subclassing Containers to act as Coordinators, and once I did something pretty cool happened...</p><ul><li>I no longer had to think about an abstraction: if I wanted a stack based Coordinator I simply subclassed <code>UINavigationController</code>. If I needed a tab based one I could subclass <code>UITabBarController</code> and load it up with my <code>UINavigationController</code> subclasses.</li><li>The state for managing the 'graph' is gone as the subclasses deal with this by design. Now all they contain are the functions for moving between View Controllers or other Containers.</li><li>I don't really care about when a flow is 'complete' anymore. When a ViewController is 'popped' from the stack, for example, it simply cleans itself up.</li></ul><p>I now found I was able to build each Coordinator, in isolation, and not have to think about how it interacted with other Coordinators.</p><p>Consider a simple app with a couple of tabs. A tab with a list of friends and a tab with a list of messages between you and those friends. Let's look at what this might look like using Containers as Coordinators.</p><p>First we have our View Controllers for the lists of friends and messages:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">FriendListViewController</span><span class="none">: </span><span class="type">UITableViewController</span><span class="none"> {
  </span><span class="comment">//..</span><span class="none">
}
</span><span class="keyword">class</span><span class="none"> </span><span class="identifier">MessageListViewController</span><span class="none">: </span><span class="type">UITableViewController</span><span class="none"> {
  </span><span class="comment">//..</span><span class="none">
}
</span></code></pre><p>We know that we will want stack based navigation for each tab so let's build our <code>UINavigationController</code> subclasses for each of them:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">FriendListNavigationController</span><span class="none">: </span><span class="type">UINavigationController</span><span class="none"> {
  </span><span class="keyword">init</span><span class="none">() {
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">nibName</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">bundle</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)

    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewController</span><span class="none"> = </span><span class="identifier">FriendListViewController</span><span class="none">()
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">title</span><span class="none"> = </span><span class="literal">&quot;Friends&quot;</span><span class="none">
    </span><span class="identifier">setViewControllers</span><span class="none">([</span><span class="identifier">viewController</span><span class="none">], </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">false</span><span class="none">)
  }
}

</span><span class="keyword">class</span><span class="none"> </span><span class="identifier">MessageListNavigationController</span><span class="none">: </span><span class="type">UINavigationController</span><span class="none"> {
  </span><span class="keyword">init</span><span class="none">() {
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">nibName</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">bundle</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)

    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewController</span><span class="none"> = </span><span class="identifier">MessageListViewController</span><span class="none">()
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">title</span><span class="none"> = </span><span class="literal">&quot;Messages&quot;</span><span class="none">
    </span><span class="identifier">setViewControllers</span><span class="none">([</span><span class="identifier">viewController</span><span class="none">], </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">false</span><span class="none">)
  }
}
</span></code></pre><p>Finally let's create our <code>UITabBarController</code> subclass to manage these:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">HomeTabController</span><span class="none">: </span><span class="type">UITabBarController</span><span class="none"> {
  </span><span class="keyword">init</span><span class="none">() {
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">nibName</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">bundle</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)

    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">users</span><span class="none"> = </span><span class="identifier">FriendListNavigationController</span><span class="none">()
    </span><span class="identifier">users</span><span class="none">.</span><span class="identifier">tabBarItem</span><span class="none"> = .</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">title</span><span class="none">: </span><span class="literal">&quot;Users&quot;</span><span class="none">, </span><span class="identifier">image</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">selectedImage</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)

    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">messages</span><span class="none"> = </span><span class="identifier">MessageListNavigationController</span><span class="none">()
    </span><span class="identifier">messages</span><span class="none">.</span><span class="identifier">tabBarItem</span><span class="none"> = .</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">title</span><span class="none">: </span><span class="literal">&quot;Messages&quot;</span><span class="none">, </span><span class="identifier">image</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">selectedImage</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)

    </span><span class="identifier">setViewControllers</span><span class="none">([</span><span class="identifier">users</span><span class="none">, </span><span class="identifier">messages</span><span class="none">], </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">false</span><span class="none">)
  }
}
</span></code></pre><p>If we now compose all of these layers together at run time we end up with an application that looks something like:</p><table><tr><th>Friends Tab</th><th>Messages Tab</th></tr><tr><td><img src="/Resources/container_coordinators/tab1.png"></td><td><img src="/Resources/container_coordinators/tab2.png"></td></tr></table>
<p>Notice that the <code>UINavigationController</code> related properties like <code>title</code> are handled by the <code>UINavigationController</code> subclasses and the <code>UITabBarController</code> related properties like <code>tabItem</code> are handled by the <code>UITabbarController</code> subclasses. This further decouples the individual View Controllers from the context they are being shown in.</p><p>Now that we have decoupled the hierarchy, what about navigation?</p><h2>The Responder Chain</h2><p>Unless you have a lot of experience with building for macOS you may have never <em>explicitly</em> used the <a href="https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_the_responder_chain_to_handle_events">Responder Chain</a> on iOS, except perhaps the <code>becomeFirstResponder()</code> function.</p><p>The Responder Chain is based on the class <code>UIResponder</code>. All the common UIKit objects you use inherit from this including <code>UIViewController</code>, <code>UIView</code>, <code>UIWindow</code>, and <code>UIApplication</code>. There are a lot of interesting members on this class but for our needs we are only interested in one:</p><pre><code class="language-swift"><span class="keyword">open</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">next</span><span class="none">: </span><span class="type">UIResponder</span><span class="none">? { </span><span class="keyword">get</span><span class="none"> }
</span></code></pre><p>Why is this one so interesting? Well, if all the items in our view hierarchy implement this it means we basically have a linked list. From any place in the hierarchy we can walk back up the Responder Chain all the way back to the <code>UIApplicationDelegate</code>.</p><p>By default, <code>next</code> will be:</p><ul><li>For <code>UIView</code>s, the <code>superview</code> or the <code>UIViewController</code> if it's the root view.</li><li>For <code>UIViewController</code>s, the containing/presenting view controller or the <code>UIWindow</code> if it's the root View Controller.</li><li>For <code>UIWindow</code>s, the <code>UIApplication</code></li><li>For <code>UIApplication</code>s, the <code>UIApplicationDelegate</code> if it is a <code>UIResponder</code></li></ul><p>We can even alter the chain by overriding <code>next</code> in our subclasses if needed! This gives us an incredibly powerful mechanism, so how can we take advantage?</p><h2>Tapping into UIResponder</h2><p>Now we know <em>what</em> the Responder Chain is; how can we use it for navigation? Well it turns out that we can extend <code>UIResponder</code> with our own custom functions. We can then override these functions elsewhere to perform whatever action is required.</p><p>Knowing this, let's look at how we can navigate to a friend's details when a user taps one from the list. First let's add our <code>UIResponder</code> extension</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">UIResponder</span><span class="none"> {
  </span><span class="keyword">@objc</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">Friend</span><span class="none">) {
    </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">next</span><span class="none"> = </span><span class="identifier">next</span><span class="none"> </span><span class="keyword">else</span><span class="none"> {
      </span><span class="comment">// This gives us a nice piece of diagnostic information in the event</span><span class="none">
      </span><span class="comment">// this action travels along the chain and isn&apos;t handled by anything</span><span class="none">
      </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">print</span><span class="none">(</span><span class="literal">&quot;⚠️ Unhandled action: </span><span class="none">\</span><span class="none">(</span><span class="keyword">#function</span><span class="none">)</span><span class="literal">, Last responder: </span><span class="none">\</span><span class="none">(</span><span class="keyword">self</span><span class="none">)</span><span class="literal">&quot;</span><span class="none">)
    }

    </span><span class="identifier">next</span><span class="none">.</span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="identifier">friend</span><span class="none">)
  }
}
</span></code></pre><p>This will expose a <code>selectedFriend(_:)</code> function to <em>anything</em> on the Responder Chain. Now that we have a way to send the message, let's do so from our friends list:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">FriendListViewController</span><span class="none">: </span><span class="type">UITableViewController</span><span class="none"> {
  </span><span class="comment">//..</span><span class="none">

  </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">tableView</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">tableView</span><span class="none">: </span><span class="type">UITableView</span><span class="none">, </span><span class="identifier">didSelectRowAt</span><span class="none"> </span><span class="identifier">indexPath</span><span class="none">: </span><span class="type">IndexPath</span><span class="none">) {
    </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="identifier">data</span><span class="none">[</span><span class="identifier">indexPath</span><span class="none">.</span><span class="identifier">row</span><span class="none">])
  }
}
</span></code></pre><p>Finally we need something to act on this message, so let's do that from our <code>UINavigationController</code> subclass:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">FriendListNavigationController</span><span class="none">: </span><span class="type">UINavigationController</span><span class="none"> {
  </span><span class="comment">//..</span><span class="none">

  </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">Friend</span><span class="none">) {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewController</span><span class="none"> = </span><span class="identifier">FriendDetailsViewController</span><span class="none">(</span><span class="identifier">friend</span><span class="none">: </span><span class="identifier">friend</span><span class="none">)
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">title</span><span class="none"> = </span><span class="identifier">friend</span><span class="none">.</span><span class="identifier">name</span><span class="none">
    </span><span class="identifier">pushViewController</span><span class="none">(</span><span class="identifier">viewController</span><span class="none">, </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">true</span><span class="none">)
  }
}
</span></code></pre><p>And that's it! Our <code>FriendListViewController</code> sends a message out that a certain friend needs to be shown and nothing more. The message travels along the responder chain until it hits our <code>UINavigationController</code> subclass that contains the override. Our subclass then constructs the appropriate View Controller and pushes it on to the stack.</p><p>We have performed all the work of a Coordinator without re-inventing the wheel.</p><h2>Reusing View Controllers</h2><p>After putting in the work to decouple our View Controllers, how we can leverage this new pattern in our app? Let's look at how we might reuse our friends list to select a friend to use when creating a new message.</p><p>You can think of the Containers as the things that provide <em>context</em> or <em>meaning</em> to a View Controllers actions. Our existing <code>FriendListNavigationController</code> translates our <code>selectedFriend</code> action into showing a friends details on the current stack. The context here being the 'friends tab'.</p><p>For this feature we have a new context, so let's create a new Container to deal with it:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">NewMessageNavigationController</span><span class="none">: </span><span class="type">UINavigationController</span><span class="none"> {
  </span><span class="keyword">init</span><span class="none">() {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewController</span><span class="none"> = </span><span class="identifier">FriendListViewController</span><span class="none">()
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">title</span><span class="none"> = </span><span class="literal">&quot;Select Recipient&quot;</span><span class="none">
    </span><span class="identifier">setViewControllers</span><span class="none">([</span><span class="identifier">viewController</span><span class="none">], </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">false</span><span class="none">)
  }

  </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">Friend</span><span class="none">) {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewController</span><span class="none"> = </span><span class="identifier">MessageComposerViewController</span><span class="none">(</span><span class="identifier">recipient</span><span class="none">: </span><span class="identifier">friend</span><span class="none">)
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">title</span><span class="none"> = </span><span class="identifier">friend</span><span class="none">.</span><span class="identifier">name</span><span class="none">
    </span><span class="identifier">setViewControllers</span><span class="none">([</span><span class="identifier">viewController</span><span class="none">], </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">true</span><span class="none">)
  }
}
</span></code></pre><p>So within this Container we start by showing the friends list, however this time when the user selects someone we will reset the stack to show the composer with the selected friend. We have used our existing friends list in a new context with very little code.</p><p>The only thing left to do is update our existing <code>MessageListNavigationController</code> Container to launch this new one:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">MessageListNavigationController</span><span class="none">: </span><span class="type">UINavigationController</span><span class="none"> {
  </span><span class="keyword">init</span><span class="none">() {
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">nibName</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">bundle</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)

    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">viewController</span><span class="none"> = </span><span class="identifier">MessageListViewController</span><span class="none">()
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">title</span><span class="none"> = </span><span class="literal">&quot;Messages&quot;</span><span class="none">
    </span><span class="identifier">viewController</span><span class="none">.</span><span class="identifier">navigationItem</span><span class="none">.</span><span class="identifier">rightBarButtonItem</span><span class="none"> = .</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">title</span><span class="none">: </span><span class="literal">&quot;New&quot;</span><span class="none">, </span><span class="identifier">style</span><span class="none">: .</span><span class="identifier">plain</span><span class="none">, </span><span class="identifier">target</span><span class="none">: </span><span class="keyword">self</span><span class="none">, </span><span class="identifier">action</span><span class="none">: </span><span class="keyword">#selector</span><span class="none">(</span><span class="identifier">composeNewMessage</span><span class="none">))
    </span><span class="identifier">setViewControllers</span><span class="none">([</span><span class="identifier">viewController</span><span class="none">], </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">false</span><span class="none">)
  }

  </span><span class="comment">//..</span><span class="none">

  </span><span class="keyword">@objc</span><span class="none"> </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">composeNewMessage</span><span class="none">() {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">container</span><span class="none"> = </span><span class="identifier">NewMessageNavigationController</span><span class="none">()
    </span><span class="identifier">present</span><span class="none">(</span><span class="identifier">container</span><span class="none">, </span><span class="identifier">animated</span><span class="none">: </span><span class="keyword">true</span><span class="none">, </span><span class="identifier">completion</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)
  }
}
</span></code></pre><p>We have updated the existing Container to attach a navigation item that launches our new message composer Container. Notice that the View Controllers are still bissfully unaware of how they are being used. It is the Containers that contain the details about how they all come together.</p><h2>Other interesting uses</h2><p>There are a few other interesting things the Responder Chain allows us to do.</p><h3>UIViews</h3><p>The fact that smaller components like <code>UIView</code> are <code>UIResponder</code>s means they can also participate in both sending and acting on our custom actions. A <code>UITableViewCell</code> subclass, for example, could call our <code>selectedFriend</code> action rather than the View Controller.</p><h3>Error Handling</h3><p>We could also use this as a way to unify error handling. For example you might consider an extension like:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">UIResponder</span><span class="none"> {
  </span><span class="keyword">@objc</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">handleError</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">error</span><span class="none">: </span><span class="type">Error</span><span class="none">) {
    </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">next</span><span class="none"> = </span><span class="identifier">next</span><span class="none"> </span><span class="keyword">else</span><span class="none"> {
      </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">print</span><span class="none">(</span><span class="literal">&quot;⚠️ Unhandled action: </span><span class="none">\</span><span class="none">(</span><span class="keyword">#function</span><span class="none">)</span><span class="literal">, Last responder: </span><span class="none">\</span><span class="none">(</span><span class="keyword">self</span><span class="none">)</span><span class="literal">&quot;</span><span class="none">)
    }

    </span><span class="identifier">next</span><span class="none">.</span><span class="identifier">handleError</span><span class="none">(</span><span class="identifier">error</span><span class="none">)
  }
}
</span></code></pre><p>Using this you can propagate errors from anywhere in your hierarchy back to a single place, like your <code>UIWindow</code>. Remember, the <code>UIWindow</code> can be a custom subclass just like your other Containers. You can present a generic error alert from there by overriding <code>handleError</code>.</p><h3>IBAction</h3><p>You can also add <code>@IBAction</code> to your <code>UIResponder</code> extensions; doing this will allow you to call them with <code>UIButton</code> taps with no code at all.</p><h3>Pay it forward!</h3><p>Finally don't forget you are dealing with a linked list! Just because you override one of these custom actions doesn't mean you have to end the chain. You might want to update your UI based on the fact that an error occured but not mess with the default handling you have in your <code>UIWindow</code> i.e.:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">MyViewController</span><span class="none">: </span><span class="type">UIViewController</span><span class="none"> {
  </span><span class="comment">//..</span><span class="none">

  </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">handleError</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">error</span><span class="none">: </span><span class="type">Error</span><span class="none">) {
    </span><span class="comment">// do something with this controllers appearance</span><span class="none">

    </span><span class="identifier">next</span><span class="none">?.</span><span class="identifier">handleError</span><span class="none">(</span><span class="identifier">error</span><span class="none">) </span><span class="comment">// pass the message along!</span><span class="none">
  }
}
</span></code></pre><h2>Caveats</h2><p>There are a few things you need to know if you would like to give this pattern a try.</p><h3>Swift</h3><p>This is an Objective-C mechanism (You may have noticed the <code>@objc</code> on our <code>UIResponder</code> extensions) and as such pure Swift code is not 'visible'. This means that, by default, you cannot pass along things like structs. To work around this we can box our Swift value in an Objective-C compatible object:</p><pre><code class="language-swift"><span class="keyword">public</span><span class="none"> </span><span class="keyword">class</span><span class="none"> </span><span class="identifier">ResponderBox</span><span class="none">: </span><span class="type">NSObject</span><span class="none"> {
  </span><span class="keyword">@nonobjc</span><span class="none"> </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none">: </span><span class="keyword">Any</span><span class="none">

  </span><span class="keyword">@nonobjc</span><span class="none"> </span><span class="keyword">public</span><span class="none"> </span><span class="keyword">init</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">value</span><span class="none">: </span><span class="type">T</span><span class="none">) {
    </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">value</span><span class="none"> = </span><span class="identifier">value</span><span class="none">
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">init</span><span class="none">()
  }

  </span><span class="keyword">@nonobjc</span><span class="none"> </span><span class="keyword">public</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none">: </span><span class="type">T</span><span class="none">.</span><span class="identifier">Type</span><span class="none"> = </span><span class="identifier">T</span><span class="none">.</span><span class="keyword">self</span><span class="none">) -&gt; </span><span class="type">T</span><span class="none"> {
    </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none"> = </span><span class="identifier">value</span><span class="none"> </span><span class="keyword">as</span><span class="none">? </span><span class="type">T</span><span class="none"> </span><span class="keyword">else</span><span class="none"> {
      </span><span class="identifier">fatalError</span><span class="none">(</span><span class="literal">&quot;Invalid value. Expected </span><span class="none">\</span><span class="none">(</span><span class="identifier">T</span><span class="none">.</span><span class="keyword">self</span><span class="none">)</span><span class="literal">, found </span><span class="none">\</span><span class="none">(</span><span class="identifier">type</span><span class="none">(</span><span class="identifier">of</span><span class="none">: </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">value</span><span class="none">)</span><span class="none">)</span><span class="literal">&quot;</span><span class="none">)
    }

    </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">value</span><span class="none">
  }
}
</span></code></pre><p>The unfortunate downside is that you'll need two <code>UIResponder</code> functions to make this work, taking our <code>selectedFriend</code> example we would need to update it to be:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">UIResponder</span><span class="none"> {
  </span><span class="keyword">@objc</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">ResponderBox</span><span class="none">) {
    </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">next</span><span class="none"> = </span><span class="identifier">next</span><span class="none"> </span><span class="keyword">else</span><span class="none"> {
      </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">print</span><span class="none">(</span><span class="literal">&quot;⚠️ Unhandled action: </span><span class="none">\</span><span class="none">(</span><span class="keyword">#function</span><span class="none">)</span><span class="literal">, Last responder: </span><span class="none">\</span><span class="none">(</span><span class="keyword">self</span><span class="none">)</span><span class="literal">&quot;</span><span class="none">)
    }

    </span><span class="identifier">next</span><span class="none">.</span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="identifier">friend</span><span class="none">)
  }
  </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">Friend</span><span class="none">) {
    </span><span class="identifier">selectedFriend</span><span class="none">(.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">friend</span><span class="none">))
  }
}
</span></code></pre><p>For the objects sending the action nothing changes. They can still call <code>selectedFriend(someFriendStruct)</code>. This function will then box up the struct and call out to the Objective-C compatible version.</p><p>For the objects wanting to act on this they would instead now override the <code>ResponderBox</code> version and extract the underlying struct with code like:</p><pre><code class="language-swift"><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">selectedFriend</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">ResponderBox</span><span class="none">) {
  </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">friend</span><span class="none">: </span><span class="type">Friend</span><span class="none"> = </span><span class="identifier">friend</span><span class="none">.</span><span class="identifier">value</span><span class="none">()

  </span><span class="comment">// use friend struct</span><span class="none">
}
</span></code></pre><p>This is a small inconveience, however the good news is you can't really mess this up. For sending it doesn't matter if you accidentally called the <code>ResponderBox</code> version as they both result in the action being sent along the Responder Chain. As for the overrides, you can only override the <code>ResponderBox</code> version thanks to the <code>@objc</code> annotation. If you tried to override the struct version the compiler would give you an error.</p><h3>Modals</h3><p>In the same way I only move forward using the Containers, I also only move backwards using them. One of the rules I follow is that "the Container that presented something should also dismiss it". However iOS throws a spanner in that by default because regardless of what does the presenting, the window's <code>rootViewController</code> is the value returned by the presented items <code>next</code> value.</p><p>What this means in our example is; Our presented <code>NewMessageNavigationController</code> would return the <code>HomeTabController</code> as its <code>next</code> responder instead of the <code>MessageListNavigationController</code> that presented it.</p><p>Luckily we can work around this also using <a href="https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html">View Controller Containment</a>:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">ResponderController</span><span class="none">: </span><span class="type">UIViewController</span><span class="none"> {
  </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">nextOverride</span><span class="none">: </span><span class="type">UIResponder</span><span class="none">
  </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">child</span><span class="none">: </span><span class="type">UIViewController</span><span class="none">

  </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">containing</span><span class="none">: </span><span class="type">UIViewController</span><span class="none">, </span><span class="identifier">nextResponder</span><span class="none">: </span><span class="type">UIResponder</span><span class="none">) {
    </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">nextOverride</span><span class="none"> = </span><span class="identifier">nextResponder</span><span class="none">
    </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">child</span><span class="none"> = </span><span class="identifier">containing</span><span class="none">
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">nibName</span><span class="none">: </span><span class="keyword">nil</span><span class="none">, </span><span class="identifier">bundle</span><span class="none">: </span><span class="keyword">nil</span><span class="none">)
  }
  </span><span class="keyword">required</span><span class="none"> </span><span class="keyword">init</span><span class="none">?(</span><span class="identifier">coder</span><span class="none">: </span><span class="type">NSCoder</span><span class="none">) {
    </span><span class="identifier">fatalError</span><span class="none">(</span><span class="literal">&quot;init(coder:) has not been implemented&quot;</span><span class="none">)
  }

  </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">viewDidLoad</span><span class="none">() {
    </span><span class="keyword">super</span><span class="none">.</span><span class="identifier">viewDidLoad</span><span class="none">()
    </span><span class="identifier">addChild</span><span class="none">(</span><span class="identifier">child</span><span class="none">)
    </span><span class="identifier">view</span><span class="none">.</span><span class="identifier">addSubview</span><span class="none">(</span><span class="identifier">child</span><span class="none">.</span><span class="identifier">view</span><span class="none">)

    </span><span class="identifier">child</span><span class="none">.</span><span class="identifier">view</span><span class="none">.</span><span class="identifier">frame</span><span class="none"> = </span><span class="identifier">view</span><span class="none">.</span><span class="identifier">bounds</span><span class="none">
    </span><span class="identifier">child</span><span class="none">.</span><span class="identifier">view</span><span class="none">.</span><span class="identifier">autoresizingMask</span><span class="none"> = [.</span><span class="identifier">flexibleWidth</span><span class="none">, .</span><span class="identifier">flexibleHeight</span><span class="none">]

    </span><span class="identifier">child</span><span class="none">.</span><span class="identifier">didMove</span><span class="none">(</span><span class="identifier">toParent</span><span class="none">: </span><span class="keyword">self</span><span class="none">)
  }
  </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">next</span><span class="none">: </span><span class="type">UIResponder</span><span class="none">? {
    </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">nextOverride</span><span class="none">
  }
}

</span><span class="keyword">extension</span><span class="none"> </span><span class="type">UIViewController</span><span class="none"> {
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">presentModal</span><span class="none">(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">viewControllerToPresent</span><span class="none">: </span><span class="type">UIViewController</span><span class="none">, </span><span class="identifier">animated</span><span class="none"> </span><span class="identifier">flag</span><span class="none">: </span><span class="type">Bool</span><span class="none">, </span><span class="identifier">completion</span><span class="none">: (() -&gt; </span><span class="type">Void</span><span class="none">)? = </span><span class="keyword">nil</span><span class="none">) {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">wrapper</span><span class="none"> = </span><span class="identifier">ResponderController</span><span class="none">(</span><span class="identifier">containing</span><span class="none">: </span><span class="identifier">viewControllerToPresent</span><span class="none">, </span><span class="identifier">nextResponder</span><span class="none">: </span><span class="keyword">self</span><span class="none">)
        </span><span class="identifier">present</span><span class="none">(</span><span class="identifier">wrapper</span><span class="none">, </span><span class="identifier">animated</span><span class="none">: </span><span class="identifier">flag</span><span class="none">, </span><span class="identifier">completion</span><span class="none">: </span><span class="identifier">completion</span><span class="none">)
    }
}
</span></code></pre><p>By overriding <code>next</code> we can maintain a Responder Chain that matches how we actually construct the UI hierarchy. All you need to do is use <code>presentModal(_:animated:completion:)</code> instead of the usual <code>present(_:animated:completion:)</code> function.</p><h2>Recap</h2><p>If you made it this far you probably have the idea but just to recap the rules I like to use when working with this pattern:</p><ul><li>Only Containers perform transitions; this includes push/pop, present/dismiss.</li><li>Containers configure properties on a View Controller relevant to their duties; this includes properties like <code>title</code>, <code>navigationItem</code>s and <code>tabBarItem</code>s</li></ul><p>Much like the more common Coordinator pattern this certainly isn't a silver bullet. However I have had really good success using it a number of apps so I'd love to hear your feedback if you decide to try it. There are some quirks but overall I find it easier to <em>lean into</em> UIKit rather than try to fight it.</p> ]]></content></entry><entry><title>Surviving RxSwift</title><link href="https://iankeen.tech/2019/03/20/surviving-rxswift/index.html"/><updated>2019-03-19T17:00:00-07:00</updated><id>https://iankeen.tech/2019/03/20/surviving-rxswift/index.html</id><content type="html"><![CDATA[ <p>Before I get started I need to mention that what follows are a set of best practices that I <em>personally</em> use to get the most out of RxSwift while avoiding a lot of the pitfalls people fall into. These are by no means presented as a set of hard rules that will work for everyone, though I do encourage you to try them.</p><h2>Why use Rx?</h2><p>If so many people struggle with it why use it at all? A perfectly valid question.</p><p>In our profession, there are so many ways to solve a problem and Rx is no different. Rx has a steep learning curve and it often isn't clear if one way of solving something is better than another. Figuring the subtleties out will take time, but it is very rewarding when you do.</p><p>The reason I use Rx is that, in my opinion, its greatest strength lies in the ability to take inputs from many sources, tame the often complex logic needed to combine them and leave you with outputs that update whenever the inputs do.</p><p>What this means is that, if you are following principles like SRP, you often don't need Rx for the individual, lower level components, but its power becomes quite clear in higher level ones.</p><p>With that in mind, let's get started...</p><h2>Use it sparingly</h2><p>The most problematic Rx codebases I have worked on and heard people complain about are the ones that have made or tried to make <em>every single part</em> reactive. The more Rx you use the bigger and scarier your stack traces are. Stepping through a long reactive chain is <em>hard</em> and the <code>.debug()</code> operator only gets you so far.</p><p>As I alluded to earlier, my solution to this is <em>only</em> using Rx in the higher level components such as view models and view controllers.</p><p>But... how do we make all these non-Rx things work in Rx?</p><h2>Wrap components in Rx</h2><p>We can build components, such as an API layer, using more widely understood paradigms like closures to deliver things asynchronously. For example:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">APIClient</span><span class="none"> {
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">perform</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">: </span><span class="type">APIOperation</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">operation</span><span class="none">: </span><span class="type">T</span><span class="none">, </span><span class="identifier">complete</span><span class="none">: </span><span class="keyword">@escaping</span><span class="none"> (</span><span class="type">Result</span><span class="none">&lt;</span><span class="type">T</span><span class="none">.</span><span class="type">Response</span><span class="none">&gt;) -&gt; </span><span class="type">Void</span><span class="none">) -&gt; </span><span class="type">Cancellable</span><span class="none"> {
        </span><span class="comment">//use URLSession to perform request and attempt conversion of data to T.Response</span><span class="none">
    }
}
</span></code></pre><p>To make this work nicely with Rx we only need a few lines of code:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">APIClient</span><span class="none">: </span><span class="type">ReactiveCompatible</span><span class="none"> { }

</span><span class="keyword">extension</span><span class="none"> </span><span class="type">Reactive</span><span class="none"> </span><span class="keyword">where</span><span class="none"> </span><span class="type">Base</span><span class="none"> == </span><span class="type">APIClient</span><span class="none"> {
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">perform</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">: </span><span class="type">APIOperation</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">operation</span><span class="none">: </span><span class="type">T</span><span class="none">) -&gt; </span><span class="type">Observable</span><span class="none">&lt;</span><span class="type">T</span><span class="none">.</span><span class="type">Response</span><span class="none">&gt; {
        </span><span class="keyword">return</span><span class="none"> .</span><span class="identifier">create</span><span class="none"> { </span><span class="identifier">observer</span><span class="none"> </span><span class="keyword">in</span><span class="none">
            </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">task</span><span class="none"> = </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">base</span><span class="none">.</span><span class="identifier">perform</span><span class="none">(</span><span class="identifier">operation</span><span class="none">) { </span><span class="identifier">result</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">switch</span><span class="none"> </span><span class="identifier">result</span><span class="none"> {
                </span><span class="keyword">case</span><span class="none"> .</span><span class="identifier">success</span><span class="none">(</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none">):
                    </span><span class="identifier">observer</span><span class="none">.</span><span class="identifier">onNext</span><span class="none">(</span><span class="identifier">value</span><span class="none">)
                    </span><span class="identifier">observer</span><span class="none">.</span><span class="identifier">onCompleted</span><span class="none">()
                </span><span class="keyword">case</span><span class="none"> .</span><span class="identifier">failure</span><span class="none">(</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">error</span><span class="none">):
                    </span><span class="identifier">observer</span><span class="none">.</span><span class="identifier">onError</span><span class="none">(</span><span class="identifier">error</span><span class="none">)
                }
            }
            </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">Disposables</span><span class="none">.</span><span class="identifier">create</span><span class="none">(</span><span class="identifier">with</span><span class="none">: </span><span class="identifier">task</span><span class="none">.</span><span class="identifier">cancel</span><span class="none">)
        }
    }
}
</span></code></pre><p>With this, our <code>APIClient</code> can now easily be used in Rx chains. So what is the benefit of doing it this way?</p><p>Debugging is now much easier, we can set breakpoints within our non-Rx code and step through without all the additional noise Rx adds to our stack traces. We can now also write tests using the standard XCTest frameworks. Finally, we have a much more portable component. There's nothing stopping us from using this same API layer in other apps that may not use Rx.</p><h2>You don't need most traits</h2><p>RxSwift provides a wide range of <a href="https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Traits.md">traits</a>. Traits are wrappers around a standard <code>Observable</code> that provide additional semantics/behaviours. This might sound great, we want to leverage Swifts' type system after all right? It's quite common to see code using a <code>Single</code> rather than an <code>Observable</code>  for the API layer example above.</p><p>The problem with these different traits is that they do not always compose well together. There are a number of custom extensions floating around to help translate between them. You can avoid jumping through all these hoops by simply sticking with a standard <code>Observable</code>. There's no downside to avoiding traits.</p><p>Keen-eyed readers will have spotted the "(most)" in the heading. There is an exception to this one! You 100% should be using RxCocoa traits like <code>Driver</code> when you expose values for your view to consume as well as <code>ControlEvent</code> or <code>ControlProperty</code> which you encounter when using properties like <code>UIButton.rx.tap</code>. This is because those traits are designed specifically to interact with your UI. They will ensure values are shared and that everything happens on the main thread.</p><h2>Avoid subjects</h2><p>There are a number of shifts you need to make in how you think about data when learning Rx. One of the biggest is learning to construct streams such that the values coming <em>out</em> of them are the result of combining and/or transforming the values being sent <em>in</em>. A simplistic way to think about streams is like a mapping function <code>(A) -> B</code>, or <code>(A, B) -> C</code></p><p>Quite often when that shift has not yet been made you will see code that falls back on subjects to bridge the gap. Subjects are objects in Rx that are both input <em>and</em> output. They can be subscribed to but also incoming values to be sent to them.</p><p>Let's look at one such example of a view model for performing a search:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">SearchViewModel</span><span class="none"> {
    </span><span class="comment">// MARK: - Input</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">searchText</span><span class="none"> = </span><span class="identifier">PublishSubject</span><span class="none">&lt;</span><span class="type">String</span><span class="none">&gt;()

    </span><span class="comment">// MARK: - Output</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">results</span><span class="none">: </span><span class="type">Driver</span><span class="none">&lt;[</span><span class="type">SearchResultViewModel</span><span class="none">]&gt;
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">resultCount</span><span class="none">: </span><span class="type">Driver</span><span class="none">&lt;</span><span class="type">String</span><span class="none">&gt;

    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">searchService</span><span class="none">: </span><span class="type">SearchService</span><span class="none">) {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">searchResults</span><span class="none"> = </span><span class="identifier">searchText</span><span class="none">
            .</span><span class="identifier">throttle</span><span class="none">(</span><span class="literal">0.3</span><span class="none">, </span><span class="identifier">scheduler</span><span class="none">: </span><span class="identifier">MainScheduler</span><span class="none">.</span><span class="identifier">instance</span><span class="none">)
            .</span><span class="identifier">distinctUntilChanged</span><span class="none">()
            .</span><span class="identifier">flatMapLatest</span><span class="none"> { </span><span class="identifier">query</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">searchService</span><span class="none">.</span><span class="identifier">search</span><span class="none">(</span><span class="identifier">query</span><span class="none">: </span><span class="identifier">query</span><span class="none">).</span><span class="identifier">catchErrorJustReturn</span><span class="none">([])
            }
            .</span><span class="identifier">asDriver</span><span class="none">(</span><span class="identifier">onErrorJustReturn</span><span class="none">: [])
            .</span><span class="identifier">startWith</span><span class="none">([])

        </span><span class="identifier">results</span><span class="none"> = </span><span class="identifier">searchResults</span><span class="none">.</span><span class="identifier">map</span><span class="none"> { </span><span class="identifier">results</span><span class="none"> </span><span class="keyword">in</span><span class="none">
            </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">results</span><span class="none">.</span><span class="identifier">map</span><span class="none"> { </span><span class="identifier">result</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">SearchResultViewModel</span><span class="none">(</span><span class="identifier">searchResult</span><span class="none">: </span><span class="identifier">result</span><span class="none">)
            }
        }

        </span><span class="identifier">resultCount</span><span class="none"> = </span><span class="identifier">searchResults</span><span class="none">.</span><span class="identifier">map</span><span class="none"> { </span><span class="literal">&quot;</span><span class="none">\</span><span class="none">(</span><span class="identifier">$0</span><span class="none">.</span><span class="identifier">count</span><span class="none">)</span><span class="literal"> result(s)&quot;</span><span class="none"> }
    }
}
</span></code></pre><p>On its own, this looks really quite straight forward. <code>searchText</code> receives some text and we use that to do our search. From that, we can define 2 other streams, one for our list of results and one for a string showing the count.</p><p>However, because <code>searchText</code> is both input <em>and</em> output we have accidentally introduced an additional output to our view model. There is no way for us to prevent something else from subscribing to <code>searchText</code> and executing other code. If this is something you need to do then you should either</p><ul><li>Subscribe directly to the underlying input source (i.e. the text field); or</li><li>Create another explicit output for this behaviour</li></ul><p>By not creating a clear separation between input and output it becomes harder to debug where values may be coming from. It's also harder to reason about what the inputs and outputs for your system actually are.</p><p>Now let's see how we might refactor the same view model to remove the use of subjects:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">SearchViewModel</span><span class="none"> {
    </span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Input</span><span class="none"> {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">searchText</span><span class="none">: </span><span class="type">Observable</span><span class="none">&lt;</span><span class="type">String</span><span class="none">&gt;
    }

    </span><span class="comment">// MARK: - Output</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">results</span><span class="none">: </span><span class="type">Driver</span><span class="none">&lt;[</span><span class="type">SearchResultViewModel</span><span class="none">]&gt;
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">resultCount</span><span class="none">: </span><span class="type">Driver</span><span class="none">&lt;</span><span class="type">String</span><span class="none">&gt;

    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">searchService</span><span class="none">: </span><span class="type">SearchService</span><span class="none">, </span><span class="identifier">inputs</span><span class="none">: </span><span class="type">Input</span><span class="none">) {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">searchResults</span><span class="none"> = </span><span class="identifier">inputs</span><span class="none">.</span><span class="identifier">searchText</span><span class="none">
            .</span><span class="identifier">throttle</span><span class="none">(</span><span class="literal">0.3</span><span class="none">, </span><span class="identifier">scheduler</span><span class="none">: </span><span class="identifier">MainScheduler</span><span class="none">.</span><span class="identifier">instance</span><span class="none">)
            .</span><span class="identifier">distinctUntilChanged</span><span class="none">()
            .</span><span class="identifier">flatMapLatest</span><span class="none"> { </span><span class="identifier">query</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">searchService</span><span class="none">.</span><span class="identifier">search</span><span class="none">(</span><span class="identifier">query</span><span class="none">: </span><span class="identifier">query</span><span class="none">).</span><span class="identifier">catchErrorJustReturn</span><span class="none">([])
            }
            .</span><span class="identifier">asDriver</span><span class="none">(</span><span class="identifier">onErrorJustReturn</span><span class="none">: [])
            .</span><span class="identifier">startWith</span><span class="none">([])

        </span><span class="identifier">results</span><span class="none"> = </span><span class="identifier">searchResults</span><span class="none">.</span><span class="identifier">map</span><span class="none"> { </span><span class="identifier">results</span><span class="none"> </span><span class="keyword">in</span><span class="none">
            </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">results</span><span class="none">.</span><span class="identifier">map</span><span class="none"> { </span><span class="identifier">result</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">SearchResultViewModel</span><span class="none">(</span><span class="identifier">searchResult</span><span class="none">: </span><span class="identifier">result</span><span class="none">)
            }
        }

        </span><span class="identifier">resultCount</span><span class="none"> = </span><span class="identifier">searchResults</span><span class="none">.</span><span class="identifier">map</span><span class="none"> { </span><span class="literal">&quot;</span><span class="none">\</span><span class="none">(</span><span class="identifier">$0</span><span class="none">.</span><span class="identifier">count</span><span class="none">)</span><span class="literal"> result(s)&quot;</span><span class="none"> }
    }
}
</span></code></pre><p>The changes here are incredibly subtle, we have required that the input is passed via the constructor. This change gives me more fine-grained control over what my inputs and outputs are. I now have a single starting point to search for bugs relating to both text coming in and search results going out.</p><blockquote><p>It's worth noting that there are, of course, other ways you can go about removing/encapsulating the subjects.</p></blockquote><p>Again, there are exceptions to this one too but I'm not going to go into that here… If you absolutely feel that you need to use subjects, at the very least ensure you are encapsulating them so they are not publicly exposed for any random code to interact with. I would, however, encourage you to try and avoid them if you can!</p><h2>Limit DisposeBags to View Controllers</h2><p>Another issue you will see before the shift I mentioned has been made is <code>DisposeBag</code>s in places they don't belong. A <code>DisposeBag</code> is something that holds subscriptions. Subscriptions are what you get when you use functions like <code>subscribe</code>, <code>drive</code> or <code>bind</code>. These subscriptions are also where your apps side-effects are contained.</p><p>These subscriptions should be limited to your view controllers. Other components like view models should not contain subscriptions because they should not contain side-effects.</p><p>Interestingly enough, this problem is quite often seen when subjects are also being misused, as mentioned above. It is common to see subscriptions calling functions like <code>onNext</code> directly. This is a sign that your stream outputs are not being modelled as transformations of their inputs.</p><p>As with the others, there are rare exceptions to this one too. If, for some reason, a stream does not have an output you may need a single private subscription to ensure the stream is enabled. However, as with the other exceptions, do your best to avoid this situation.</p><h2>Summary</h2><p>So to quickly sum up the tips:</p><ul><li>Limit Rx to higher level components like view models and view controllers.</li><li>Build lower level components without Rx then add Rx wrapper extensions.</li><li>Limit yourself to <code>Observable</code> and <code>Driver</code>.</li><li>Write your Rx without subjects as much as possible.</li><li><code>DisposeBag</code>s really only belong in view controllers.</li></ul><p>I would strongly suggest anyone who is new to Rx or is feeling overwhelmed by it to simplify their use with these tips. As you get more comfortable with Rx you will start to get a good sense of when and how these tips apply as well as when they don't.</p> ]]></content></entry><entry><title>Better Codable models through composition</title><link href="https://iankeen.tech/2019/03/01/better-codable-models-through-composition/index.html"/><updated>2019-02-28T16:00:00-08:00</updated><id>https://iankeen.tech/2019/03/01/better-codable-models-through-composition/index.html</id><content type="html"><![CDATA[ <p>Imagine we want to build an app to track books. The API we are building against provides JSON for authors and book which looks like:</p><pre><code>{
    "identifier": "A13424B6",
    "name": "Robert C. Martin"
}

{
    "identifier": "A161F15C",
    "title": "Clean Code",
    "authorIdentifier": "A13424B6"
}
</code></pre><p>Swifts <code>Codable</code> features enable us to quickly create matching models:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Author</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">identifier</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Book</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">identifier</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">title</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">authorIdentifier</span><span class="none">: </span><span class="type">String</span><span class="none">
}
</span></code></pre><p>Thanks to <code>Codable</code> this is all we have to do to get JSON mapping to type-safe models for free!</p><p>There are, however, a couple of subtle issues that could cause problems as we progress. The <code>identifier</code>s are defined as <code>String</code>s. This isn't <em>wrong</em> but it could lead to a scenario like:</p><pre><code class="language-swift"><span class="keyword">func</span><span class="none"> </span><span class="identifier">allBooks</span><span class="none">(</span><span class="identifier">by</span><span class="none"> </span><span class="identifier">authorIdentifier</span><span class="none">: </span><span class="type">String</span><span class="none">) -&gt; [</span><span class="type">Book</span><span class="none">] {
    </span><span class="comment">//.. lookup books by id</span><span class="none">
}

</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">bobsBooks</span><span class="none"> = </span><span class="identifier">allBooks</span><span class="none">(</span><span class="identifier">by</span><span class="none">: </span><span class="literal">&quot;Robert C. Martin&quot;</span><span class="none">) </span><span class="comment">// oops!</span><span class="none">
</span></code></pre><p>This would compile and although the call-site <em>seems</em> to read correctly it would never return anything because the function expects an authors identifier not their name. Let's look at a type we can use instead of <code>String</code> to improve the type-safety here.</p><h2>Identifier<T></h2><p>We can't change the fact that the server is sending us <code>String</code>s but we can change how those strings are represented locally using a wrapper and phantom-types.</p><p>Usually when we define a generic type like <code>Identifier<T></code> we also use that <code>T</code> elsewhere in the type, something like <code>let value: T</code>. However when the <code>T</code> is only present as part of the declaration it is called a phantom type.</p><p>What's the point then? Why make something generic if we aren't using the type? Well we actually <em>are</em> using the type, just not in the usual way. Let's take a look:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Identifier</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">&gt; {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none">: </span><span class="type">String</span><span class="none">
}
</span></code></pre><p>Updating our models to use this new type, they become:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Author</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">identifier</span><span class="none">: </span><span class="type">Identifier</span><span class="none">&lt;</span><span class="type">Author</span><span class="none">&gt;
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Book</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">identifier</span><span class="none">: </span><span class="type">Identifier</span><span class="none">&lt;</span><span class="type">Book</span><span class="none">&gt;
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">title</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">authorIdentifier</span><span class="none">: </span><span class="type">Identifier</span><span class="none">&lt;</span><span class="type">Author</span><span class="none">&gt;
}
</span></code></pre><p>and our function now becomes:</p><pre><code class="language-swift"><span class="keyword">func</span><span class="none"> </span><span class="identifier">allBooks</span><span class="none">(</span><span class="identifier">by</span><span class="none"> </span><span class="identifier">authorIdentifier</span><span class="none">: </span><span class="type">Identifier</span><span class="none">&lt;</span><span class="type">Author</span><span class="none">&gt;) -&gt; [</span><span class="type">Book</span><span class="none">] {
    </span><span class="comment">//.. lookup books by authorIdentifier.value</span><span class="none">
}

</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">bobsBooks</span><span class="none"> = </span><span class="identifier">allBooks</span><span class="none">(</span><span class="identifier">by</span><span class="none">: </span><span class="literal">&quot;Robert C. Martin&quot;</span><span class="none">) </span><span class="comment">// failure!! (the good kind)</span><span class="none">
</span></code></pre><p>We have now made it impossible to incorrectly pass a <code>String</code>. We <em>must</em> provide an <code>Identifier<Author></code> instead otherwise it will not compile even though they are all still <code>String</code>s underneath.</p><p>This is what makes phantom types so useful. In this instance we are adding type-safety to an ordinary <code>String</code> using a generic placeholder. We can now use <code>Identifier<T></code> for not only our <code>Book</code> and <code>Author</code> models but any other model with an identifier as well.</p><h2>Codable support</h2><p>There is a new problem our new <code>Identifier<T></code>  has introduced. <code>Codable</code>, by default, uses the same structure as the type. This means the JSON representation of an identifier would be:</p><pre><code>{"value": "A13424B6"}
</code></pre><p>This is wrong, we still want the JSON representation to be a <code>String</code> so it works seamlessly with our API. Let's fix the <code>Codable</code> behaviour:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">Identifier</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">: </span><span class="type">Decoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">value</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">String</span><span class="none">(</span><span class="identifier">from</span><span class="none">: </span><span class="identifier">decoder</span><span class="none">)
    }
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">to</span><span class="none"> </span><span class="identifier">encoder</span><span class="none">: </span><span class="type">Encoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">value</span><span class="none">.</span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">to</span><span class="none">: </span><span class="identifier">encoder</span><span class="none">)
    }
}
</span></code></pre><p>Now when we convert between the model and JSON it will be a regular <code>String</code> rather than a nested object.</p><h2>Adding new data to the API</h2><p>Listing books and authors is working really well. Now it's time to allow our users to submit new entries. The only problem is our API is responsible for determining the identifiers of new data so we want to send JSON containing everything <em>but</em> the object identifier.</p><p>There are different ways we could tackle this:</p><ul><li>We could maintain a separate model that excludes the <code>identifier</code>. This is tedious and fragile but perhaps we could leverage a codegen solution to help? This is a big dependency to add if you aren't already using one though.</li><li>We could provide a dummy identifier and remove it from the JSON before sending it to our API. This isn't very nice though, using dummy values in production code seems like something just begging to break and/or corrupt things.</li></ul><p>Since we are creating new types today let's look at another one that can be used to solve this problem.</p><h2>Identified<T></h2><p>What we need is a way to define two versions of our models. One with an <code>identifier</code> when data is sent down and one without an <code>identifier</code> when we send data up.</p><p>We can't use the type system to <em>remove</em> properties... but we can use it to <em>add</em> them.</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Identified</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">&gt; {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">identifier</span><span class="none">: </span><span class="type">Identifier</span><span class="none">&lt;</span><span class="type">T</span><span class="none">&gt;
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none">: </span><span class="type">T</span><span class="none">
}
</span></code></pre><p>Using this type we can remove the <code>identifier</code> property from our models.</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Author</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
}

</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Book</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">title</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">authorIdentifier</span><span class="none">: </span><span class="type">Identifier</span><span class="none">&lt;</span><span class="type">Author</span><span class="none">&gt;
}
</span></code></pre><p>We can then define the two version of a model we need. When we are receiving books from the API we can use <code>Identified<Book></code> for each instance. When we want to add a new book we simply use <code>Book</code> as-is.</p><p>Having a type like <code>Identified<T></code> gives us the flexibility we want without needing to maintain parallel models or hack out unwanted values before sending data.</p><h2>Codable support</h2><p>As with <code>Identifier<T></code> the default <code>Codable</code> behaviour for <code>Identified<T></code> would result in the wrong JSON:</p><pre><code>{
    "identifier": "A13424B6",
    "value": {
        "name": "Robert C. Martin"
    }
}
</code></pre><p>We need to fix the <code>Codable</code> behaviour so everything is still flattened when in it's JSON form:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">Identified</span><span class="none">: </span><span class="type">Codable</span><span class="none"> </span><span class="keyword">where</span><span class="none"> </span><span class="type">T</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">: </span><span class="type">Decoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">container</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">.</span><span class="identifier">container</span><span class="none">(</span><span class="identifier">keyedBy</span><span class="none">: </span><span class="identifier">AnyCodingKey</span><span class="none">.</span><span class="keyword">self</span><span class="none">)

        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">identifier</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decode</span><span class="none">(</span><span class="identifier">Identifier</span><span class="none">&lt;</span><span class="type">T</span><span class="none">&gt;.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: </span><span class="identifier">AnyCodingKey</span><span class="none">(</span><span class="identifier">stringValue</span><span class="none">: </span><span class="literal">&quot;identifier&quot;</span><span class="none">)!)
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">value</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">T</span><span class="none">.</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">from</span><span class="none">: </span><span class="identifier">decoder</span><span class="none">)
    }

    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">to</span><span class="none"> </span><span class="identifier">encoder</span><span class="none">: </span><span class="type">Encoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">container</span><span class="none"> = </span><span class="identifier">encoder</span><span class="none">.</span><span class="identifier">container</span><span class="none">(</span><span class="identifier">keyedBy</span><span class="none">: </span><span class="identifier">AnyCodingKey</span><span class="none">.</span><span class="keyword">self</span><span class="none">)

        </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">identifier</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: </span><span class="identifier">AnyCodingKey</span><span class="none">(</span><span class="identifier">stringValue</span><span class="none">: </span><span class="literal">&quot;identifier&quot;</span><span class="none">)!)
        </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">value</span><span class="none">.</span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">to</span><span class="none">: </span><span class="identifier">encoder</span><span class="none">)
    }
}
</span></code></pre><p>The <code>AnyCodingKey</code> type is used to allow us to dynamically decode certain parts of the data without needing all new types:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">AnyCodingKey</span><span class="none">: </span><span class="type">CodingKey</span><span class="none"> {
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">stringValue</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">intValue</span><span class="none">: </span><span class="type">Int</span><span class="none">?

    </span><span class="keyword">init</span><span class="none">?(</span><span class="identifier">intValue</span><span class="none">: </span><span class="type">Int</span><span class="none">) {
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">intValue</span><span class="none"> = </span><span class="identifier">intValue</span><span class="none">
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">stringValue</span><span class="none"> = </span><span class="literal">&quot;</span><span class="none">\</span><span class="none">(</span><span class="identifier">intValue</span><span class="none">)</span><span class="literal">&quot;</span><span class="none">
    }
    </span><span class="keyword">init</span><span class="none">?(</span><span class="identifier">stringValue</span><span class="none">: </span><span class="type">String</span><span class="none">) {
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">intValue</span><span class="none"> = </span><span class="keyword">nil</span><span class="none">
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">stringValue</span><span class="none"> = </span><span class="identifier">stringValue</span><span class="none">
    }
}
</span></code></pre><h2>The end!</h2><p>There are many ways to skin a cat, but hopefully this has shown a couple of interesting way to solve some common problems using wrapper types and some pretty nifty Swift features.</p><p>There are a lot of additions that can be made to improve the ergonomics of these types also such as:</p><ul><li><code>ExpressibleBy*</code> conformance</li><li>Supporting values other than <code>String</code></li></ul><p>But I'll leave these as an exercise for the reader 🤘</p><p>You can grab a playground with all the code <a href="/Resources/better_codable_models_through_composition/CodableComposition.zip">here</a></p><p>If you have any feedback feel free to reach out!</p> ]]></content></entry><entry><title>Omitting Codable properties</title><link href="https://iankeen.tech/2018/06/29/omitting-codable-properties/index.html"/><updated>2018-06-28T17:00:00-07:00</updated><id>https://iankeen.tech/2018/06/29/omitting-codable-properties/index.html</id><content type="html"><![CDATA[ <p><code>Codable</code> was a pretty great addition to Swift, among other things it can drastically reduce the amount of code needed when working with a REST API. This magical feature can quickly become frustrating however when you need a model that isn't a 1:1 match with the incoming data.</p><p>One example might be that you have some additional data you want to add to your model that can only be created on device. There are a couple of options, you might have server/client representations of the model and convert one to the other. Alternatively you could just make the property optional.</p><p>The former may not be an option, if you have a large number of properties that can be painful to maintain for the sake of 1-2 client side differences. This makes the latter seem more desirable but it requires you make the type conform to <code>Codable</code> also... or does it?</p><p>Turns out you can actually skip certain properties, and you don't actually need to make them <code>Codable</code> at all!</p><h2>Example</h2><p>Lets say you have a <code>User</code> model that you will receive from your server, but you also have some <code>ClientData</code> that your app might want to add afterwards, but never get from, or send to, the server.</p><p>All you need to do is define a custom <code>CodingKey</code> which omits the properties you want left out of encoding and decoding <em>and</em> give it a default value, like so:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">User</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
   </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">enum</span><span class="none"> </span><span class="identifier">CodingKeys</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="type">CodingKey</span><span class="none"> {
      </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">id</span><span class="none">, </span><span class="identifier">name</span><span class="none">, </span><span class="identifier">age</span><span class="none">
   }

   </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">id</span><span class="none">: </span><span class="type">String</span><span class="none">
   </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
   </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">age</span><span class="none">: </span><span class="type">Int</span><span class="none">
   </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">clientData</span><span class="none">: </span><span class="type">ClientData</span><span class="none">? = </span><span class="keyword">nil</span><span class="none">
}
</span></code></pre><h2>That's it!</h2><p>You can now encode an instance of <code>User</code> and the <code>clientData</code> won't be part of the resulting <code>Data</code>. Conversely when you decode incoming data <code>clientData</code> will simply use the default value.</p><p>Pretty simple right? - it's generally a better idea to model your data as strictly as possible... for example if <code>clientData</code> is required then this may not be ideal - but its a handy trick when you need it.</p><p>Big thanks to <a href="https://twitter.com/christinamltn">Christina Moulton</a> for teaching me this trick 🤘</p> ]]></content></entry><entry><title>Type safe temporary models</title><link href="https://iankeen.tech/2018/06/05/type-safe-temporary-models/index.html"/><updated>2018-06-04T17:00:00-07:00</updated><id>https://iankeen.tech/2018/06/05/type-safe-temporary-models/index.html</id><content type="html"><![CDATA[ <p>Recently I had to build a system to onboard users. This meant collecting different pieces of information over a number of screens. We are also utilizing A/B testing which means not only can the order of screens change, but certain pieces of information may be collected by a single screen or broken up across many.</p><p>The data I want to end up with looks something like:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">User</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">firstName</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">lastName</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">age</span><span class="none">: </span><span class="type">Int</span><span class="none">?
}
</span></code></pre><p>There are multiple ways to go about collecting this data, I could simply give each screen an optional property:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">FirstNameViewController</span><span class="none">: </span><span class="type">UIViewController</span><span class="none"> {
    </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">firstName</span><span class="none">: </span><span class="type">String</span><span class="none">?

    </span><span class="comment">// ...</span><span class="none">
}
</span></code></pre><p>This would get the job done, but there are a few problems to overcome...</p><ul><li>What about the A/B testing? We would very quickly end up with our screens having a number of the same optional properties.</li><li>How do we keep track of and consolidate all of these properties at the end?</li></ul><p>An alternate approach would be to have a second version of our model with optional properties, such as:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">PartialUser</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">firstName</span><span class="none">: </span><span class="type">String</span><span class="none">?
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">lastName</span><span class="none">: </span><span class="type">String</span><span class="none">?
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">age</span><span class="none">: </span><span class="type">Int</span><span class="none">?
}
</span></code></pre><p>This is an improvement, we now have all the pieces in one place. We can create a <code>User.init</code> that accepts this model to produce a complete <code>User</code> instance for us:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">User</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">partial</span><span class="none">: </span><span class="type">PartialUser</span><span class="none">) {
        </span><span class="comment">// ...</span><span class="none">
    }
}
</span></code></pre><p>However it comes with it own set of problems...</p><ul><li>We have to keep it in sync with the 'real' model</li><li>This <code>init</code> can look a little messy having to deal with both required and optional properties</li><li>What do we do when a required value is missing?</li></ul><p>It's worth noting that neither of these solution scale well for other uses, there is a lot of associated boilerplate that we would need to replicate for each specific use case.</p><p>We could try to solve the scaling problem with a <code>Dictionary</code>... what about using <code>[String: Any]</code>? While this scales fine it's a step backwards in safety.</p><p><code>String</code> keys are problematic, they are prone to typos and will easily fall out of sync. We could look at using a <code>String</code> enum but then we've re-introduced our scaling issue again!</p><p>On the value side <code>Any</code> strips all our type information and we would then have to cast values back top the desired types again anyway.</p><p>What we need is something that combines the last two attempts. It should scale like a dictionary but gives us the type safety of an explicit model.</p><p>Lets stick with the <code>Dictionary</code> for now. Can we improve on <code>String</code> keys? Turns out Swift <code>KeyPath</code>s are a great solution to this!</p><pre><code class="language-swift"><span class="keyword">var</span><span class="none"> </span><span class="identifier">partialUser</span><span class="none">: [</span><span class="type">PartialKeyPath</span><span class="none">&lt;</span><span class="type">User</span><span class="none">&gt;: </span><span class="keyword">Any</span><span class="none">] = [:]
</span></code></pre><p>By using a <code>PartialKeyPath</code> we are able to restrict the keys to <em>only</em> properties on <code>User</code> like so:</p><pre><code class="language-swift"><span class="identifier">partialUser</span><span class="none">[\</span><span class="identifier">User</span><span class="none">.</span><span class="identifier">firstName</span><span class="none">] = </span><span class="literal">&quot;Ian&quot;</span><span class="none">
</span></code></pre><p>This is great! Now if our <code>User</code> model changes this dictionary will scale perfectly with it. New properties will be available as they are added and changes to existing properties will cause the compiler to complain.</p><p>What about the pesky <code>Any</code>? Right now you could replace the <code>String</code> value <code>"Ian"</code> with something like an <code>Int</code> of <code>42</code> and it would still compile (though it will fail when you try and extract it). Is there a different type we can use here to fix that?</p><p>Sadly no...</p><p>But there is hope! Let's build a new type that will solve this problem <em>and</em> make this solution more <em>generic</em> (pun intended 😄)</p><h2>Partial<T></h2><p>Let's start by putting in the <code>KeyPath</code> based <code>Dictionary</code> we have already to keep track of our changes:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Partial</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">&gt; {
    </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">data</span><span class="none">: [</span><span class="type">PartialKeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">&gt;: </span><span class="keyword">Any</span><span class="none">] = [:]

    </span><span class="comment">//...</span><span class="none">
}
</span></code></pre><p>This gives us a generic type that we can now use with <em>any</em> type we want:</p><pre><code class="language-swift"><span class="keyword">var</span><span class="none"> </span><span class="identifier">partial</span><span class="none"> = </span><span class="identifier">Partial</span><span class="none">&lt;</span><span class="type">User</span><span class="none">&gt;()
</span></code></pre><p>Next, we can use a generic function to ensure the dictionary is updated with the correct types:</p><pre><code class="language-swift"><span class="keyword">mutating</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">update</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">&gt;, </span><span class="identifier">to</span><span class="none"> </span><span class="identifier">newValue</span><span class="none">: </span><span class="type">U</span><span class="none">?) {
    </span><span class="identifier">data</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">] = </span><span class="identifier">newValue</span><span class="none">
}
</span></code></pre><p>We use a <em>full</em> <code>KeyPath</code> here so we can gain access to the generic type of the value of the property. This works because <code>KeyPath</code> is a subclass of <code>PartialKeyPath</code>. With this function we can now update the data using:</p><pre><code class="language-swift"><span class="identifier">partial</span><span class="none">.</span><span class="identifier">update</span><span class="none">(\.</span><span class="identifier">firstName</span><span class="none">, </span><span class="identifier">to</span><span class="none">: </span><span class="literal">&quot;Ian&quot;</span><span class="none">)
</span></code></pre><p>And because we now have access to the properties type we can restrict the value being set. For instance we can no longer pass <code>42</code>. It's also worth noting that we can pass <code>nil</code> to erase any stored value too! We now have a type safe, scalable, setter!</p><p>We can use these same features to also build out the getter:</p><pre><code class="language-swift"><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">&gt;(</span><span class="identifier">for</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">&gt;) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">U</span><span class="none"> {
    </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none"> = </span><span class="identifier">data</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">] </span><span class="keyword">as</span><span class="none">? </span><span class="type">U</span><span class="none"> </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">throw</span><span class="none"> </span><span class="identifier">Error</span><span class="none">.</span><span class="identifier">valueNotFound</span><span class="none"> }
    </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">value</span><span class="none">
}
</span></code></pre><p>Here we are encapsulating the casting of <code>Any</code> to the desired type and adding error handling. We also add in an overload to allow us to deal with optionals in a consistent way.</p><h2>Dragons! 🐉</h2><p>I should point out that there is one potential gotcha with the current implementation... when you use <code>update(_:to:)</code> you are only associating a single <code>KeyPath</code> with a single value. What this means is that if you are working with data like:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Pet</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
}
</span><span class="keyword">struct</span><span class="none"> </span><span class="identifier">User</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">pet</span><span class="none">: </span><span class="type">Pet</span><span class="none">
}
</span></code></pre><p>And you update the value like so:</p><pre><code class="language-swift"><span class="keyword">var</span><span class="none"> </span><span class="identifier">partial</span><span class="none"> = </span><span class="identifier">Partial</span><span class="none">&lt;</span><span class="type">User</span><span class="none">&gt;()
</span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">update</span><span class="none">(\.</span><span class="identifier">pet</span><span class="none">, </span><span class="identifier">to</span><span class="none">: </span><span class="identifier">Pet</span><span class="none">(</span><span class="identifier">name</span><span class="none">: </span><span class="literal">&quot;Rover&quot;</span><span class="none">))
</span></code></pre><p>This only creates a pairing of the <code>pet</code> <code>KeyPath</code> and the <code>Pet</code> object, you cannot then extract the nested data using:</p><pre><code class="language-swift"><span class="keyword">let</span><span class="none"> </span><span class="identifier">petName</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: \.</span><span class="identifier">pet</span><span class="none">.</span><span class="identifier">name</span><span class="none">)
</span></code></pre><p>This will fail because the inner <code>Dictionary</code> does not have an entry for <code>\.pet.name</code>... only <code>\.pet</code>. You need to ensure you are first extracting the data using a <code>KeyPath</code> you have already used <em>then</em> accessing the data from that:</p><pre><code class="language-swift"><span class="keyword">let</span><span class="none"> </span><span class="identifier">pet</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: \.</span><span class="identifier">pet</span><span class="none">)
</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">petName</span><span class="none"> = </span><span class="identifier">pet</span><span class="none">.</span><span class="identifier">name</span><span class="none">
</span></code></pre><p>To correct this we can add an overload for <code>value(for:)</code> that first extracts the stored property then allows us you use <code>KeyPath</code>s to dig further down:</p><pre><code class="language-swift"><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">, </span><span class="identifier">V</span><span class="none">&gt;(</span><span class="identifier">for</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">&gt;, </span><span class="keyword">_</span><span class="none"> </span><span class="identifier">inner</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">U</span><span class="none">, </span><span class="type">V</span><span class="none">&gt;) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">V</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">root</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: </span><span class="identifier">keyPath</span><span class="none">)
    </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">root</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">: </span><span class="identifier">inner</span><span class="none">]
}
</span></code></pre><p>Using this you could then do</p><pre><code class="language-swift"><span class="keyword">let</span><span class="none"> </span><span class="identifier">petName</span><span class="none">: </span><span class="type">String</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: \.</span><span class="identifier">pet</span><span class="none">, \.</span><span class="identifier">name</span><span class="none">)
</span></code></pre><p>This is great because once you have the 'root' object the inner <code>KeyPath</code> can dig down any number of nested levels.</p><h2>Putting it all together</h2><p>This is what our full <code>Partial<T></code> looks like. I've also added some overloads to better handle optionals too:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">Partial</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">&gt; {
    </span><span class="keyword">enum</span><span class="none"> </span><span class="identifier">Error</span><span class="none">: </span><span class="type">Swift</span><span class="none">.</span><span class="type">Error</span><span class="none"> {
        </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">valueNotFound</span><span class="none">
    }

    </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">data</span><span class="none">: [</span><span class="type">PartialKeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">&gt;: </span><span class="keyword">Any</span><span class="none">] = [:]

    </span><span class="keyword">mutating</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">update</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">&gt;, </span><span class="identifier">to</span><span class="none"> </span><span class="identifier">newValue</span><span class="none">: </span><span class="type">U</span><span class="none">?) {
        </span><span class="identifier">data</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">] = </span><span class="identifier">newValue</span><span class="none">
    }
    </span><span class="keyword">mutating</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">update</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">?&gt;, </span><span class="identifier">to</span><span class="none"> </span><span class="identifier">newValue</span><span class="none">: </span><span class="type">U</span><span class="none">?) {
        </span><span class="identifier">data</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">] = </span><span class="identifier">newValue</span><span class="none">
    }
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">&gt;(</span><span class="identifier">for</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">&gt;) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">U</span><span class="none"> {
        </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none"> = </span><span class="identifier">data</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">] </span><span class="keyword">as</span><span class="none">? </span><span class="type">U</span><span class="none"> </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">throw</span><span class="none"> </span><span class="identifier">Error</span><span class="none">.</span><span class="identifier">valueNotFound</span><span class="none"> }
        </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">value</span><span class="none">
    }
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">&gt;(</span><span class="identifier">for</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">?&gt;) -&gt; </span><span class="type">U</span><span class="none">? {
        </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">data</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">] </span><span class="keyword">as</span><span class="none">? </span><span class="type">U</span><span class="none">
    }
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">, </span><span class="identifier">V</span><span class="none">&gt;(</span><span class="identifier">for</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">&gt;, </span><span class="keyword">_</span><span class="none"> </span><span class="identifier">inner</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">U</span><span class="none">, </span><span class="type">V</span><span class="none">&gt;) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">V</span><span class="none"> {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">root</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: </span><span class="identifier">keyPath</span><span class="none">)
        </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">root</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">: </span><span class="identifier">inner</span><span class="none">]
    }
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">U</span><span class="none">, </span><span class="identifier">V</span><span class="none">&gt;(</span><span class="identifier">for</span><span class="none"> </span><span class="identifier">keyPath</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">T</span><span class="none">, </span><span class="type">U</span><span class="none">?&gt;, </span><span class="keyword">_</span><span class="none"> </span><span class="identifier">inner</span><span class="none">: </span><span class="type">KeyPath</span><span class="none">&lt;</span><span class="type">U</span><span class="none">, </span><span class="type">V</span><span class="none">&gt;) -&gt; </span><span class="type">V</span><span class="none">? {
        </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">root</span><span class="none"> = </span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: </span><span class="identifier">keyPath</span><span class="none">) </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="keyword">nil</span><span class="none"> }
        </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">root</span><span class="none">[</span><span class="identifier">keyPath</span><span class="none">: </span><span class="identifier">inner</span><span class="none">]
    }
}
</span></code></pre><p>And we can now extend our original <code>User</code> model like so:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">User</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">partial</span><span class="none">: </span><span class="type">Partial</span><span class="none">&lt;</span><span class="type">User</span><span class="none">&gt;) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">firstName</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: \.</span><span class="identifier">firstName</span><span class="none">)
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">lastName</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: \.</span><span class="identifier">lastName</span><span class="none">)
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">age</span><span class="none"> = </span><span class="identifier">partial</span><span class="none">.</span><span class="identifier">value</span><span class="none">(</span><span class="identifier">for</span><span class="none">: \.</span><span class="identifier">age</span><span class="none">)
    }
}
</span></code></pre><h2>Wrapping up</h2><p>Sadly we are not able to provide a default implementation for the convenience <code>init</code> <em>yet</em>. I've explored a few ways of getting this to work however the core issue is that there is, currently, no way of converting to or from <code>KeyPath</code>s to other types.</p><p>It's a shame but regardless, I think this is an interesting use of <code>KeyPath</code>s. I also like the feel of this solution when compared to the other attempts because of the ability to exactly mirror the underlying model and the resulting compiler safety.</p><p><strong>UPDATE:</strong> I forgot to mention that while there is no way to provide a default implementation for the convenience <code>init</code> you <em>can</em> of course use a tool like <a href="https://github.com/krzysztofzablocki/Sourcery">Sourcery</a> to do this for you until <code>KeyPath</code>s get some love.</p><p>Let me know what you think!</p> ]]></content></entry><entry><title>Improving Codable for enums with associated values</title><link href="https://iankeen.tech/2017/12/08/improving-codable-for-enums-with-associated-values/index.html"/><updated>2017-12-07T16:00:00-08:00</updated><id>https://iankeen.tech/2017/12/08/improving-codable-for-enums-with-associated-values/index.html</id><content type="html"><![CDATA[ <p>With Swift 4 we received a new api to help automagically encode and decode types. By conforming to <code>Codable</code> (A protocol composed of <code>Encodable</code> and <code>Decodable</code>) we can convert types to and from different formats, such as json or property lists.</p><h2>Quick recap</h2><p>There are a number of types that already conform to <code>Codable</code> out-of-the-box. At the time of writing these are: <code>String</code>, <code>Int</code>, <code>Double</code>, <code>Date</code>, <code>Data</code> and <code>URL</code>. The nice part about <code>Codable</code> is, if your type is made up of <em>other</em> <code>Codable</code>s then you get <code>Codable</code> for free. So that means you can define types like:</p><pre><code class="language-swift"><span class="keyword">struct</span><span class="none"> </span><span class="identifier">User</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">name</span><span class="none">: </span><span class="type">String</span><span class="none">
    </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">url</span><span class="none">: </span><span class="type">URL</span><span class="none">
}
</span></code></pre><p>and</p><pre><code class="language-swift"><span class="keyword">enum</span><span class="none"> </span><span class="identifier">AuthState</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">loggedIn</span><span class="none">
    </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">loggedOut</span><span class="none">
}
</span></code></pre><p>And <code>Codable</code> <em>just works</em> - no extra code is required.</p><p>You can store <code>AuthState</code> for example with something like:</p><pre><code class="language-swift"><span class="keyword">let</span><span class="none"> </span><span class="identifier">state</span><span class="none">: </span><span class="type">AuthState</span><span class="none"> = .</span><span class="identifier">loggedIn</span><span class="none">
</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">data</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">JSONEncoder</span><span class="none">().</span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">state</span><span class="none">)
</span><span class="identifier">data</span><span class="none">.</span><span class="identifier">write</span><span class="none">(</span><span class="identifier">to</span><span class="none">: </span><span class="identifier">configFile</span><span class="none">)
</span></code></pre><p>How great is that?!</p><h2>Limitations</h2><p>The enum is interesting. The reason this works is because we have given it a <code>RawValue</code> of <code>String</code>. Swift can use that to infer a <code>String</code> for each case and since <code>String</code> is <code>Codable</code> we get it for free, but what if we wanted to change the enum slightly?</p><pre><code class="language-swift"><span class="keyword">enum</span><span class="none"> </span><span class="identifier">AuthState</span><span class="none">: </span><span class="type">Codable</span><span class="none"> {
    </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">loggedIn</span><span class="none">(</span><span class="type">User</span><span class="none">)
    </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">loggedOut</span><span class="none">
}
</span></code></pre><p>We decide its better to store the logged in user with the logged in state and since <code>User</code> is <code>Codable</code> this should just work too right?</p><p>Unfortunately this isn’t the case (no pun intended)… the enum is no longer <code>RawRepresentable</code> and since there is <em>no</em> <code>RawValue</code> anymore Swift doesn’t know how to encode/decode each case.</p><h2>Manually implementing Codable</h2><p>To make this change work we will need to implement <code>Codable</code> ourselves. Lets start by creating the <code>CodingKey</code>s the enum will use to provide a unique key for each case:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">AuthState</span><span class="none"> {
    </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">enum</span><span class="none"> </span><span class="identifier">CodingKeys</span><span class="none">: </span><span class="type">String</span><span class="none">, </span><span class="type">CodingKey</span><span class="none"> {
        </span><span class="keyword">case</span><span class="none"> </span><span class="identifier">loggedIn</span><span class="none">, </span><span class="identifier">loggedOut</span><span class="none">
    }
}
</span></code></pre><p>Next, lets implement the <code>Encodable</code> part:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">AuthState</span><span class="none"> {
    </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">to</span><span class="none"> </span><span class="identifier">encoder</span><span class="none">: </span><span class="type">Encoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">container</span><span class="none"> = </span><span class="identifier">encoder</span><span class="none">.</span><span class="identifier">container</span><span class="none">(</span><span class="identifier">keyedBy</span><span class="none">: </span><span class="identifier">CodingKeys</span><span class="none">.</span><span class="keyword">self</span><span class="none">)

        </span><span class="keyword">switch</span><span class="none"> </span><span class="keyword">self</span><span class="none"> {
        </span><span class="keyword">case</span><span class="none"> .</span><span class="identifier">loggedIn</span><span class="none">(</span><span class="keyword">let</span><span class="none"> </span><span class="identifier">user</span><span class="none">): </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">user</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: .</span><span class="identifier">loggedIn</span><span class="none">)
        </span><span class="keyword">case</span><span class="none"> .</span><span class="identifier">loggedOut</span><span class="none">:          </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">encode</span><span class="none">(</span><span class="identifier">CodingKeys</span><span class="none">.</span><span class="identifier">loggedOut</span><span class="none">.</span><span class="identifier">stringValue</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: .</span><span class="identifier">loggedOut</span><span class="none">)
        }
    }
}
</span></code></pre><p>You can see the <code>Encodable</code> part benefits from exhaustive switching, we encode cases with an associated value using their <code>CodingKey</code> as the ‘key’ and the associated value as the ‘value’. For cases without an associated value we use the <code>CodingKey</code> as both the ‘key’ and ‘value’.</p><p>Finally lets look at the <code>Decodable</code> code:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">AuthState</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">: </span><span class="type">Decoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">container</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">.</span><span class="identifier">container</span><span class="none">(</span><span class="identifier">keyedBy</span><span class="none">: </span><span class="identifier">CodingKeys</span><span class="none">.</span><span class="keyword">self</span><span class="none">)

        </span><span class="keyword">if</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">user</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decodeIfPresent</span><span class="none">(</span><span class="identifier">User</span><span class="none">.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: .</span><span class="identifier">loggedIn</span><span class="none">) {
            </span><span class="keyword">self</span><span class="none"> = .</span><span class="identifier">loggedIn</span><span class="none">(</span><span class="identifier">user</span><span class="none">)
        } </span><span class="keyword">else</span><span class="none"> </span><span class="keyword">if</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="keyword">_</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decodeIfPresent</span><span class="none">(</span><span class="identifier">String</span><span class="none">.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: .</span><span class="identifier">loggedOut</span><span class="none">) {
            </span><span class="keyword">self</span><span class="none"> = .</span><span class="identifier">loggedOut</span><span class="none">
        } </span><span class="keyword">else</span><span class="none"> {
            </span><span class="keyword">throw</span><span class="none"> </span><span class="identifier">DecodingError</span><span class="none">.</span><span class="identifier">valueNotFound</span><span class="none">(</span><span class="identifier">AuthState</span><span class="none">.</span><span class="keyword">self</span><span class="none">, .</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">codingPath</span><span class="none">: </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">codingPath</span><span class="none">, </span><span class="identifier">debugDescription</span><span class="none">: </span><span class="literal">&quot;&quot;</span><span class="none">))
        }
    }
}
</span></code></pre><p>For <code>Decodable</code>  we unfortunately aren’t able to leverage exhaustive switching. So we need to attempt to decode each case one by one. For cases with an associated value this means attempting to decode the associated value for the key. For cases without associated values we attempt to decode the <code>String</code> value. Finally if nothing succeeds we throw a <code>DecodingError</code>.</p><p>This is perfectly fine and will work as-is, so we <em>could</em> just leave it here and be done. While the <code>Encodable</code> code is about as concise as we can make it this <code>Decodable</code> code is a little wordy.</p><p>Let's look at how we might clean this up a little.</p><h2>Creating a reusable way to decode enums</h2><p>If we look at the current solution to decoding its essentially the same as iterating through all possible cases attempting to decode the required data for each case. It stops as soon as a something is decoded, if nothing was decoded we throw an error.</p><p>Lets build something that uses that pattern:</p><pre><code class="language-swift"><span class="keyword">typealias</span><span class="none"> </span><span class="identifier">Decode</span><span class="none">&lt;</span><span class="identifier">Result</span><span class="none">: </span><span class="type">Decodable</span><span class="none">, </span><span class="identifier">Key</span><span class="none">: </span><span class="type">CodingKey</span><span class="none">&gt; = (</span><span class="type">KeyedDecodingContainer</span><span class="none">&lt;</span><span class="type">Key</span><span class="none">&gt;) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">Result</span><span class="none">?

</span><span class="keyword">func</span><span class="none"> </span><span class="identifier">decode</span><span class="none">&lt;</span><span class="identifier">Result</span><span class="none">: </span><span class="type">Decodable</span><span class="none">, </span><span class="identifier">Key</span><span class="none">&gt;(</span><span class="identifier">using</span><span class="none"> </span><span class="identifier">container</span><span class="none">: </span><span class="type">KeyedDecodingContainer</span><span class="none">&lt;</span><span class="type">Key</span><span class="none">&gt;, </span><span class="identifier">cases</span><span class="none">: [</span><span class="type">Decode</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">, </span><span class="type">Key</span><span class="none">&gt;]) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">Result</span><span class="none"> {
    </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">result</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">cases</span><span class="none">.</span><span class="identifier">lazy</span><span class="none">.</span><span class="identifier">flatMap</span><span class="none">({ </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">$0</span><span class="none">(</span><span class="identifier">container</span><span class="none">) }).</span><span class="identifier">first</span><span class="none">
        </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">throw</span><span class="none"> </span><span class="identifier">DecodingError</span><span class="none">.</span><span class="identifier">valueNotFound</span><span class="none">(</span><span class="identifier">Result</span><span class="none">.</span><span class="keyword">self</span><span class="none">, .</span><span class="identifier">init</span><span class="none">(</span><span class="identifier">codingPath</span><span class="none">: </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">codingPath</span><span class="none">, </span><span class="identifier">debugDescription</span><span class="none">: </span><span class="literal">&quot;&quot;</span><span class="none">)) }

    </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">result</span><span class="none">
}
</span></code></pre><p>This allows us to supply an array of closures, each one uses the container to attempt to decode the data for its specific case. Using this we end up with <code>Decodable</code> code that looks like this:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">AuthState</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">: </span><span class="type">Decoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">self</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">decode</span><span class="none">(</span><span class="identifier">using</span><span class="none">: </span><span class="identifier">decoder</span><span class="none">.</span><span class="identifier">container</span><span class="none">(</span><span class="identifier">keyedBy</span><span class="none">: </span><span class="identifier">CodingKeys</span><span class="none">.</span><span class="keyword">self</span><span class="none">), </span><span class="identifier">cases</span><span class="none">: [
            { </span><span class="identifier">container</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decodeIfPresent</span><span class="none">(</span><span class="identifier">User</span><span class="none">.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: .</span><span class="identifier">loggedIn</span><span class="none">) </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="keyword">nil</span><span class="none"> }
                </span><span class="keyword">return</span><span class="none"> .</span><span class="identifier">loggedIn</span><span class="none">(</span><span class="identifier">value</span><span class="none">)
            },
            { </span><span class="identifier">container</span><span class="none"> </span><span class="keyword">in</span><span class="none">
                </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="keyword">_</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decodeIfPresent</span><span class="none">(</span><span class="identifier">String</span><span class="none">.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: .</span><span class="identifier">loggedOut</span><span class="none">) </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="keyword">nil</span><span class="none"> }
                </span><span class="keyword">return</span><span class="none"> .</span><span class="identifier">loggedOut</span><span class="none">
            },
            ]
        )
    }
}
</span></code></pre><p>Now we have something that does the same thing as the original pattern, and while it now takes care of the error handling for us it doesn’t really read any better (in fact you could argue its actually worse 😭).</p><p>What we want to end up with is a function that fits our <code>Decode</code> signature. However because we need to provide more data we will need to create a curried function that <em>eventually</em> returns our <code>Decode</code> function.</p><p>The code we already have actually covers our two scenarios, so we can use them as the basis for our new curried functions.</p><h3>Without associated values</h3><p>Here is our function for dealing with cases without associated values. We are passing in the case we want, assuming decoding is successful, as well as the <code>CodingKey</code> it should be stored under.</p><pre><code class="language-swift"><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">Result</span><span class="none">: </span><span class="type">Decodable</span><span class="none">, </span><span class="identifier">Key</span><span class="none">: </span><span class="type">CodingKey</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">case</span><span class="none">: </span><span class="type">Result</span><span class="none">, </span><span class="identifier">for</span><span class="none"> </span><span class="identifier">key</span><span class="none">: </span><span class="type">Key</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">Decode</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">, </span><span class="type">Key</span><span class="none">&gt; {
    </span><span class="keyword">return</span><span class="none"> { </span><span class="identifier">container</span><span class="none"> </span><span class="keyword">in</span><span class="none">
        </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="keyword">_</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decodeIfPresent</span><span class="none">(</span><span class="identifier">String</span><span class="none">.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: </span><span class="identifier">key</span><span class="none">) </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="keyword">nil</span><span class="none"> }
        </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">`case`</span><span class="none">
    }
}
</span></code></pre><p>Now we can use the statement <code>value(AuthState.loggedOut, for: .loggedOut)</code> in place of the closure for this case.</p><h3>With associated values</h3><p>Handling cases with associated values lets us use one of Swifts many cool features.  Cases with associated values behave like constructor functions and can be referenced the same way. An example should make this clearer:</p><pre><code class="language-swift"><span class="comment">// notice we have omitted the associated value for this case</span><span class="none">
</span><span class="identifier">AuthState</span><span class="none">.</span><span class="identifier">loggedIn</span><span class="none"> </span><span class="comment">// (User) -&gt; AuthState</span><span class="none">
</span></code></pre><p>Well that is convenient, thats the exact function we need to infer all the extra details from the original closure!</p><pre><code class="language-swift"><span class="keyword">func</span><span class="none"> </span><span class="identifier">value</span><span class="none">&lt;</span><span class="identifier">Result</span><span class="none">: </span><span class="type">Decodable</span><span class="none">, </span><span class="identifier">Key</span><span class="none">: </span><span class="type">CodingKey</span><span class="none">, </span><span class="identifier">T</span><span class="none">: </span><span class="type">Decodable</span><span class="none">&gt;(</span><span class="keyword">_</span><span class="none"> </span><span class="identifier">function</span><span class="none">: </span><span class="keyword">@escaping</span><span class="none"> (</span><span class="type">T</span><span class="none">) -&gt; </span><span class="type">Result</span><span class="none">, </span><span class="identifier">for</span><span class="none"> </span><span class="identifier">key</span><span class="none">: </span><span class="type">Key</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> -&gt; </span><span class="type">Decode</span><span class="none">&lt;</span><span class="type">Result</span><span class="none">, </span><span class="type">Key</span><span class="none">&gt; {
    </span><span class="keyword">return</span><span class="none"> { </span><span class="identifier">container</span><span class="none"> </span><span class="keyword">in</span><span class="none">
        </span><span class="keyword">guard</span><span class="none"> </span><span class="keyword">let</span><span class="none"> </span><span class="identifier">value</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">container</span><span class="none">.</span><span class="identifier">decodeIfPresent</span><span class="none">(</span><span class="identifier">T</span><span class="none">.</span><span class="keyword">self</span><span class="none">, </span><span class="identifier">forKey</span><span class="none">: </span><span class="identifier">key</span><span class="none">) </span><span class="keyword">else</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="keyword">nil</span><span class="none"> }
        </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">function</span><span class="none">(</span><span class="identifier">value</span><span class="none">)
    }
}
</span></code></pre><p>Now our associated value closure can be replaced with <code>value(AuthState.loggedIn, for: .loggedIn)</code>.</p><h3>Final Solution</h3><p>Putting it all together re can rewrite our <code>Decodable</code> code:</p><pre><code class="language-swift"><span class="keyword">extension</span><span class="none"> </span><span class="type">AuthState</span><span class="none"> {
    </span><span class="keyword">init</span><span class="none">(</span><span class="identifier">from</span><span class="none"> </span><span class="identifier">decoder</span><span class="none">: </span><span class="type">Decoder</span><span class="none">) </span><span class="keyword">throws</span><span class="none"> {
        </span><span class="keyword">self</span><span class="none"> = </span><span class="keyword">try</span><span class="none"> </span><span class="identifier">decode</span><span class="none">(</span><span class="identifier">using</span><span class="none">: </span><span class="identifier">decoder</span><span class="none">.</span><span class="identifier">container</span><span class="none">(</span><span class="identifier">keyedBy</span><span class="none">: </span><span class="identifier">CodingKeys</span><span class="none">.</span><span class="keyword">self</span><span class="none">), </span><span class="identifier">cases</span><span class="none">: [
            </span><span class="identifier">value</span><span class="none">(</span><span class="identifier">AuthState</span><span class="none">.</span><span class="identifier">loggedIn</span><span class="none">, </span><span class="identifier">for</span><span class="none">: .</span><span class="identifier">loggedIn</span><span class="none">),
            </span><span class="identifier">value</span><span class="none">(</span><span class="identifier">AuthState</span><span class="none">.</span><span class="identifier">loggedOut</span><span class="none">, </span><span class="identifier">for</span><span class="none">: .</span><span class="identifier">loggedOut</span><span class="none">),
            ]
        )
    }
}
</span></code></pre><p>I think that looks much nicer now.</p><h2>Caveats</h2><p>It’s worth noting that while this works great for local serialization it <em>may</em> not be in the format you need if you intend on sending this to a server. For instance our cases, when converted to json become:</p><p><code>.loggedIn(User(name: "Ian Keen", url: URL(string: "http://iankeen.tech/")!))</code> becomes:</p><pre><code>{"loggedIn":{"name":"Ian Keen","url":"http://iankeen.tech/"}}
</code></pre><p><code>.loggedOut</code> becomes:</p><pre><code>{"loggedOut":"loggedOut"}
</code></pre><p>You may need to tweak the format a little to suit your server api requirements.</p><h2>Wrapping up</h2><p>Its a shame this doesn’t fit into the automagical <code>Codable</code> bucket, hopefully it is something we will get in the future. For now I think this is a decent solution for keeping this cleaner.</p><p>To see the full code checkout <a href="/Resources/improving_codable_for_enums_with_associated_values/improving-codable-for-enums-with-associated-values.zip">this</a> playground.</p> ]]></content></entry><entry><title>Your ViewController isn’t a View</title><link href="https://iankeen.tech/2017/12/04/your-viewcontroller-isnt-a-view/index.html"/><updated>2017-12-03T16:00:00-08:00</updated><id>https://iankeen.tech/2017/12/04/your-viewcontroller-isnt-a-view/index.html</id><content type="html"><![CDATA[ <p>Today I’m going to step through a very under utilized way to slim down your <code>UIViewController</code>s.</p><h2>Example</h2><p>Lets look at a simple login screen:</p><p><img title="" src="/Resources/your_viewcontroller_isnt_a_view/example.gif"></p><h2>Breaking down View and ViewController</h2><p>Lets take a high level look at this screens functionality:</p><ul><li>Contains UI elements</li><li>Lays out UI elements</li><li>Performs Facebook login</li><li>Performs Google login</li><li>Toggles the loading indicator</li><li>Toggles the email login input</li><li>Toggles the keyboard</li><li>Resizing based on the keyboard</li><li>Performs email login</li></ul><p>This is pretty standard list for a screen like this and its common to see <em>all</em> of this contained in the view controller. Over time having a controller handling all these responsibilities can make it harder to understand as well as harder to <em>change</em>.</p><h3>Blurred lines</h3><p>Our first step to separating our code is to figure out what belongs where. What we want to do is group the items in our list in terms of how the screen <em>looks</em> vs what the screen <em>does</em>. This defines our <code>UIView</code> and <code>UIViewController</code> respectively.</p><p>This can be harder than it sounds…</p><p>As we move through each item you may notice some don’t <em>really</em> fit completely in a single category.  Lets look at a few:</p><ul><li>Toggling the loading indicator: This is made up of how that should <em>look</em> but it can show or hide based on what the screen <em>does</em>.</li><li>Toggling the email login elements: This is a state transition so you might think to put that in the controller - however because it is a <em>view state</em> transition that doesn’t rely on any outside logic it should really live in the view in this instance. Remember, theres no reason a view can’t react to things like button taps!</li><li>Dealing with the keyboard can be especially tricky since it exists <em>outside</em> the immediate view hierarchy. Just use your best judgement when it comes to elements like this.</li></ul><p>Now that we’ve had a think about these things lets break our original items out further to create our new lists.</p><h3>How it looks (UIView)</h3><ul><li>Contains UI elements</li><li>Appearance for social logins</li><li>Appearance for email login</li><li>Toggle appearance based on social/email state</li><li>Animate the loading indicator in/out</li><li>Show/hide keyboard</li></ul><h3>What it does (UIViewController) *</h3><ul><li>Performs Facebook login</li><li>Performs Google login</li><li>Performs email login</li><li>Show/hide loading indicator</li><li>Resize when keyboard shows/hides</li></ul><blockquote><p>* NOTE: view controllers accept user input and <em>trigger</em> actions like logging in. However you should not put all the code that <em>performs</em> these actions there. Please use separate service objects in conjunction with this technique.</p></blockquote><p>We can see that what this screen <em>really</em> does is much more than we originally thought. However now that we have a clearer separation of concerns we can break the original view controller down into a separate view and controller that handle their own, distinct, roles.</p><p>So once we have moved the view code into a custom <code>UIView</code> how do we bring that into a <code>UIViewController</code>?</p><h2>Code UI</h2><p>You have no doubt used a number of overrides in <code>UIViewController</code> . <code>viewDidLoad</code>, <code>viewDidAppear</code> etc.. however there is a lesser known override called <code>loadView</code>.</p><h3>Custom Views</h3><p><code>loadView</code> allows you to insert a custom <code>UIView</code> that the <code>UIViewController</code> will use as its <code>view</code> simply by assigning it, for example:</p><pre><code class="language-swift"><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">loadView</span><span class="none">() {
    </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">view</span><span class="none"> = </span><span class="identifier">MyCustomView</span><span class="none">()
}
</span></code></pre><h3>Accessing the custom view</h3><p>How that our custom view is loaded we want typed access to it. The most straight forward way to do this is with a computed property:</p><pre><code class="language-swift"><span class="keyword">var</span><span class="none"> </span><span class="identifier">customView</span><span class="none">: </span><span class="type">MyCustomView</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">view</span><span class="none"> </span><span class="keyword">as</span><span class="none">! </span><span class="type">MyCustomView</span><span class="none"> }
</span></code></pre><p>Now in your <code>UIViewController</code> you access the typed version of the view via the new  <code>customView</code> property instead of <code>self.view</code>  (the <code>!</code> is safe here as we can guarantee <code>view</code> will always be <code>MyCustomView</code>)</p><h3>Bonus</h3><p>Here is a nice generic <code>UIViewController</code> subclass I like to use to simplify this pattern.</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">ViewController</span><span class="none">&lt;</span><span class="identifier">T</span><span class="none">: </span><span class="type">UIView</span><span class="none">&gt;: </span><span class="type">UIViewController</span><span class="none"> {
    </span><span class="comment">// MARK: - View Separation</span><span class="none">
    </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">customView</span><span class="none">: </span><span class="type">T</span><span class="none"> { </span><span class="keyword">return</span><span class="none"> </span><span class="identifier">view</span><span class="none"> </span><span class="keyword">as</span><span class="none">! </span><span class="type">T</span><span class="none"> }

    </span><span class="comment">// MARK: - Lifecycle</span><span class="none">
    </span><span class="keyword">override</span><span class="none"> </span><span class="keyword">func</span><span class="none"> </span><span class="identifier">loadView</span><span class="none">() {
        </span><span class="keyword">self</span><span class="none">.</span><span class="identifier">view</span><span class="none"> = </span><span class="identifier">T</span><span class="none">()
    }
}
</span></code></pre><p>With this you can define your view controllers as:</p><pre><code class="language-swift"><span class="keyword">class</span><span class="none"> </span><span class="identifier">MyViewController</span><span class="none">: </span><span class="type">ViewController</span><span class="none">&lt;</span><span class="type">MyView</span><span class="none">&gt; {
   </span><span class="comment">//you now get a `customView` property typed as `MyView` for free</span><span class="none">
}
</span></code></pre><h2>Storyboard / Nib UI</h2><p>The process for storyboards and nibs are the same.</p><h3>Custom Views</h3><p>Open the storyboard or nib, find your view controllers view in Interface Builders document outline.<img title="" src="/Resources/your_viewcontroller_isnt_a_view/outline.png"></p><p>In the identity inspector update the view class to the type of your custom view.<img title="" src="/Resources/your_viewcontroller_isnt_a_view/inspector.png"></p><h3>Accessing the custom view</h3><p>As with the code based method, we will want typed access to our custom view. We use a computed property again however this time it will be an <code>IBOutlet</code>:</p><pre><code class="language-swift"><span class="keyword">@IBOutlet</span><span class="none"> </span><span class="keyword">private</span><span class="none"> </span><span class="keyword">var</span><span class="none"> </span><span class="identifier">customView</span><span class="none">: </span><span class="type">MyCustomView</span><span class="none">!
</span></code></pre><p>Finally we just need to hook the <code>IBOutlet</code> from the <code>UIViewController</code> to the custom <code>UIView</code>.<img title="" src="/Resources/your_viewcontroller_isnt_a_view/outlet.png"></p><h2>Results</h2><p>So what have we achieved?</p><p>We have defined a clearer separation of concerns between a view and a controller.  Now our view can focus solely on how a screen <em>looks</em> and the controller can focus on what a screen <em>does</em>.</p><p>This is a technique you can use regardless of whether you build your UIs with code, nibs or storyboards <em>and</em> it will work with any architecture or pattern.</p><p>Speaking of patterns… this one is called MVC 😄</p><p>You can download a project with an example of all three UI methods <a href="/Resources/your_viewcontroller_isnt_a_view/your-viewcontroller-isnt-a-view.zip">here</a></p> ]]></content></entry><entry><title>A fresh start</title><link href="https://iankeen.tech/2017/10/08/a-fresh-start/index.html"/><updated>2017-10-07T17:00:00-07:00</updated><id>https://iankeen.tech/2017/10/08/a-fresh-start/index.html</id><content type="html"><![CDATA[ <p>After a bit of a love/hate relationship with <a href="https://medium.com/@iankeen">Medium</a>,I thought it might be nicer to have my own space to write about developing in Swift.</p><p>I have no specific plans for what is going to end up here - but hopefully others may find some of the content useful...</p><p>✌ see you soon</p> ]]></content></entry></feed>