<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Invariante</title>
 <link href="http://invariante.com/atom.xml" rel="self"/>
 <link href="http://invariante.com/"/>
 <updated>2016-09-16T16:36:26+00:00</updated>
 <id>http://invariante.com/</id>
 <author>
   <name>Bruno Koga e Diogo Tridapalli</name>
   <email>feed@invariante.com</email>
 </author>

 
 <entry>
   <title>Logs em Swift</title>
   <link href="http://invariante.com/2016/09/15/Log-em-swift/"/>
   <updated>2016-09-15T00:00:00+00:00</updated>
   <id>http://invariante.com/2016/09/15/Log-em-swift</id>
   <content type="html">&lt;hr /&gt;

&lt;p&gt;Depois de quase 5 meses estamos de volta, 🖖.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Todo mundo, uma hora ou outra, coloca uns &lt;code class=&quot;highlighter-rouge&quot;&gt;NSLog&lt;/code&gt;s no código. Muitas vezes esse log só é útil apenas para o desenvolvimento ou &lt;em&gt;debug&lt;/em&gt;. Então pode não ser uma boa idéia usar direto o &lt;code class=&quot;highlighter-rouge&quot;&gt;NSLog&lt;/code&gt; ou o &lt;code class=&quot;highlighter-rouge&quot;&gt;print&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;, pois esses log aparecem no console dos aparelhos.&lt;/p&gt;

&lt;p&gt;Em &lt;code class=&quot;highlighter-rouge&quot;&gt;Objective-C&lt;/code&gt; eu tenho duas macros (que escrevi faz muitos anos) para resolver esse problema:&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef DEBUG
&lt;/span&gt;    &lt;span class=&quot;cp&quot;&gt;#define DTLog(fmt, ...) NSLog((@&quot;%s:%d %s : &quot; fmt), __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__)
#else
&lt;/span&gt;    &lt;span class=&quot;cp&quot;&gt;#define DTLog NSLog
#endif
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef DEBUG
&lt;/span&gt;    &lt;span class=&quot;cp&quot;&gt;#define DTLogD(fmt, ...) NSLog((@&quot;%s:%d %s : &quot; fmt), __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__)
#else
&lt;/span&gt;    &lt;span class=&quot;cp&quot;&gt;#define DTLogD(...)
#endif
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Um adicional delas que eu gosto bastante é que quando o programa roda em &lt;em&gt;debug&lt;/em&gt;, além da mensagem, são apresentados o nome do arquivo &lt;code class=&quot;highlighter-rouge&quot;&gt;__FILE__&lt;/code&gt;, a linha &lt;code class=&quot;highlighter-rouge&quot;&gt;__LINE__&lt;/code&gt; e o nome da função &lt;code class=&quot;highlighter-rouge&quot;&gt;__PRETTY_FUNCTION__&lt;/code&gt; em que elas foram chamadas. Além disso em &lt;em&gt;release&lt;/em&gt; uma delas não mostra nada.&lt;/p&gt;

&lt;p&gt;Note que essas são macros do pré-processador de C, isso significa que são avaliadas antes do código ser compilado e que seu comportamento depende da macro &lt;em&gt;DEBUG&lt;/em&gt; estar definida. Quando criamos um projeto, o Xcode já define essa macro para nós:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/log-01.png&quot; alt=&quot;Xcode precompiler macros&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Então se você copia-las para seu projeto tudo já vai estar funcionando!&lt;/p&gt;

&lt;p&gt;Em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt; as coisas mudam um pouco, não temos macros do pré-processador. Mas o equivalente direto seriam funções globais, o que não tem muito cara de &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;. O que tenho usado&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; é um &lt;code class=&quot;highlighter-rouge&quot;&gt;struct&lt;/code&gt;  com duas funções estáticas:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Log&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#if DEBUG&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fileURLWithPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lastPathComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lastPathComponent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#if DEBUG&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lastPathComponent&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineNumber&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;] &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functionName&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;terminator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;terminator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Apesar de &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt; não ter macros, temos as &lt;em&gt;&lt;a href=&quot;https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID389&quot;&gt;Special Literal Expressions&lt;/a&gt;&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;#file&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;#line&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;#function&lt;/code&gt; que têm praticamente o mesmo comportamento. Juntando com um pouco de malabarismo com &lt;a href=&quot;https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID166&quot;&gt;Variadic Parameters&lt;/a&gt; fica até mais elegante que as macros.
Mas se você copiar e colar esse código no seu projeto provavelmente ele não vai funcionar direito, isso por conta do &lt;code class=&quot;highlighter-rouge&quot;&gt;#if DEBUG&lt;/code&gt;. Isso não é uma macro, é um &lt;em&gt;&lt;a href=&quot;https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-ID31&quot;&gt;Conditional Compilation Blocks&lt;/a&gt;&lt;/em&gt; e o &lt;em&gt;Xcode&lt;/em&gt; não cria automaticamente um &lt;code class=&quot;highlighter-rouge&quot;&gt;DEBUG&lt;/code&gt; para você 😔. Mas não tem problema, é só adicionar no &lt;em&gt;Build Settings&lt;/em&gt; do projeto:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/log-02.png&quot; alt=&quot;Xcode swift custom flags&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note que diferente da macro não é atribuido um valor e a &lt;em&gt;flag&lt;/em&gt; é precedida de &lt;code class=&quot;highlighter-rouge&quot;&gt;-D&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Criticas, sugestões e comentários são sempre bem-vindos, é só me &lt;em&gt;pingar&lt;/em&gt; no &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt; ou no &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;Slack do iOS Dev BR&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Já em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt; 3.0 &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Minimizando o acoplamento entre Views e ViewControllers</title>
   <link href="http://invariante.com/2016/04/18/minimizando-acoplamento-view-e-viewcontrollers/"/>
   <updated>2016-04-18T00:00:00+00:00</updated>
   <id>http://invariante.com/2016/04/18/minimizando-acoplamento-view-e-viewcontrollers</id>
   <content type="html">&lt;hr /&gt;

&lt;p&gt;Esse artigo foi publicado originalmente no &lt;a href=&quot;http://equinocios.com/arquitetura/2016/03/08/minimizando-acoplamento-view-e-viewcontrollers/&quot;&gt;equinociOS&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;O excesso de responsabilidades do &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt; é algo que vem me incomodando há algum tempo. Já &lt;a href=&quot;http://invariante.com/2015/10/20/todo-view-controller-deveria-ter-delegate/&quot;&gt;escrevi&lt;/a&gt; um pouco sobre a relação entre &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewControllers&lt;/code&gt;, hoje quero falar sobre a relação entre as &lt;code class=&quot;highlighter-rouge&quot;&gt;Views&lt;/code&gt; e o &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Views&lt;/code&gt;, de maneira geral, são genéricas. Não contêm lógica e podem ser reutilizadas em diferentes contextos. Por exemplo, &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; possui uma série de customizações como &lt;code class=&quot;highlighter-rouge&quot;&gt;text&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;font&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;textColor&lt;/code&gt;, que permitem que ela seja usada em diversos contextos. Até aqui tudo certo&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Na maioria dos casos nem todas as configurações são alteradas, o mais comum é alterar as 3 citadas. Em alguns casos é necessário definir uma configuração para o mesmo valor, por exemplo &lt;code class=&quot;highlighter-rouge&quot;&gt;textColor&lt;/code&gt;, cujo o valor padrão é &lt;code class=&quot;highlighter-rouge&quot;&gt;blackColor&lt;/code&gt; mas no &lt;em&gt;app&lt;/em&gt; todos os textos são &lt;code class=&quot;highlighter-rouge&quot;&gt;grayColor&lt;/code&gt;, para evitar a replicação de código algumas vezes eu já fiz uma subclasse de &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; com configurações padrão diferentes, mas isso sempre me pareceu estranho. Essa questão de onde deve ficar o código que define as configurações é um ponto desconfortável. Por exemplo o &lt;code class=&quot;highlighter-rouge&quot;&gt;text&lt;/code&gt;, normalmente quem atribui uma &lt;em&gt;string&lt;/em&gt; é o &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt; que é um estranho pois normalmente ele tira essa &lt;em&gt;string&lt;/em&gt; de um &lt;code class=&quot;highlighter-rouge&quot;&gt;Model&lt;/code&gt;. Quem deve ter o propósito de definir essas configurações?&lt;/p&gt;

&lt;p&gt;Primeiramente o que são essas configurações? São um conjunto de customizações de um componente que correspondem a um resultado final específico, vamos chamar esse conjunto de configurações de &lt;strong&gt;estado&lt;/strong&gt;. Note que a definição de &lt;strong&gt;estado&lt;/strong&gt; aqui é a mesma usada em física&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, uma descrição que define de maneira única e não ambígua a configuração de um sistema. Por exemplo, se o sistema for a localização de algo em uma rua, um estado é definido pelo número da casa. Se o sistema for a localização de algo em alguma cidade na terra, temos várias descrições (ou &lt;em&gt;modelos&lt;/em&gt;) de estados possíveis, por exemplo [País, cidade, rua, número da casa] ou [latitude, longitude, altitude].&lt;/p&gt;

&lt;p&gt;Então cada componente possui um número quase infinito de estados diferentes, pois, no caso do &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt;, para cada &lt;code class=&quot;highlighter-rouge&quot;&gt;text&lt;/code&gt; diferente temos um estado diferente. Se cada estado é único e corresponde a um conjunto de configurações, porque não criar uma classe responsável por definir o estado de uma &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt;? Precisamos de um nome para essa descrição de estado, como devemos fazer uma &lt;em&gt;modelagem&lt;/em&gt; de quais as configurações são relevantes acho que &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; pode ser um nome adequado ;-)&lt;/p&gt;

&lt;p&gt;Um &lt;code class=&quot;highlighter-rouge&quot;&gt;LabelViewModel&lt;/code&gt; simplificado seria:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LabelViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIFont&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; deve ser imutável, então um &lt;code class=&quot;highlighter-rouge&quot;&gt;struct&lt;/code&gt; parece mais adequado.
Para definir uma configuração padrão é só definir um &lt;code class=&quot;highlighter-rouge&quot;&gt;init&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
     &lt;span class=&quot;nv&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;blackColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIFont&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIFont&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;systemFontOfSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;font&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;E uma &lt;code class=&quot;highlighter-rouge&quot;&gt;extension&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; faz a conexão:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UILabel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LabelViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LabelViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;font&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A ideia parece interessante, mas esse exemplo dá uma impressão de excesso de complexidade. Concordo, realmente estamos trocando 6 por meia dúzia.
Vamos tomar um exemplo mais real. Temos uma &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; que contém uma &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; e um &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt;. Sua interface pública seria:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UILabel&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIButton&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Note que as &lt;em&gt;subviews&lt;/em&gt; não são expostas e a única maneira de alterar o &lt;em&gt;estado&lt;/em&gt; dessa &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; é alterando o &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;, que seria assim:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;attributedLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;attributedButtonText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;backgroundColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;onTap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;attributedLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Label&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;attributedButtonText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;backgroundColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;grayColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;onTap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attributedLabel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attributedLabel&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attributedButtonText&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attributedButtonText&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backgroundColor&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onTap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onTap&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Os atributos que podem ser alterados são o&lt;code class=&quot;highlighter-rouge&quot;&gt;NSAttributedString&lt;/code&gt; da &lt;code class=&quot;highlighter-rouge&quot;&gt;label&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;NSAttributedString&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt; em &lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState.Normal&lt;/code&gt;, a &lt;code class=&quot;highlighter-rouge&quot;&gt;backgroundColor&lt;/code&gt; e um &lt;em&gt;closure&lt;/em&gt; que é executado quando o botão tem um &lt;em&gt;tap&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;estado&lt;/em&gt; dessa &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; depende de um &lt;code class=&quot;highlighter-rouge&quot;&gt;Model&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Emoji&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;👍&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;👎&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;👊&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;emoji&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Emoji&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Dado que a configuração da &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; é necessariamente feita de maneira a representar visualmente o &lt;code class=&quot;highlighter-rouge&quot;&gt;Model&lt;/code&gt; o &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; funciona como um &lt;em&gt;&lt;a href=&quot;https://pt.wikipedia.org/wiki/Adapter&quot;&gt;adapter&lt;/a&gt;&lt;/em&gt;, uma interface com apenas com as configurações relevantes. Isso é representado por uma &lt;code class=&quot;highlighter-rouge&quot;&gt;extension&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromModel&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;onTap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSForegroundColorAttributeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;redColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()])&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emoji&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;attributedLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSAttributedString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;attributedButtonText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;onTap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onTap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Aqui vemos mais uma grande vantagem dessa maneira de separar o código.
Testar como será a representação da tela dado um modelo fica muito simples, não é necessário instanciar &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; nem &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt;, um simples teste unitário nessa &lt;code class=&quot;highlighter-rouge&quot;&gt;extension&lt;/code&gt; é suficiente. Isso porque toda a lógica está isolada em apenas um lugar!&lt;/p&gt;

&lt;p&gt;Já que falamos de &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt;, qual seria seu papel aqui? Muito simples:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fromModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;aView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Cria o &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; à partir do &lt;code class=&quot;highlighter-rouge&quot;&gt;Model&lt;/code&gt; e define qual a ação que será tomada quando o botão for acionado. Menos código na &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt;, menos complexidade para testar porque tudo está isolado, mais uma vitória do bem!&lt;/p&gt;

&lt;p&gt;Dessa forma todo o fluxo de informação entre a &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; e o &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt; necessariamente passa pelo &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Um exemplo completo pode ser encontrado no repositório &lt;a href=&quot;https://github.com/diogot/PlainMVVM&quot;&gt;PlainMVVM&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;O nome &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; não foi usado aqui por mero acaso, ele vem de um padrão de arquitetura conhecido como &lt;code class=&quot;highlighter-rouge&quot;&gt;MVVM&lt;/code&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Model–view–viewmodel&quot;&gt;Model-View-ViewModel&lt;/a&gt;). Ele tem se tornado popular, principalmente num contexto de programação reativa, inclusive em alguns artigos do &lt;a href=&quot;http://equinocios.com&quot;&gt;equinociOS&lt;/a&gt;.
Mas pouco se fala fora desse contexto, a &lt;a href=&quot;https://twitter.com/NatashaTheRobot&quot;&gt;NatashaTheRobot&lt;/a&gt; deu uma palestra sobre &lt;a href=&quot;http://www.slideshare.net/natashatherobot/protocoloriented-mvvm-extended-edition&quot;&gt;Protocol Oriented MVVM&lt;/a&gt;, com algumas idéias interessantes para organizar o código usando &lt;code class=&quot;highlighter-rouge&quot;&gt;MVVM&lt;/code&gt;. A idéia que eu descrevi aqui pode não corresponder à um &lt;code class=&quot;highlighter-rouge&quot;&gt;MVVM&lt;/code&gt; formal, mas ilustra de uma maneira razoavelmente simples como separar mais as responsabilidades facilitando testes e reaproveitamento de código.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Criticas, sugestões e comentários são sempre bem vindos, é só me &lt;em&gt;pingar&lt;/em&gt; no &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt; ou no &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;Slack do iOS Dev BR&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;certo? &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;¯\_(ツ)_/¯ &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Tela de login</title>
   <link href="http://invariante.com/2016/03/15/tela-de-login/"/>
   <updated>2016-03-15T00:00:00+00:00</updated>
   <id>http://invariante.com/2016/03/15/tela-de-login</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Nota do autor:&lt;/strong&gt; Estou começando um projeto novo e nele vou tentar usar o máximo sobre &lt;code class=&quot;highlighter-rouge&quot;&gt;RxSwift&lt;/code&gt; que eu conseguir. E vou compartilhar grande parte dessa caminhada aqui no Invariante.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Todos nós já estivemos nessa situação: projeto novo, aplicativo novo. E, invariantemente: uma tela de login.&lt;/p&gt;

&lt;p&gt;E muitas vezes é nesse momento que nos questionamos sobre as decisões mais básicas em relação a arquitetura e organização do código que vamos construir a partir desse momento. Se pararmos para pensar, a tela de login agrega e unifica várias faces do desenvolvimento de software: conexão com uma API, armazenamento (seguro) de informações do usuário, validação de dados, interação com o usuário e até bons cenários de testes.&lt;/p&gt;

&lt;p&gt;E por isso é sempre uma ótima oportunidade para tentarmos, testarmos - e muitas vezes aprender - coisas novas. Eu acredito que uma tela de login oferece desafios para desenvolvedores de &lt;strong&gt;todos&lt;/strong&gt; os níveis de experiência.&lt;/p&gt;

&lt;h2 id=&quot;a-tela-de-login&quot;&gt;A tela de login&lt;/h2&gt;

&lt;p&gt;Nome de usuário, senha e um botão.&lt;/p&gt;

&lt;p&gt;O cenário não poderia ser mais ideal para exercitarmos o uso de &lt;em&gt;bindings&lt;/em&gt;. A idéia é simples: queremos habilitar o botão se os campos de nome de usuário e senha forem válidos. Por enquanto, vamos supor que ambos os campos são válidos se tiverem pelo menos um caractere.&lt;/p&gt;

&lt;p&gt;Nenhuma novidade por aqui. Apenas por clareza, esses são nossos &lt;code class=&quot;highlighter-rouge&quot;&gt;IBOutlets&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;usernameTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginTextField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;passwordTextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginTextField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loginButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIButton&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;E, como em qualquer mundo, vamos definir as nossas duas funções de validação:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validateUsername&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validatePassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;E agora, vamos fazer nosso binding:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;validUsername&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usernameTextField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rx_text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validateUsername&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;validPassword&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;passwordTextField&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rx_text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validatePassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;validUsername&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validPassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;combineLatest&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bindTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loginButton&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rx_enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addDisposableTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disposeBag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;É exatamente isso: essas 6 linhas de código resolvem o nosso problema.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Se você não tem idéia do que o código acima signfica, recomendo &lt;a href=&quot;http://equinocios.com/2016/03/14/rxswift-como-eu-vim-parar-aqui/&quot;&gt;ler o meu post sobre RxSwift no equinocios.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Primeiramente, é importante saber que existe uma extensão do &lt;code class=&quot;highlighter-rouge&quot;&gt;RxSwift&lt;/code&gt; chamada &lt;code class=&quot;highlighter-rouge&quot;&gt;RxCocoa&lt;/code&gt; que aplica os conceitos do &lt;code class=&quot;highlighter-rouge&quot;&gt;RxSwift&lt;/code&gt; em várias  classes do &lt;code class=&quot;highlighter-rouge&quot;&gt;Cocoa&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;UIKit&lt;/code&gt;. É através do &lt;code class=&quot;highlighter-rouge&quot;&gt;RxCocoa&lt;/code&gt; que conseguimos fazer os &lt;em&gt;bindings&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No código acima, fazemos um &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt; em cima do &lt;code class=&quot;highlighter-rouge&quot;&gt;rx_text&lt;/code&gt; (que nada mais é do que o &lt;em&gt;stream&lt;/em&gt; de strings do &lt;code class=&quot;highlighter-rouge&quot;&gt;UITextField&lt;/code&gt;. Lembre-se: no &lt;code class=&quot;highlighter-rouge&quot;&gt;RxSwift&lt;/code&gt; tudo são &lt;em&gt;streams&lt;/em&gt;). E as funções que utilizamos para fazer o &lt;code class=&quot;highlighter-rouge&quot;&gt;map&lt;/code&gt;, nada mais são do que as nossas funções de validação declaradas mais acima.&lt;/p&gt;

&lt;p&gt;Com isso, nossas variáveis &lt;code class=&quot;highlighter-rouge&quot;&gt;validUsername&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;validPassoword&lt;/code&gt; são do tipo &lt;code class=&quot;highlighter-rouge&quot;&gt;Observable&amp;lt;Bool&amp;gt;&lt;/code&gt; e não &lt;code class=&quot;highlighter-rouge&quot;&gt;Bool&lt;/code&gt;, o que nos permite usar o operador &lt;code class=&quot;highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt;, que emitirá um &lt;em&gt;array&lt;/em&gt; com dois &lt;code class=&quot;highlighter-rouge&quot;&gt;Bool&lt;/code&gt;, toda vez que um dos &lt;em&gt;streams&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;validUsername&lt;/code&gt; &lt;strong&gt;ou&lt;/strong&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;validPassword&lt;/code&gt; emitirem um valor. E esses dois &lt;em&gt;streams&lt;/em&gt; por sua vez irão emitir valores quando houver alguma mudança no &lt;code class=&quot;highlighter-rouge&quot;&gt;usernameTextField&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;passwordTextField&lt;/code&gt; respectivamente.&lt;/p&gt;

&lt;p&gt;O nosso &lt;code class=&quot;highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt; nada mais faz do que um &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt; entre o primeiro e o último elemento do nosso array. Aqui usamos um &lt;em&gt;force unwrap&lt;/em&gt; (é, eu sei: dói até de ver) porque sabemos que nosso &lt;em&gt;array&lt;/em&gt; terá &lt;strong&gt;sempre&lt;/strong&gt; dois elementos.&lt;/p&gt;

&lt;p&gt;E agora? Qual o tipo do resultado do resultado do nosso &lt;code class=&quot;highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt;?  Se você pensou &lt;code class=&quot;highlighter-rouge&quot;&gt;Observable&amp;lt;Bool&amp;gt;&lt;/code&gt;, você já está pensando de uma maneira mais zen ☮️.&lt;/p&gt;

&lt;p&gt;Por último (ou quase último), fazemos o &lt;strong&gt;bind&lt;/strong&gt; desse resultado com o valor &lt;code class=&quot;highlighter-rouge&quot;&gt;rx_enabled&lt;/code&gt; do nosso &lt;code class=&quot;highlighter-rouge&quot;&gt;loginButton&lt;/code&gt;. Ou seja, toda vez que o resultado do &lt;code class=&quot;highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt; for &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;, nosso botão irá passar para o estado ativo. E toda vez que o resultado for &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;, nosso botão ficará inativo.&lt;/p&gt;

&lt;p&gt;Por último (de verdade), temos o &lt;code class=&quot;highlighter-rouge&quot;&gt;addDisposableTo&lt;/code&gt;. Essa é a forma que o RxSwift gerencia a memória e os recursos alocados. Se você quiser saber mais sobre as &lt;code class=&quot;highlighter-rouge&quot;&gt;DisposeBags&lt;/code&gt;, recomento ler o &lt;a href=&quot;https://github.com/ReactiveX/RxSwift/blob/master/Documentation/GettingStarted.md#disposing&quot;&gt;Getting Started do &lt;code class=&quot;highlighter-rouge&quot;&gt;RxSwift&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;No próximo artigo, vamos trabalhar em cima de outro conceito simples, mas com uma abordagem funcional: vamos fazer com que a ação do nosso botão de login dispare a requisição de autenticação para a nossa 
API.&lt;/p&gt;

&lt;p&gt;Bruno Koga &lt;br /&gt;
&lt;a href=&quot;http://twitter.com/brunokoga&quot;&gt;@brunokoga&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Em Swift, nil é diferente de Zero</title>
   <link href="http://invariante.com/2016/02/14/Em-Swift-nil-diferente-de-zero/"/>
   <updated>2016-02-14T00:00:00+00:00</updated>
   <id>http://invariante.com/2016/02/14/Em-Swift-nil-diferente-de-zero</id>
   <content type="html">&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Objective-C&lt;/code&gt; possui uma característica muito interessante e polêmica, enviar mensagens para &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; é válido e não lança excessão como em outras linguagens. Não vou discutir se isso é bom ou ruim, mas é algo que gosto e uso frequentemente quando programo nessa linguagem.&lt;/p&gt;

&lt;p&gt;Um uso comum seria quando é necessário testar se um &lt;em&gt;array&lt;/em&gt; é vazio:&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;NSLog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Isso funciona porque o retorno de qualquer mensagem enviada para &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; é &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; ou &lt;code class=&quot;highlighter-rouge&quot;&gt;NULL&lt;/code&gt; dependendo do tipo de retorno da mensagem, semanticamente diferentes mas tecnicamente iguais a &lt;code class=&quot;highlighter-rouge&quot;&gt;ZERO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então se &lt;code class=&quot;highlighter-rouge&quot;&gt;array&lt;/code&gt; for &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;array.count&lt;/code&gt; retorna &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;, mais uma vitória do bem e menos código escrito 😎.&lt;/p&gt;

&lt;p&gt;Sem pensar muito o podemos escrever o equivalente em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Se &lt;code class=&quot;highlighter-rouge&quot;&gt;array&lt;/code&gt; for um opcional, novamente sem pensar muito, poderíamos fazer um &lt;em&gt;optional chaining&lt;/em&gt; e só colocar um &lt;code class=&quot;highlighter-rouge&quot;&gt;?&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NÃO!!&lt;/strong&gt; Quando &lt;code class=&quot;highlighter-rouge&quot;&gt;array = nil&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;array?.count == 0&lt;/code&gt; é falso, mas porque?&lt;/p&gt;

&lt;p&gt;A resposta está em no funcionamento do &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html&quot;&gt;&lt;em&gt;optional chaining&lt;/em&gt;&lt;/a&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;?&lt;/code&gt; tem um comportamento semelhante ao &lt;code class=&quot;highlighter-rouge&quot;&gt;!&lt;/code&gt; (&lt;em&gt;force unwrapping&lt;/em&gt;), com a diferença que se o valor opcional for &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; não é lançado um erro de &lt;em&gt;runtime&lt;/em&gt;. Como não ocorre a interrupção do programa e afim de evitar inconsistências o resultado de chamadas de métodos, propriedades e &lt;em&gt;subscripts&lt;/em&gt; sempre vão retornar um opcional, mesmo que o tipo original não seja. Por exemplo:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]?&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// count is Int? not Int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Isso significa que quando &lt;code class=&quot;highlighter-rouge&quot;&gt;array = nil&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;count = nil&lt;/code&gt; que não é igual a &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt; e por isso o teste anterior falha! Ou seja em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;nil != 0&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Para escrever o teste de maneira que funciona temos várias opções.&lt;/p&gt;

&lt;p&gt;Definir que quando o resultado do &lt;code class=&quot;highlighter-rouge&quot;&gt;count&lt;/code&gt; for &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; o resultado esperado é &lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Testar o &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; e fazer &lt;em&gt;force unwrapping&lt;/em&gt;. Não me agrada o &lt;em&gt;force unwrapping&lt;/em&gt;, sei que nesse caso nunca aconteceria um erro de &lt;em&gt;runtime&lt;/em&gt; mas prefiro evitar ao máximo o &lt;code class=&quot;highlighter-rouge&quot;&gt;!&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Por algum motivo ainda desconhecido para mim, &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; é menor que qualquer &lt;code class=&quot;highlighter-rouge&quot;&gt;Int&lt;/code&gt;. Então temos uma opção que eu não recomendo, ¯\_(ツ)_/¯:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Com certeza devem haver mais uma dezena de maneiras de escrever mas acho que já deu para ter uma idéia. Provavelmente o erro desse caso é transpor exatamente a mesma lógica do &lt;code class=&quot;highlighter-rouge&quot;&gt;Objective-C&lt;/code&gt; para &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Update 2016/02/16&lt;/em&gt; - O &lt;a href=&quot;https://twitter.com/marcelofabri_&quot;&gt;Fabri&lt;/a&gt; e o &lt;a href=&quot;https://twitter.com/brunokoga&quot;&gt;Koga&lt;/a&gt; lembraram que o &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt; adota o protocolo &lt;code class=&quot;highlighter-rouge&quot;&gt;CollectionType&lt;/code&gt; e portanto o &lt;code class=&quot;highlighter-rouge&quot;&gt;isEmpty&lt;/code&gt; seria mais adequado:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty array&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;O Fabri pensou mais no assunto&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; e propôs uma extensão para o &lt;code class=&quot;highlighter-rouge&quot;&gt;Optional&lt;/code&gt; de &lt;code class=&quot;highlighter-rouge&quot;&gt;IntegerType&lt;/code&gt; que evitaria o problema apresentado:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Optional&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Wrapped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IntegerType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;valueOrZero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Wrapped&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Assim o teste ficaria:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valueOrZero&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;empty&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Um bom exercício para evitar o erro, mas acho que a versão com o &lt;code class=&quot;highlighter-rouge&quot;&gt;isEmpty&lt;/code&gt; ainda fica mais legível.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Criticas, sugestões e comentários são sempre bem vindos, é só me &lt;em&gt;pingar&lt;/em&gt; no &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt; ou no &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;slack do iOS Dev BR&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Assumindo que eu seja um cara teimoso e me recuse a usar o &lt;code class=&quot;highlighter-rouge&quot;&gt;isEmpty&lt;/code&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Uma collection view cell to rule them all</title>
   <link href="http://invariante.com/2016/01/31/collectionviewcell-to-rule-them-all/"/>
   <updated>2016-01-31T00:00:00+00:00</updated>
   <id>http://invariante.com/2016/01/31/collectionviewcell-to-rule-them-all</id>
   <content type="html">&lt;p&gt;Feliz ano novo, feliz &lt;em&gt;post&lt;/em&gt; novo!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Um dia desses o caro &lt;a href=&quot;https://twitter.com/viniciusc70&quot;&gt;Vinicius&lt;/a&gt; estava &lt;a href=&quot;https://twitter.com/viniciusc70/status/693172598981693441&quot;&gt;reclamando&lt;/a&gt; da curva de aprendizado do &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UICollectionView&lt;/code&gt;&lt;/a&gt;, para quem não conhece é uma &lt;code class=&quot;highlighter-rouge&quot;&gt;UITableViewController&lt;/code&gt; com esteroides.&lt;br /&gt;
Você pode usar &lt;em&gt;layouts&lt;/em&gt; customizados, transições de animações e muitas outras coisas que eu nem consigo imaginar. Por coincidência nesse mesmo dia eu estava implementando minha primeira &lt;code class=&quot;highlighter-rouge&quot;&gt;UICollectionView&lt;/code&gt; em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;. Nesse &lt;em&gt;post&lt;/em&gt; não vou falar sobre essa classe mas de sobre suas células &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewCell_class/index.html&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UICollectionViewCell&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No último mês venho &lt;em&gt;brigando&lt;/em&gt; muito com &lt;a href=&quot;https://github.com/apple/swift/blob/master/docs/Generics.rst&quot;&gt;&lt;em&gt;generics&lt;/em&gt;&lt;/a&gt; (ou &lt;a href=&quot;https://github.com/CocoaHeadsBrasil/the-swift-programming-language-in-portuguese-br/blob/master/guia/genericos.md&quot;&gt;genéricos&lt;/a&gt;) e consegui montar um exemplo interessante de uso aplicado à &lt;code class=&quot;highlighter-rouge&quot;&gt;UICollectionViewCell&lt;/code&gt;. Esse classe não tem um &lt;em&gt;label&lt;/em&gt; como a &lt;code class=&quot;highlighter-rouge&quot;&gt;UITableViewCell&lt;/code&gt;, apenas uma &lt;code class=&quot;highlighter-rouge&quot;&gt;contentView&lt;/code&gt;, isso dificulta exemplos mais simples pois implica que 100% da vezes você vai ter que customizar as células.&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;UICollectionViewCell&lt;/code&gt; precisa de uma ou mais &lt;code class=&quot;highlighter-rouge&quot;&gt;UIView&lt;/code&gt; que vão ser adicionadas à &lt;code class=&quot;highlighter-rouge&quot;&gt;contentView&lt;/code&gt; para essa customização. Então seria natural que eu uma célula genérica dependesse desse tipo:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CollectionViewCell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UICollectionViewCell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private(set)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;contentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autoresizingMask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FlexibleHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FlexibleWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nesse caso específico não vejo necessidade de usar &lt;code class=&quot;highlighter-rouge&quot;&gt;AutoLayout&lt;/code&gt;. Aqui temos algo bem simples, na criação da célula uma instância da &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; é criada adicionada à &lt;code class=&quot;highlighter-rouge&quot;&gt;contentView&lt;/code&gt; de forma a ter sempre o seu tamanho.
Para customizar essa view em &lt;code class=&quot;highlighter-rouge&quot;&gt;collectionView(_: cellForItemAtIndexPath:)&lt;/code&gt; seria apenas utilizar a referência a ela em &lt;code class=&quot;highlighter-rouge&quot;&gt;customView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mas se começarmos a pensar na linha do &lt;code class=&quot;highlighter-rouge&quot;&gt;MVVM&lt;/code&gt; seria interessante que essa &lt;code class=&quot;highlighter-rouge&quot;&gt;view&lt;/code&gt; aceitasse configuração via um &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;. Nesse caso teríamos um protocolo para tipos que possuem um &lt;code class=&quot;highlighter-rouge&quot;&gt;model&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;HasModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Aqui temos um protocolo que possui um tipo associado (&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html&quot;&gt;Associated Type&lt;/a&gt;), isso significa que o tipo da propriedade &lt;code class=&quot;highlighter-rouge&quot;&gt;model&lt;/code&gt; pode ser diferente para cada tipo que adotar esse protocol. Entretanto isso tem alguns &lt;a href=&quot;http://www.russbishop.net/swift-associated-types&quot;&gt;efeitos colaterais&lt;/a&gt; não relevantes para o exemplo corrente.&lt;/p&gt;

&lt;p&gt;Vamos supor que eu não queira acessar a &lt;code class=&quot;highlighter-rouge&quot;&gt;customView &lt;/code&gt;, mas passar o &lt;em&gt;view model&lt;/em&gt; diretamente para a célula, como o modelo depende de cada view nossa célula vai passar a ter dois parâmetros, &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;. Essa classe então ficaria:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CollectionViewCell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;HasModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UICollectionViewCell&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private(set)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;contentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autoresizingMask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FlexibleHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FlexibleWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;customView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newModel&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Agora a coisa fica mais interessante, note a definição do &lt;em&gt;generics&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;View: UIView, ViewModel where View: HasModel, View.Model == ViewModel&amp;gt;&lt;/code&gt;. Ele define um tipo &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; que é subclasse de &lt;code class=&quot;highlighter-rouge&quot;&gt;UIView&lt;/code&gt; e um tipo &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;, o &lt;code class=&quot;highlighter-rouge&quot;&gt;where&lt;/code&gt; aplica restrições a esse tipos, o &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; adota o &lt;code class=&quot;highlighter-rouge&quot;&gt;HasModel&lt;/code&gt; e o tipo associado &lt;code class=&quot;highlighter-rouge&quot;&gt;Model&lt;/code&gt; da &lt;code class=&quot;highlighter-rouge&quot;&gt;View&lt;/code&gt; é o mesmo do &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Isso é suficiente para que qualquer &lt;code class=&quot;highlighter-rouge&quot;&gt;UIView&lt;/code&gt; que adote o &lt;code class=&quot;highlighter-rouge&quot;&gt;HasModel&lt;/code&gt; seja usada em uma &lt;em&gt;collection view&lt;/em&gt;. Vamos supor que eu queira usar um &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; para isso, uma &lt;em&gt;extension&lt;/em&gt; de poucas linhas isso está resolvido:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UILabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;HasModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newModel&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;textAlignment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Center&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Para usar isso numa &lt;em&gt;collection view&lt;/em&gt; precisamos primeiro registrar a classe da célula genérica (no &lt;code class=&quot;highlighter-rouge&quot;&gt;viewDidLoad&lt;/code&gt; por exemplo):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;n&quot;&gt;collectionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;registerClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CollectionViewCell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UILabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forCellWithReuseIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reuseIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;E então configurar a célula:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;collectionView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;collectionView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UICollectionView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cellForItemAtIndexPath&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;indexPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSIndexPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UICollectionViewCell&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dequeueReusableCellWithReuseIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reuseIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forIndexPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indexPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CollectionViewCell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UILabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;numberOfItemsInSection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indexPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cell &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indexPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Um exemplo completo pode ser encontrado no repositório &lt;a href=&quot;https://github.com/diogot/GenericCollectionViewCell&quot;&gt;GenericCollectionViewCell&lt;/a&gt;. Criticas, sugestões e comentários são sempre bem vindos, é só me &lt;em&gt;pingar&lt;/em&gt; no &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt; ou no &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;slack do iOS Dev BR&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Construindo um UIButton</title>
   <link href="http://invariante.com/2015/11/22/construindo-um-uibutton/"/>
   <updated>2015-11-22T00:00:00+00:00</updated>
   <id>http://invariante.com/2015/11/22/construindo-um-uibutton</id>
   <content type="html">&lt;p&gt;O &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIButton_Class/&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt;&lt;/a&gt; é uma classe extensamente utilizada, muito testada e configurável, então:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Porque alguém em sã consciência perderia tempo fazendo um botão?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu acredito que o objetivo didático seria justificativa suficiente, algo como o &lt;a href=&quot;https://twitter.com/mikeash&quot;&gt;Mike Ash&lt;/a&gt; faz com alguma frequência em seu &lt;a href=&quot;https://mikeash.com/pyblog/&quot;&gt;blog&lt;/a&gt;, mas não é o caso. Por &lt;em&gt;simplicidade&lt;/em&gt; vamos assumir que o problema não está na minha sanidade, mas em um desconforto ao customizar um botão.&lt;/p&gt;

&lt;p&gt;Com frequência os botões são usados para iniciar requisições à servidores, no mundo real isso não é instantâneo e o usuário deve (ou deveria) ser &lt;em&gt;entretido&lt;/em&gt; de alguma maneira enquanto a resposta dessa requisição não chega.&lt;/p&gt;

&lt;p&gt;Existem inúmeras maneiras de fazer isso, não vou discutir todas porque não cabe no escopo desse artigo, só digo para não colocar um &lt;em&gt;spinner&lt;/em&gt; bem no meio da tela impedindo o usuário de interagir com seu &lt;em&gt;app&lt;/em&gt;. Uma maneira que gosto bastante é de apresentar o estado da requisição dentro do botão que a iniciou. Mas para isso é preciso ter um botão que tenha esse novo estado. Adaptar (&lt;em&gt;cof&lt;/em&gt; &lt;em&gt;hackear&lt;/em&gt; &lt;em&gt;cof&lt;/em&gt;) um UIButton não me pareceu uma maneira honesta, vou discutir isso em um artigo específico, então decidi construir um botão que replica o &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIButton_Class/&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt;&lt;/a&gt; e depois adicionar o novo estado, o que não é uma tarefa fácil, mas muito instrutiva. A idéia é reproduzir o comportamento de um botão do tipo &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButtonType.System&lt;/code&gt;. Além disso me pareceu uma boa oportunidade de exercitar um pouco meu &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt; tem muitos elementos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;titleLabel&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;attributedTitle&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;titleColor&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;titleShadow&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;image&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;backgroundImage&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tintColor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;estados:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState.Normal&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState.Highlighted&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState.Disabled&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState.Selected&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E outros detalhes não óbvios como reagir à &lt;code class=&quot;highlighter-rouge&quot;&gt;tintAdjustmentMode&lt;/code&gt;, acessibilidade, &lt;code class=&quot;highlighter-rouge&quot;&gt;UIAppearance&lt;/code&gt;, animações, &lt;code class=&quot;highlighter-rouge&quot;&gt;contentEdgeInsets&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;titleEdgeInsets&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;imageEdgeInsets &lt;/code&gt; e outras coisas que eu ainda não descobri, então decidi limitar os requisitos dessa versão 1.0. Uma das primeiras decisões é que o &lt;code class=&quot;highlighter-rouge&quot;&gt;Button&lt;/code&gt; deve ser subclasse do &lt;code class=&quot;highlighter-rouge&quot;&gt;UIControl&lt;/code&gt;, suponho que isso deve facilitar a vida. A interface, se é que existe isso em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;, deve ser algo assim:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UILabel&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;titleForState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forState&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;titleColorForState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setTitleColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forState&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImageView&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;imageForState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forState&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;backgroundImageForState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setBackgroundImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forState&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forControlEvents&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;controlEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Vemos que os &lt;em&gt;insets&lt;/em&gt; estão de fora, a parte de acessibilidade também vou deixar para a próxima versão, junto com &lt;code class=&quot;highlighter-rouge&quot;&gt;UIAppearance&lt;/code&gt;. Uma coisa que eu gostaria de fazer mas me pareceu bem mais complicado do que eu imaginava são as animações, especialmente a do &lt;code class=&quot;highlighter-rouge&quot;&gt;titleLabel&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/construindo-um-uibutton-01.gif&quot; alt=&quot;UIButton label animation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note que nunca os dois textos aparecem ao mesmo tempo, o texto do estado &lt;code class=&quot;highlighter-rouge&quot;&gt;Normal&lt;/code&gt; desaparece e depois o &lt;code class=&quot;highlighter-rouge&quot;&gt;Highlighted&lt;/code&gt; aparece, mas porque esse tempo sem texto nenhum? 
Nas minhas tentativas de animar a transição percebi que a diferença no tamanho do texto obriga o redimensionamento da &lt;em&gt;label&lt;/em&gt;, e ai tudo vai para o brejo. Uma maneira de evitar é colocar esse tempo em “branco”. Fuçando com o &lt;a href=&quot;http://revealapp.com&quot;&gt;Reveal&lt;/a&gt; descobri que o &lt;em&gt;label&lt;/em&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt; não é uma &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; mas uma &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButtonLabel&lt;/code&gt;, uma classe que não é pública e deve resolver esses detalhes das animações ¯\_(ツ)_/¯. Uma outra complicação é que essa animação pode ser cancelada, ou alterada, antes de seu fim, dependendo do tempo de duração do toque. Acho que isso daria assunto para um artigo inteiro!&lt;/p&gt;

&lt;p&gt;A hierarquia de &lt;em&gt;views&lt;/em&gt; consiste de uma &lt;code class=&quot;highlighter-rouge&quot;&gt;UIImageView&lt;/code&gt; que vai conter a &lt;code class=&quot;highlighter-rouge&quot;&gt;backgrondImage&lt;/code&gt;, uma &lt;code class=&quot;highlighter-rouge&quot;&gt;contentView&lt;/code&gt; que contém &lt;code class=&quot;highlighter-rouge&quot;&gt;UIImageView&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;UILabel&lt;/code&gt; como mostra a imagem:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/construindo-um-uibutton-02.png&quot; alt=&quot;Button view hierarchy&quot; /&gt;&lt;/p&gt;

&lt;p&gt;O Layout foi feito usando &lt;code class=&quot;highlighter-rouge&quot;&gt;Autolayout&lt;/code&gt; e não vou entrar em mais detalhes porque ele foi estruturado para não depender do conteúdo do botão, quem se interessar pode dar uma olhada no projeto do github.&lt;/p&gt;

&lt;p&gt;O &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt; tem alguns comportamentos específicos para cada um de suas “propriedades”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;titleLabel&lt;/code&gt;, se não for definida uma &lt;em&gt;string&lt;/em&gt; para um estado específico a do estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Normal&lt;/code&gt; é utilizada. O estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Highlighted&lt;/code&gt; causa um comportamento diferente quando este não tem uma &lt;em&gt;string&lt;/em&gt; definda e nem uma &lt;code class=&quot;highlighter-rouge&quot;&gt;titleColor&lt;/code&gt;, o &lt;code class=&quot;highlighter-rouge&quot;&gt;alpha&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;titleLabel&lt;/code&gt; passa a ser &lt;code class=&quot;highlighter-rouge&quot;&gt;0.2&lt;/code&gt;, causando o efeito de selecionado;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;titleColor&lt;/code&gt;, se não for definida uma cor para um estado específico a do estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Normal&lt;/code&gt; é utilizada. Quando nenhuma cor específica for definida as coisa ficam interessantes. No estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Normal&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;.Highlighted&lt;/code&gt; é utilizada a &lt;code class=&quot;highlighter-rouge&quot;&gt;tintColor&lt;/code&gt;, e quanto ela muda, por exemplo devido a alteração no &lt;code class=&quot;highlighter-rouge&quot;&gt;tintAdjustmentMode&lt;/code&gt;, isso é respeitado. Esse comportamento é o que faz com que o botão fique “cinza” quando aparece um &lt;em&gt;popup&lt;/em&gt;. Quando o estado é 
&lt;code class=&quot;highlighter-rouge&quot;&gt;.Disabled&lt;/code&gt; a cor é alterada para &lt;code class=&quot;highlighter-rouge&quot;&gt;UIColor(white: 0.4, alpha: 0.35)&lt;/code&gt;, infelizmente não consegui achar uma cor do sistema que corresponda a esse padrão :-(&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;image&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;backgroundImage&lt;/code&gt;, se não for definida uma imagem para um estado específico a do estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Normal&lt;/code&gt; é utilizado. No caso do estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Highlighted&lt;/code&gt; não ter uma imagem, além de ser utilizada a do estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Normal&lt;/code&gt; o &lt;code class=&quot;highlighter-rouge&quot;&gt;alpha&lt;/code&gt; do elemento em questão passa a ser &lt;code class=&quot;highlighter-rouge&quot;&gt;0.2&lt;/code&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dividimos essa questão em dois problemas, primeiro como armazenar os valores das propriedades para cada estado e depois aplicar a lógica para cada propriedade.&lt;/p&gt;

&lt;p&gt;A maneira mais simples de armazenar seria utilizando um dicionário:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;titles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;titleColors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;backgroundImages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Mas &lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState&lt;/code&gt; não implementa o protocolo &lt;code class=&quot;highlighter-rouge&quot;&gt;Hashable&lt;/code&gt;, isso é facilmente resolvido com uma &lt;code class=&quot;highlighter-rouge&quot;&gt;extension&lt;/code&gt; que implementa o &lt;code class=&quot;highlighter-rouge&quot;&gt;hashValue&lt;/code&gt; como o &lt;code class=&quot;highlighter-rouge&quot;&gt;Int(rawValue)&lt;/code&gt; do protocolo &lt;code class=&quot;highlighter-rouge&quot;&gt;RawRepresentable&lt;/code&gt; (esse “truque” fez &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt; ganhar alguns pontos comigo):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Hashable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;hashValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A implementação dos métodos públicos lidam com estados do &lt;code class=&quot;highlighter-rouge&quot;&gt;titleLabel&lt;/code&gt; ficam bem simples:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;titleForState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forState&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;titles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;titles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;removeValueForKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Os métodos das outras propriedades tem exatamente a mesma lógica, o que vale notar aqui é a chamada &lt;code class=&quot;highlighter-rouge&quot;&gt;updateUI()&lt;/code&gt;, esse método é o que atualiza as mudanças na tela e resolve grande parte do segundo problema:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;defaultState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Normal&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;titleIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titleIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getValeuIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;textColorIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textColorIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getValeuIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titleColors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tintColor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getValeuIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;backgroundImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;backgroundImageIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backgroundImageIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getValeuIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;backgroundImages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;textAlpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGFloat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlighted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titleIsFallback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textColorIsFallback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;highlightedAlpha&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalAlpha&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageAlpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGFloat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlighted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageIsFallback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;highlightedAlpha&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalAlpha&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;backgroundImageAlpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGFloat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlighted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backgroundImageIsFallback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;highlightedAlpha&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalAlpha&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textColor&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;textAlpha&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageAlpha&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;backgroundImageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backgroundImage&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;backgroundImageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backgroundImageAlpha&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;É um método extenso, o correto seria extrair a lógica de cada propriedade em métodos separados para poder testar somente a lógica, mas para uma primeira versão serve.&lt;/p&gt;

&lt;p&gt;A lógica é feita em duas fases, na primeira é definido o valor da propriedade para o estado atual e se esse valor foi definido ou é padrão (&lt;em&gt;fallback&lt;/em&gt;). Na segunda fase é definido o &lt;code class=&quot;highlighter-rouge&quot;&gt;alpha&lt;/code&gt;,
no fim tudo é atualizado de uma só vez.&lt;/p&gt;

&lt;p&gt;Um método genérico é usado na primeira fase:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getValeuIn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forState&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fallbackState&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIControlState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;thingIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aThing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aThing&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thingIsFallback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaultState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fallbackValue&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;thingIsFallback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thingIsFallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O único comentário pertinente seria mais uma vez ponto para o &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt; com &lt;em&gt;generics&lt;/em&gt; e &lt;em&gt;tuples&lt;/em&gt; (já não sinto tanta falta do &lt;code class=&quot;highlighter-rouge&quot;&gt;;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Para completar a atualização dos estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Disabled&lt;/code&gt; é preciso fazer chamar &lt;code class=&quot;highlighter-rouge&quot;&gt;updateUI()&lt;/code&gt; quando o &lt;code class=&quot;highlighter-rouge&quot;&gt;enabled&lt;/code&gt; é chamado:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;didSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;E o equivalente quando há uma mudança na &lt;code class=&quot;highlighter-rouge&quot;&gt;tintColor&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tintColorDidChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A atualização para o estado &lt;code class=&quot;highlighter-rouge&quot;&gt;.Highlighted&lt;/code&gt; requer alterações no &lt;em&gt;tracking&lt;/em&gt; do &lt;em&gt;touch&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;beginTrackingWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UITouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withEvent&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beginTrackingWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;withEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;updateWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;continueTrackingWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UITouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withEvent&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;continueTrackingWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;withEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;updateWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;endTrackingWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UITouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withEvent&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;endTrackingWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;withEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;touch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;updateWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O &lt;em&gt;highlight&lt;/em&gt; depende do &lt;em&gt;touch&lt;/em&gt; estar dentro da área do botão, a propriedade &lt;code class=&quot;highlighter-rouge&quot;&gt;touchInside&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;UIControl&lt;/code&gt; é a ideal para saber isso, mas temos um problema. Ela só é atualizada quando o &lt;code class=&quot;highlighter-rouge&quot;&gt;beginTrackingWithTouch(_:withEvent:) -&amp;gt; Bool&lt;/code&gt; retorna, como nosso método &lt;code class=&quot;highlighter-rouge&quot;&gt;updateWithTouch(_:)&lt;/code&gt; é chamado antes do retorno temos que fazer um &lt;em&gt;workaround&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateWithTouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UITouch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;point&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;locationInView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ended&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;phase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Ended&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Workaround because touchInside inside is not true on beginTrackingWithTouch&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;insideTouch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pointInside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;withEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;highlighted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ended&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insideTouch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;touchInside&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Acho que com isso consegui cobrir os requisitos da versão 1.0 e deu para entender um pouco melhor o funcionamento do &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt;. Algumas propriedades ainda permanecem um mistério para mim, como o &lt;code class=&quot;highlighter-rouge&quot;&gt;adjustsImageWhenHighlighted&lt;/code&gt;, que ao meu entendimento deveria habilitar e desabilitar a alteração do &lt;code class=&quot;highlighter-rouge&quot;&gt;alpha&lt;/code&gt; quando falso, mas nos meus testes não consegui ver diferença.&lt;/p&gt;

&lt;p&gt;O &lt;a href=&quot;https://github.com/diogot/LoadingButton/blob/Button/LoadingButton/Button.swift&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Button&lt;/code&gt;&lt;/a&gt; pode ser encontrado no &lt;em&gt;branch&lt;/em&gt; &lt;a href=&quot;https://github.com/diogot/LoadingButton/tree/Button&quot;&gt;Button&lt;/a&gt; do repositório &lt;a href=&quot;https://github.com/diogot/LoadingButton&quot;&gt;LoadingButton&lt;/a&gt;. Criticas, sugestões e comentários são sempre bem vindos, é só me &lt;em&gt;pingar&lt;/em&gt; no &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt; ou no &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;slack do iOS Dev BR&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Uma dica para quem usa cores e não imagens como background e quer se beneficiar dos estados é criar um &lt;code class=&quot;highlighter-rouge&quot;&gt;UIImage&lt;/code&gt; à partir de uma &lt;code class=&quot;highlighter-rouge&quot;&gt;UIColor&lt;/code&gt; usando a seguinte &lt;em&gt;extension&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;UIGraphicsBeginImageContextWithOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;setFill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;UIRectFill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIGraphicsGetImageFromCurrentImageContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;UIGraphicsEndImageContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Storyboards e Injeções de Dependências.</title>
   <link href="http://invariante.com/2015/11/03/eu-amo-storyboards/"/>
   <updated>2015-11-03T00:00:00+00:00</updated>
   <id>http://invariante.com/2015/11/03/eu-amo-storyboards</id>
   <content type="html">&lt;p&gt;##Eu sou fã de Storyboards.&lt;/p&gt;

&lt;p&gt;Acho a discussão “Storyboards versus UI programaticamente” totalmente válida. É importante entender que existem duas (ou até mais) formas diferentes de resolver os mesmos problemas. Sempre gostei da forma que XIBs e Storyboards facilitam e agilizam o desenvolvimento de views e view controllers. Além disso, acho que são ferramentas insubstituíveis para o aprendizado de alguns conceitos do UIKit.&lt;/p&gt;

&lt;p&gt;Assim como em código, você precisa saber o que está fazendo ao usar um Storyboard. O propósito do Storyboard é você simplificar um fluxo de view controllers que estão interconectadas. Como o meu caro amigo Diogo apontou no &lt;a href=&quot;http://invariante.com/2015/10/20/todo-view-controller-deveria-ter-delegate/&quot;&gt;último post do Invariante&lt;/a&gt;, ao usar Storyboards você acaba acoplando o seu código, pois de uma forma ou outra suas view controllers vão saber da existência uma das outras. Mas será que isso é tão ruim assim quando você está falando de um Storyboard que representa um fluxo atômico no seu app (um fluxo de cadastro ou de tutorial, por exemplo) onde realmente não existe uma complexidade que justifique esse isolamento entre suas view controllers? Para mim, faz parte do &lt;em&gt;toolset&lt;/em&gt; de um bom desenvolvedor iOS saber desenvolver fluxos simples e prototipar utilizando Storyboards.&lt;/p&gt;

&lt;p&gt;E existem também os (vários) casos em que Storyboards atrapalham mais do que ajudam. O modo como os Storyboards são implementados no UIKit fazem com que muitas vezes ele nos force a usar &lt;a href=&quot;https://en.wikipedia.org/wiki/Anti-pattern&quot;&gt;anti-patterns&lt;/a&gt; como &lt;a href=&quot;https://en.wikipedia.org/wiki/God_object&quot;&gt;God Object&lt;/a&gt; (onde um objeto sabe ou faz muito, violando o &lt;a href=&quot;https://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;Princípio de Responsabilidade Única&lt;/a&gt;), &lt;a href=&quot;https://en.wikipedia.org/wiki/Magic_string#Magic_strings_in_code&quot;&gt;Magic Strings&lt;/a&gt;, ou &lt;a href=&quot;https://en.wikipedia.org/wiki/BaseBean&quot;&gt;BaseBean&lt;/a&gt; (forçar herança ao invés de delegação). Os Storyboards também são (justamente) conhecidos por aumentar o acoplamento do seu código, dificultando &lt;a href=&quot;https://pt.wikipedia.org/wiki/Injeção_de_dependência&quot;&gt;injeções de dependências&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;##O que é Injeção de Dependências mesmo?
O conceito de Injeção de Dependências pode ser difícil de se entender para desenvolvedores com pouca experiência, principalmente quando se está começando a programar (e muitas vezes é esquecido em projetos reais). Uma explicação simples seria mais ou menos assim:&lt;/p&gt;

&lt;p&gt;Teoricamente, você quer sempre deixar o seu código com o menor nível de acoplamento possível. Isso significa que cada módulo do seu sistema deve saber o mínimo possível sobre os outros módulos existentes para cumprir a sua funcionalidade. Injetar dependências signfica que cada módulo, ao ser criado, terá suas dependências configuradas por outro módulo do sistema, mantendo assim um baixo acoplamento.&lt;/p&gt;

&lt;p&gt;##Exemplo usando Storyboard&lt;/p&gt;

&lt;p&gt;Para ilustrar, temos o app abaixo, onde há um tela que busca uma imagem na internet e apresenta para usuário. A idéia é que o &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchAndDisplayImageViewController&lt;/code&gt; consiga buscar uma imagem através do &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchImageService&lt;/code&gt; e mostrar na sua &lt;code class=&quot;highlighter-rouge&quot;&gt;imageView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/euamostoryboard-1.png&quot; alt=&quot;Storyboard do projeto&amp;lt;3&quot; style=&quot;width: 100%; margin 0 auto 0 auto;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Em uma implementação mais ingênua do &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchAndDisplayImageViewController&lt;/code&gt; teríamos algo assim:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchAndDisplayImageViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//Image Service to fetch the image to display&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchImageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;//Image View utilizada para mostrar a imagem&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchImageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;param1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Invariante&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;param2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Rocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetchImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Acredito que seja fácil de perceber que essa implementação é, no mínimo, questionável, pois o &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchAndDisplayImageViewController&lt;/code&gt; sabe como instanciar o &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchImageService&lt;/code&gt;. Isso deixa o nosso código mais amarrado e faz com que nossa &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchAndDisplayImageViewController&lt;/code&gt; seja praticamente impossível de ser testada. Uma solução melhor é apresentada abaixo. Num post futuro mostrarei porque esse maior acoplamento (e a falta de injeção de dependência) torna o nosso código menos testável.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchAndDisplayImageViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//Image Service to fetch the image to display&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchImageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;//Image View utilizada para mostrar a imagem&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@IBOutlet&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
        
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;//Esperamos que alguém externo tenha configurado nossa dependência:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetchImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Não era para isso acontecer...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Desta forma, nós não instanciamos a nossa propriedade &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt;, mas ao invés disso, no &lt;code class=&quot;highlighter-rouge&quot;&gt;viewDidLoad&lt;/code&gt; esperamos que a propriedade &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt; tenha sido configurada por alguém.&lt;/p&gt;

&lt;p&gt;No post anterior o Diogo também comentou sobre a forma de se passar informações entre o nosso &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController&lt;/code&gt; e o &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchAndDisplayImageViewController&lt;/code&gt; quando utilizamos Storyboards. Essa seria a forma correta de setar a propriedade &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt; nessa abordagem:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prepareForSegue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;segue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIStoryboardSegue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ViewControllerToFetchAndDisplayImageViewControllerSegue&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;destinationViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destinationViewController&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchAndDisplayImageViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchImageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;param1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Invariante&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;param2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Rocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;destinationViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;E é aí que o Storyboard mostra sua fragilidade. Quantos problemas você consegue ver nos dois últimos trechos de código acima? Eu consigo citar alguns:&lt;/p&gt;

&lt;p&gt;1) A property &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt; é uma &lt;em&gt;var&lt;/em&gt;. Gostaríamos muito que ela fosse imutável (&lt;em&gt;let&lt;/em&gt;). Para isso precisaríamos setá-la no &lt;em&gt;init&lt;/em&gt; (e, por estarmos utilizando Storyboards, não temos como fazer isso);&lt;/p&gt;

&lt;p&gt;2) Essa mesma propriedade precisa ser &lt;em&gt;public&lt;/em&gt; ou &lt;em&gt;internal&lt;/em&gt; pois ela é setada por outra classe (ViewController). Idealmente, queremos que ela seja &lt;em&gt;private&lt;/em&gt;;&lt;/p&gt;

&lt;p&gt;3) Além disso, &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt; precisa ser um optional, o que acaba deixando o código mais verboso, pois precisamos sempre fazer o unwrap dessa variável ao usá-la;&lt;/p&gt;

&lt;p&gt;4) Por ser possível apresentar a &lt;code class=&quot;highlighter-rouge&quot;&gt;FetchAndDisplayImageViewController&lt;/code&gt; sem setar a &lt;em&gt;var&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt;, precisamos definir o comportamento da view controller caso isso aconteça.&lt;/p&gt;

&lt;p&gt;Que bagunça! E como a gente pode melhorar isso? Simples: não use Storyboards :)&lt;/p&gt;

&lt;p&gt;##Exemplo em código&lt;/p&gt;

&lt;p&gt;Veja que no código abaixo, agora é mandatório que o &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt; seja passado na inicialização da nossa classe. Assim, conseguimos fazer que a nossa propriedade &lt;code class=&quot;highlighter-rouge&quot;&gt;imageService&lt;/code&gt; seja privada e imutável (e, claro, não-opcional).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchAndDisplayImageViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//Image Service to fetch the image to display&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//Note que agora nossa propriedade é imutável (let), além de ser privada.&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchImageService&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;//Image View utilizada para mostrar a imagem&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
    
    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FetchImageService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nibName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coder&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;init(coder:) has not been implemented&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loadView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImageView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//Adicionar constraints manualmente.&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;//Sabemos que nossa dependência foi configurada no `init`&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;imageView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imageService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetchImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;##Entendi! Agora eu também odeio Storyboards!&lt;/p&gt;

&lt;p&gt;Pode ter certeza que você não está sozinho, mas infelizmente não compartilho da mesma opinião. Como eu falei, sou fã de Storyboards e acho sim que eles tem um papel importantíssimo no desenvolvimento de apps. É importante saber discernir os momentos certos de utilizar ou não Storyboards. Não acredito que as abordagens acima utilizando Storyboards estejam &lt;strong&gt;necessariamente&lt;/strong&gt; erradas. É tudo uma questão de saber o que está fazendo e escolher a ferramenta certa para cada problema.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Fique a vontade para discutir os artigos do &lt;em&gt;Invariante&lt;/em&gt; no &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;Slack do iOSDevBR&lt;/a&gt;. Temos alguns canais como o &lt;em&gt;#general&lt;/em&gt;, &lt;em&gt;#code-help&lt;/em&gt;, &lt;em&gt;#learn&lt;/em&gt;, &lt;em&gt;#swift&lt;/em&gt;, entre outros. A galera lá está sempre disposta a ajudar e esclarecer dúvidas :)&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Bruno Koga &lt;br /&gt;
&lt;a href=&quot;http://twitter.com/brunokoga&quot;&gt;@brunokoga&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Todo View Controller deveria ter um delegate</title>
   <link href="http://invariante.com/2015/10/20/todo-view-controller-deveria-ter-delegate/"/>
   <updated>2015-10-20T00:00:00+00:00</updated>
   <id>http://invariante.com/2015/10/20/todo-view-controller-deveria-ter-delegate</id>
   <content type="html">&lt;p&gt;Qualquer pessoa que frequente o &lt;em&gt;slack&lt;/em&gt; do &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;iOS Dev BR&lt;/a&gt; sabe que ando insatisfeito com &lt;code class=&quot;highlighter-rouge&quot;&gt;Storyboard&lt;/code&gt;. Os motivos são vários mas hoje vou falar apenas de um, as &lt;code class=&quot;highlighter-rouge&quot;&gt;segues&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As &lt;code class=&quot;highlighter-rouge&quot;&gt;segues&lt;/code&gt; facilitam a visualização do fluxo do &lt;em&gt;app&lt;/em&gt; para uma pessoa que não está habituada com o projeto. É só abrir o &lt;code class=&quot;highlighter-rouge&quot;&gt;storyboard&lt;/code&gt; (ou &lt;code class=&quot;highlighter-rouge&quot;&gt;storyboards&lt;/code&gt;) e está tudo lá, todas as &lt;em&gt;setinhas&lt;/em&gt; ligando seus &lt;em&gt;controllers&lt;/em&gt;. Ai você me pergunta: &lt;em&gt;“Mas isso é lindo, porque te incomoda?”&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;[self performSegueWithIdentifier:@&quot;Segue&quot; sender:result];&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O que você acha desse trecho de código? Não me refiro a aquela bela &lt;em&gt;string&lt;/em&gt; &lt;em&gt;mágica&lt;/em&gt;, mas &lt;strong&gt;onde&lt;/strong&gt; essa linha normalmente fica. Essa instrução está contida no &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; e é executada quando o mesmo terminou seu propósito e o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller B&lt;/code&gt; deve ser instanciado para continuar o fluxo.&lt;/p&gt;

&lt;p&gt;Isso implica que o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; tem algum conhecimento do que deve acontecer depois dele, se eu quiser trocar o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller B&lt;/code&gt; por um &lt;code class=&quot;highlighter-rouge&quot;&gt;controller C&lt;/code&gt; eu poderia manter o nome da &lt;code class=&quot;highlighter-rouge&quot;&gt;segue&lt;/code&gt; e fazer a alteração somente no &lt;code class=&quot;highlighter-rouge&quot;&gt;storyboard&lt;/code&gt;, isso seria deselegante mas não um problema. Agora imagine que  o &lt;em&gt;controller&lt;/em&gt; a ser instanciado a seguir dependa de algum resultado anterior a &lt;code class=&quot;highlighter-rouge&quot;&gt;segue&lt;/code&gt;, quem deve decidir qual &lt;code class=&quot;highlighter-rouge&quot;&gt;segue&lt;/code&gt; deve ser chamada? Na grande maioria dos códigos que vi (talvez não sejam tantos assim) o próprio &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; é responsável por tomar essa decisão. Isso não me cheira bem (vulgo &lt;a href=&quot;https://en.wikipedia.org/wiki/Code_smell&quot;&gt;code smell&lt;/a&gt;), mas vamos continuar…&lt;/p&gt;

&lt;p&gt;Bom, em qualquer app, alguma hora, você vai precisar passar informação entre os &lt;em&gt;controllers&lt;/em&gt; e como você faz isso?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@&quot;SegueB&quot;]) {
        MYControllerB *controller = segue.destinationViewController;
        controller.propertyB = sender;
    } else if ([segue.identifier isEqualToString:@&quot;SegueC&quot;]) {
        MYControllerC *controller = segue.destinationViewController;
        controller.propertyC = sender;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Se antes não estava cheirando bem, agora o cheiro está pior que  o Rio Pinheiros ali na estação Vila Olímpia! As &lt;em&gt;strings&lt;/em&gt; &lt;em&gt;mágicas&lt;/em&gt; continuam por aí, temos um &lt;code class=&quot;highlighter-rouge&quot;&gt;sender&lt;/code&gt; que pode ser qualquer coisa e, por último mas o pior de todos, o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; &lt;em&gt;sabe&lt;/em&gt; sobre o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller B&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;controller C&lt;/code&gt;. &lt;em&gt;“Mas porque isso é tão ruim?”&lt;/em&gt; Esse acoplamento dificulta muito a substituição de qualquer uma das três classes, faz com que seja muito mais complexo para testar essa classe pois não há como fazer injeção de dependência (&lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_injection&quot;&gt;Dependency Injection&lt;/a&gt;) e esse &lt;code class=&quot;highlighter-rouge&quot;&gt;if else if ...&lt;/code&gt; interminável é deselegante (sim, eu sei que em &lt;em&gt;Swift&lt;/em&gt; seria um &lt;code class=&quot;highlighter-rouge&quot;&gt;switch&lt;/code&gt; menos deselegante).&lt;/p&gt;

&lt;p&gt;Depois de todo esse discurso &lt;em&gt;anti-&lt;/em&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Storyboard&lt;/code&gt; imagino os defensores dessa &lt;em&gt;“tecnologia”&lt;/em&gt; estejam incomodados, para eles tenho duas coisas a dizer: Primeiro eu acredito que existem situações em que &lt;code class=&quot;highlighter-rouge&quot;&gt;Storyboards&lt;/code&gt; são adequados, projetos grandes e que vão durar muitos anos não se enquadram nessas situações (estou disposto a discutir esse assunto em uma outra ocasião); Segundo, fazendo a transição de &lt;em&gt;controllers&lt;/em&gt; sem &lt;code class=&quot;highlighter-rouge&quot;&gt;segue&lt;/code&gt; vemos o mesmo acoplamento:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;if (something) {
    MYControllerB *controller = [[MYControllerB alloc] initWithThing:aThing];
    [self.navigationController pushViewController:controller animated:YES];
} else if (otherthing) {
    MYControllerC *controller = [[MYControllerC alloc] initWithThing:aThing2];
    [self presentViewController:controller animated:YES completion:nil];
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nesse caso algo ruim que era resolvido pelo &lt;code class=&quot;highlighter-rouge&quot;&gt;segue&lt;/code&gt; acontece, o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; tem a responsabilidade de escolher como os outros &lt;em&gt;controllers&lt;/em&gt; serão apresentados e ainda esperar que ele próprio esteja dentro de um &lt;code class=&quot;highlighter-rouge&quot;&gt;UINavigationController&lt;/code&gt;, nada bom.&lt;/p&gt;

&lt;p&gt;Existe um conceito chamado de &lt;em&gt;Princípio de responsabilidade única&lt;/em&gt; (não sei se essa seria a tradução mais adequada, &lt;a href=&quot;https://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;Single responsibility principle&lt;/a&gt;), ele diz cada classe deve ter apenas uma responsabilidade ou, como diria o &lt;a href=&quot;https://en.wikipedia.org/wiki/Agent_Smith&quot;&gt;Agent Smith&lt;/a&gt;, um &lt;strong&gt;propósito&lt;/strong&gt;. Imaginemos que o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; tenha o propósito de obter a idade do usuário, então dele deve ser criado quando o &lt;em&gt;app&lt;/em&gt; precisar obter essa informação e a única coisa que o &lt;em&gt;controller&lt;/em&gt; precisa fazer é obter esse informação. Não faz parte do propósito dele ter conhecimento (&lt;em&gt;importar&lt;/em&gt;) classes que não tenham relação direta com seu propósito, em particular, classes que venham antes ou depois dele no fluxo. Muito menos &lt;strong&gt;decidir&lt;/strong&gt;, com base nessa informação, qual seria o próximo passo no fluxo do &lt;em&gt;app&lt;/em&gt;, &lt;strong&gt;instanciar&lt;/strong&gt; o próximo controller e passar a informação para ele, &lt;strong&gt;decidir&lt;/strong&gt; como esse controller será apresentado e &lt;strong&gt;apresentá-lo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Esse é um problema que vem me incomodando faz algum tempo, há um ano li um artigo falando sobre &lt;a href=&quot;http://albertodebortoli.github.io/blog/2014/09/03/flow-controllers-on-ios-for-a-better-navigation-control/&quot;&gt;Flow Controllers&lt;/a&gt;, achei interessante, ele resolve o problema da injeção de dependência, mas o &lt;em&gt;controller&lt;/em&gt; ainda tem a responsabilidade de dizer qual é o próximo passo no fluxo do &lt;em&gt;app&lt;/em&gt; e eu acredito que isso não faz parte do propósito dele.&lt;/p&gt;

&lt;p&gt;Uma possível solução para isso é postular que:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Todo &lt;code class=&quot;highlighter-rouge&quot;&gt;view controller&lt;/code&gt; tem que ter um &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;Um &lt;code class=&quot;highlighter-rouge&quot;&gt;view controller&lt;/code&gt; não deve usar referências a &lt;code class=&quot;highlighter-rouge&quot;&gt;parentViewController&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;navigationController&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;tabBarController&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;splitViewControoler&lt;/code&gt;, ou &lt;code class=&quot;highlighter-rouge&quot;&gt;presentingViewController&lt;/code&gt; ou qualquer outro &lt;em&gt;parent controller&lt;/em&gt; que inventarem;&lt;/li&gt;
  &lt;li&gt;Um &lt;code class=&quot;highlighter-rouge&quot;&gt;view controller&lt;/code&gt; só pode fazer (&lt;code class=&quot;highlighter-rouge&quot;&gt;#include&lt;/code&gt;) de outros &lt;code class=&quot;highlighter-rouge&quot;&gt;view controllers&lt;/code&gt; se esses forem necessários para cumprir seu propósito;&lt;/li&gt;
  &lt;li&gt;Quando um &lt;code class=&quot;highlighter-rouge&quot;&gt;view controller&lt;/code&gt; completar seu propósito ele notifica seu &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt; e esse é responsável por continuar o fluxo;&lt;/li&gt;
  &lt;li&gt;Um &lt;code class=&quot;highlighter-rouge&quot;&gt;view controller&lt;/code&gt; nunca deve usar &lt;code class=&quot;highlighter-rouge&quot;&gt;segues&lt;/code&gt;, isso não faz parte do seu propósito.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uma maneira de satisfazer essas condições é ter uma classe que é &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt; de todos os &lt;code class=&quot;highlighter-rouge&quot;&gt;view controllers&lt;/code&gt;, que sabe instanciar todos os &lt;code class=&quot;highlighter-rouge&quot;&gt;view controller&lt;/code&gt; e inclusive quais modelos são necessários para isso. Isso não me cheira muito bem, mas é melhor que antes. Como ainda é uma das primeiras interações alguma hora deve aparecer alguma idéia (aceito sugestões).&lt;/p&gt;

&lt;p&gt;Penso que esse &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt; deve ser o primeiro &lt;code class=&quot;highlighter-rouge&quot;&gt;controller&lt;/code&gt; do &lt;em&gt;app&lt;/em&gt;, por exemplo, uma subclasse do &lt;code class=&quot;highlighter-rouge&quot;&gt;UINavigationController&lt;/code&gt;.
Essa abordagem tem algumas vantagens:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Pode ser uma maneira de começar a migrar um &lt;em&gt;app&lt;/em&gt; para &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt; pois, normalmente, a essa &lt;em&gt;controller&lt;/em&gt; inicial é padrão e não tem muita interação com outros &lt;em&gt;controllers&lt;/em&gt;. Além disso os novos &lt;em&gt;controllers&lt;/em&gt; irão interagir somente com esse, além dos modelos e a camada de rede;&lt;/li&gt;
  &lt;li&gt;Todo o fluxo do &lt;em&gt;app&lt;/em&gt; fica em apenas uma classe e não espalhado por vários lugares;&lt;/li&gt;
  &lt;li&gt;Como o &lt;em&gt;delegate&lt;/em&gt; sabe instanciar todos os &lt;em&gt;controllers&lt;/em&gt;, ele pode receber o &lt;em&gt;roteamento&lt;/em&gt; vindo de &lt;em&gt;deep links&lt;/em&gt; ou &lt;code class=&quot;highlighter-rouge&quot;&gt;NSUserActivity&lt;/code&gt; sem dificuldade;&lt;/li&gt;
  &lt;li&gt;Se você quiser fazer uma classe especial para mostrar notificações ou &lt;code class=&quot;highlighter-rouge&quot;&gt;popups&lt;/code&gt; personalizados, o delegate seria o cara ideal para gerenciar quando e como eles devem ser apresentados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Um exemplo pode deixar as coisas mais claras. Um &lt;em&gt;app&lt;/em&gt; tem dois &lt;em&gt;view controllers&lt;/em&gt;. O responsável pelo primeira tela (&lt;code class=&quot;highlighter-rouge&quot;&gt;DTRootViewController&lt;/code&gt;) em &lt;code class=&quot;highlighter-rouge&quot;&gt;Objective-c&lt;/code&gt;, o propósito dele é obter do usuário um texto, sua interface seria:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;@interface DTRootViewController : UIViewController

@property (nonatomic, weak) id&amp;lt;DTRootViewControllerDelegate&amp;gt; delegate;

@end

@protocol DTRootViewControllerDelegate &amp;lt;ViewControllerDelegate&amp;gt;

- (void)didSelectedText:(nullable NSString *)text
   onRootViewController:(nonnull DTRootViewController *)controller;

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O segundo &lt;em&gt;view controller&lt;/em&gt;, em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;, (&lt;code class=&quot;highlighter-rouge&quot;&gt;OtherViewController&lt;/code&gt;) tem como propósito mostrar um texto, e  sua interface pública seria:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewControllerDelegate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ViewControllerDelegate&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shouldDismissOtherViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewController&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;navigationCloseButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewControllerDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O &lt;em&gt;view controller&lt;/em&gt; primário desse &lt;em&gt;app&lt;/em&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;NavigationController&lt;/code&gt;) é uma subclasse do &lt;code class=&quot;highlighter-rouge&quot;&gt;UINavigationController&lt;/code&gt; (também em &lt;code class=&quot;highlighter-rouge&quot;&gt;Swift&lt;/code&gt;) e sua implementação seria:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NavigationController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UINavigationController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DTRootViewControllerDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewControllerDelegate&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;awakeFromNib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DTRootViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setViewControllers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// MARK: DTRootViewController&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;didSelectedText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onRootViewController&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DTRootViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;presentOtherViewControllerWithText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;do nothing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// MARK: OtherViewController&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;presentOtherViewControllerWithText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;localizedCaseInsensitiveContainsString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;modal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;navigationCloseButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;presentViewControllerWithNavigationController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;localizedCaseInsensitiveContainsString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;push&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;navigationCloseButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pushViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shouldDismissOtherViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OtherViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dismissViewControllerAnimated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// MARK:&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;presentViewControllerWithNavigationController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                         &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;navigation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UINavigationController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rootViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;presentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;navigation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O projeto completo se encontra no &lt;a href=&quot;https://github.com/diogot/ViewControllerDelegate&quot;&gt;github&lt;/a&gt;, mas olhando apenas a implementação do &lt;code class=&quot;highlighter-rouge&quot;&gt;NavigationController&lt;/code&gt; vemos que toda a lógica de fluxo de app está contida em apenas uma classe, dessa forma é possível apresentar o &lt;code class=&quot;highlighter-rouge&quot;&gt;OtherViewController &lt;/code&gt; tanto &lt;em&gt;modalmente&lt;/em&gt; quanto dentro do &lt;em&gt;navigation controller&lt;/em&gt; de maneira transparente, sem ter que alterar o &lt;em&gt;controller&lt;/em&gt; apresentado.&lt;/p&gt;

&lt;p&gt;Como eu disse anteriormente, eu ainda estou começando a utilizar essa abordagem e novos problemas e dificuldades devem aparecer com o uso. Minha intenção e fazer outros artigos sobre esse assunto conforme eu for desenvolvendo o tema, críticas, comentários e sugestões são bem vindos, o &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;Twitter&lt;/a&gt; e o &lt;a href=&quot;http://iosdevbr.herokuapp.com&quot;&gt;slack do iOS Dev BR&lt;/a&gt; são os canais mais fáceis.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Update 2015/10/20 13h&lt;/em&gt; - O &lt;a href=&quot;https://twitter.com/icastanheda&quot;&gt;Igor&lt;/a&gt; levantou um ponto que eu não tinha pensado, é possível se livrar sem grande dificuldade do acoplamento no &lt;code class=&quot;highlighter-rouge&quot;&gt;prepareForSegue:sender:&lt;/code&gt; usando uma subclasse da &lt;code class=&quot;highlighter-rouge&quot;&gt;UIStoryboardSegue&lt;/code&gt;, fazendo o acoplamento do &lt;code class=&quot;highlighter-rouge&quot;&gt;controller A&lt;/code&gt; com o &lt;code class=&quot;highlighter-rouge&quot;&gt;controller B&lt;/code&gt; dentro dessa classe. Acho uma solução bem razoável.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update 2015/10/20 23h&lt;/em&gt; - O &lt;a href=&quot;https://twitter.com/marcelofabri_&quot;&gt;Fabri&lt;/a&gt; comentou que existem várias iniciativas como o &lt;a href=&quot;https://github.com/krzyzanowskim/Natalie&quot;&gt;Natalie&lt;/a&gt; para resolver o problema das &lt;em&gt;strings mágicas&lt;/em&gt;, acho válido, mas preferia que houvesse alguma coisa nativa.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update 2014/11/22&lt;/em&gt; - O &lt;a href=&quot;https://twitter.com/talesp&quot;&gt;Tales&lt;/a&gt; apontou um ponto importante, nem sempre é possível usar um &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt;. Por exemplo quando o &lt;em&gt;view controller&lt;/em&gt; é subclasse de &lt;code class=&quot;highlighter-rouge&quot;&gt;UITableViewController&lt;/code&gt;. Casos em que um &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt; não é conveniente seria melhor usar propriedades que contém blocos que são chamados no lugar dos métodos do protocolo do &lt;code class=&quot;highlighter-rouge&quot;&gt;delegate&lt;/code&gt;. Nada impede que as duas maneiras sejam implementadas.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Como o &lt;strong&gt;Invariante&lt;/strong&gt; foi citado no &lt;strong&gt;Podcast do CocoaHeads Brasil&lt;/strong&gt;, acho justo retribuir a gentileza ;-)&lt;/p&gt;

&lt;p&gt;Essa semana saiu a terceira edição do Podcast semanal do CocoaHeads Brasil, nessa edição &lt;a href=&quot;https://twitter.com/diogot&quot;&gt;eu&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/brunokoga&quot;&gt;Bruno Koga&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/DougDiskin&quot;&gt;Douglas Fischer&lt;/a&gt; e &lt;a href=&quot;https://twitter.com/talesp&quot;&gt;Tales Pinheiro&lt;/a&gt; conversamos sobre as novidades do iOS 9, o podcast está disponível no
&lt;a href=&quot;https://itunes.apple.com/br/podcast/cocoaheads-brasil/id1044808957?l=en&amp;amp;mt=2&quot;&gt;iTunes&lt;/a&gt; e no &lt;a href=&quot;https://soundcloud.com/cocoaheadsbr/s01e02-novidades-do-ios9&quot;&gt;SoundCloud&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;https://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Tratamento de Erros em Swift</title>
   <link href="http://invariante.com/2015/10/04/Tratamento-de-Erros/"/>
   <updated>2015-10-04T00:00:00+00:00</updated>
   <id>http://invariante.com/2015/10/04/Tratamento-de-Erros</id>
   <content type="html">&lt;p&gt;Uma das grandes novidades do Swift 2 foi o suporte para tratamento de erros (em inglês, &lt;em&gt;error handling&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Mas o que isso quer dizer?&lt;/p&gt;

&lt;p&gt;Algumas operações (geralmente funções) não oferecem a garantia de completar sua execução ou mesmo de produzir um retorno útil. Em Swift, usamos &lt;em&gt;optionals&lt;/em&gt; para representar uma ausência de valor (&lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;). Porém, quando uma função retorna &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; pode ter acontecido um erro e, muitas vezes, queremos entender o que causou este erro, para que nosso programa possa responder de acordo. É importante diferenciar as diversas formas que uma operação pode falhar e comunicar ao usuário adequadamente.&lt;/p&gt;

&lt;p&gt;A forma mais comum de resolver o problema de tratamentos de erros com Objective-C é passar uma variável adicional de erro no método e, caso haja algum erro, o método fica responsável por popular essa variável com o objeto de erro, além de retornar &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Essa abordagem é confusa e não intuitiva. Esse é um exemplo comum em Objective-C:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kt&quot;&gt;NSString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&quot;...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// caminho para um arquivo&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;NSError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dataWithContentsOfFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O problema aqui é que não temos informações claras sobre a relação entre o retorno &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; e o erro &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt;. Se &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; for &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; isso significa que &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt; é não-&lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;? E se &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; for um objeto &lt;code class=&quot;highlighter-rouge&quot;&gt;NSData&lt;/code&gt; válido, significa que &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt; vai ser sempre &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;? Existe algum caso em que ambos &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt; são populados? Existe algum caso em que ambos &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt; são &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Uma forma ingênua de resolver o problema em Swift de maneira similar (e carregar os mesmos efeitos colaterais da abordagem) seria termos funções que retornam uma tupla:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dataWithContentsOfFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Aqui, novamente, não existe relação entre os valores retornados na tupla e, pior, como precisamos retornar &lt;code class=&quot;highlighter-rouge&quot;&gt;optionals&lt;/code&gt; (afinal, os valores podem ser nulos), o código fica totalmente deselegante.&lt;/p&gt;

&lt;h2 id=&quot;e-agora&quot;&gt;E agora?&lt;/h2&gt;

&lt;p&gt;O Swift 2 resolve o problema introduzindo uma sintaxe adequada para o tratamento de erros.&lt;/p&gt;

&lt;p&gt;Para os exemplos desse artigo, vamos criar uma camada de abstração sobre o &lt;a href=&quot;https://developer.apple.com/library/prerelease/ios/documentation/AddressBook/Reference/AddressBook_iPhoneOS_Framework/&quot;&gt;AddressBook&lt;/a&gt;. Apesar de muitas das funcionalidades do AddressBook terem sido &lt;em&gt;deprecated&lt;/em&gt; no iOS 9 (graças ao &lt;a href=&quot;https://developer.apple.com/library/prerelease/ios/documentation/Contacts/Reference/Contacts_Framework/index.html#//apple_ref/doc/uid/TP40015328&quot;&gt;Contacts Framework&lt;/a&gt;), ele ainda é importante para apps que suportam acesso aos contatos no iOS 8. A idéia dessa camada é, exatamente, facilitar a transição para o &lt;code class=&quot;highlighter-rouge&quot;&gt;Contacts Framework&lt;/code&gt; no futuro, minimizando o impacto no nosso código.&lt;/p&gt;

&lt;p&gt;Primeiramente, vamos falar sobre o protocolo &lt;code class=&quot;highlighter-rouge&quot;&gt;ErrorType&lt;/code&gt;. Ele é declarado na biblioteca padrão do Swift da seguinte forma:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ErrorType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Isso mesmo. Ele é um protocolo vazio. Isso quer dizer que qualquer tipo de dado pode ser usado para representar um erro.&lt;/p&gt;

&lt;p&gt;Em Swift, a melhor forma de representar erros é com &lt;em&gt;enums&lt;/em&gt; (adotando o protocolo &lt;code class=&quot;highlighter-rouge&quot;&gt;ErrorType&lt;/code&gt;). É importante lembrar que podemos passar valores associados a esses enums, possibilitando adicionar alguma informação relevante sobre a natureza do erro. Nesse artigo, porém, não falaremos de valores associados.&lt;/p&gt;

&lt;p&gt;Para o nosso exemplo, temos a seguinte &lt;em&gt;struct&lt;/em&gt;, que representará a nossa camada sobre o AddressBook. O importante aqui é saber que essa &lt;em&gt;struct&lt;/em&gt; pode ser inicializada tanto passando um &lt;code class=&quot;highlighter-rouge&quot;&gt;ABAddressBook&lt;/code&gt; como parâmetro ou inicializar com o &lt;code class=&quot;highlighter-rouge&quot;&gt;ABAddressBook&lt;/code&gt; padrão:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAddressBook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;unmanagedAddressBookRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAddressBookCreateWithOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;addressBookRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unmanagedAddressBookRef&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;takeRetainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAddressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;E, para representar nossos erros, vamos declarar o seguinte enum (dentro de uma extension de &lt;code class=&quot;highlighter-rouge&quot;&gt;AddressBookPermission&lt;/code&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ErrorType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NotAuthorized&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ContactCouldNotBeCreated&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Agora, vamos criar uma função no nosso &lt;code class=&quot;highlighter-rouge&quot;&gt;AddressBookPermission&lt;/code&gt; onde recebemos um &lt;code class=&quot;highlighter-rouge&quot;&gt;CFData&lt;/code&gt; contendo o vCard a ser adicionado ao &lt;em&gt;Address Book&lt;/em&gt; e retornamos um array de Strings com os IDs adicionados:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CFData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note que o retorno da nossa função &lt;strong&gt;não&lt;/strong&gt; é um &lt;em&gt;optional&lt;/em&gt;, ou seja, nós garantimos que vamos retornar um Array de Strings (nem que ele seja vazio). Mas nossa função pode não conseguir completar a sua tarefa e se deparar com algum erro no seu caminho. Além disso, queremos determinar de forma clara a diferença entre retornar um Array vazio (ou seja, não havia nenhum contato no vCard) ou “retornar” um erro (ou seja, alguma coisa realmente deu errado).&lt;/p&gt;

&lt;p&gt;Para isso, vamos adicionar o &lt;em&gt;keyword&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;throws&lt;/code&gt; na nossa função. Como somos bons cidadãos, também vamos documentar (uso o &lt;a href=&quot;https://github.com/onevcat/VVDocumenter-Xcode&quot;&gt;VVDocumenter&lt;/a&gt; para isso):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;cm&quot;&gt;/**
    Adds contacts (in form of vCard data) to the Address Book.
    
    - parameter vCardData: The vCardData to be added.
    
    - throws: AddressBookPermissionError.NotAuthorized if the user has denied access to the Address Book.
    
    	AddressBookPermissionError.ContactCouldNotBeCreated contact couldn't not be created for any other reason.
    
    - returns: the new Contact IDs as a [String]
    */&lt;/span&gt;
    
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CFData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nota: como utilizamos a sintaxe do Swift para documentação, é assim que vemos nossos comentários ao clicarmos com ⌥+click na chamada na nossa função:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/error-handling-1.png&quot; alt=&quot;Boa documentação &amp;lt;3&quot; style=&quot;width: 100%; margin 0 auto 0 auto;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A declaração da nossa função agora diz que ela retorna um Array de Strings, mas &lt;strong&gt;ao invés disso&lt;/strong&gt; ela pode terminar a execução no meio e jogar um  erro.&lt;/p&gt;

&lt;p&gt;Nesse caso, existem dois tipos de erros que nos interessa: ou o usuário não deu permissão para acessar o Address Book (.NotAuthorized) ou o contato não pôde ser criado por qualquer outro motivo (falta de espaço em disco, dados corrompidos, etc: .ContactCouldNotBeCreated). Esse é o corpo da nossa função (não se assuste com as chamadas C-style da API do &lt;code class=&quot;highlighter-rouge&quot;&gt;ABAddressBook&lt;/code&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;cm&quot;&gt;/**
    Adds contacts (in form of vCard data) to the Address Book.
    
    - parameter vCardData: The vCardData to be added.
    
    - throws: AddressBookPermissionError.NotAuthorized if the user has denied access to the Address Book.
    
        AddressBookPermissionError.ContactCouldNotBeCreated contact couldn't not be created for any other reason.
    
    - returns: the new Contact IDs as a [String]
    */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CFData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;authorizationStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Authorized&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NotAuthorized&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;contactIds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;defaultSource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAddressBookCopyDefaultSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;takeRetainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vCardPeople&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABPersonCreatePeopleInSourceWithVCardRepresentation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaultSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;takeRetainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ABRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vCardPeople&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;addRecordError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unmanaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CFError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAddressBookAddRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRecordError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;recordId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABRecordGetRecordID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;contactIdString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recordId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;contactIds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contactIdString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addRecordError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;takeRetainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;kt&quot;&gt;ABAddressBookRevert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;kABOperationNotPermittedByUserError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NotAuthorized&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;kABOperationNotPermittedByStoreError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;fallthrough&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ContactCouldNotBeCreated&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ContactCouldNotBeCreated&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;kt&quot;&gt;ABAddressBookSave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addressBookRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contactIds&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nas duas primeiras linhas, checamos se estamos autorizados a acessar o Address Book. Essa é a implementação da função &lt;code class=&quot;highlighter-rouge&quot;&gt;authorizationStatus()&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;cm&quot;&gt;/**
    Checks our current ABAuthorizationStatus.
    
    - returns: The current ABAuthorizationStatus
    */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;authorizationStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAuthorizationStatus&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;authorizationStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ABAddressBookGetAuthorizationStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authorizationStatus&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Se não tivermos acesso, nós jogamos um erro. Nesse caso, a execução da função é encerrada (e não há retorno!). Caso contrário, continuamos a execução. Utilizamos a API do &lt;code class=&quot;highlighter-rouge&quot;&gt;ABAddressBook&lt;/code&gt; para criar um array de &lt;code class=&quot;highlighter-rouge&quot;&gt;ABRecord&lt;/code&gt; a partir do nosso vCard (um vCard pode ter mais de um contato). A partir daí iteramos sobre esse Array, criando os contatos no nosso AddressBook. Na implementação apresentada, se tivermos &lt;em&gt;qualquer erro&lt;/em&gt; durante esse processo, nós revertemos o AddressBook para o estado inicial e jogamos o erro apropriado (fazendo um mapeamento dos &lt;code class=&quot;highlighter-rouge&quot;&gt;CFError&lt;/code&gt; criados pela função &lt;code class=&quot;highlighter-rouge&quot;&gt;ABAddressBookAddRecord&lt;/code&gt; para &lt;code class=&quot;highlighter-rouge&quot;&gt;ErrorType&lt;/code&gt;). Caso tudo ocorra bem, salvamos o AddressBook e retornamos o Array de IDs (String) criados.&lt;/p&gt;

&lt;h2 id=&quot;ok-entendi-mas-como-uso-isso-agora&quot;&gt;Ok, entendi. Mas como uso isso agora?&lt;/h2&gt;

&lt;p&gt;Bom, agora vamos criar o código que vai utilizar nossa função. Se tentarmos escrever algo assim:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;permission&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mainBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pathForResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vcard&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ofType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vcf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;contentsOfFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//ignoramos o return&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;O compilador nos dará o erro “Call can throw, but it is not marked with ‘try’ and the error is not handled”.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/error-handling-2.png&quot; alt=&quot;Cadê o try?&quot; style=&quot;width: 100%; margin 0 auto 0 auto;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;faa-tente-capture&quot;&gt;Faça, tente, capture.&lt;/h2&gt;

&lt;p&gt;Existem quatro formas de manipular erros em Swift. Você pode propagar o erro, tratar o erro com &lt;code class=&quot;highlighter-rouge&quot;&gt;do-catch&lt;/code&gt;, tratar o erro como um valor opcional ou você pode forçar a chamada sem tratar o erro (e caso o erro ocorra você terá um crash - similar a forçar um desempacotamento de opcional quando ele é &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;É importante lembrar que quando uma função lança um erro (lançar = &lt;em&gt;throw&lt;/em&gt;), o fluxo do seu programa sofre uma alteração. É importante identificar e tratar corretamente os lugares onde erros podem ser lançados.&lt;/p&gt;

&lt;h3 id=&quot;propagar&quot;&gt;Propagar&lt;/h3&gt;

&lt;p&gt;No nosso exemplo, se quisermos simplesmente propagar o erro, podemos encapsular o nosso código em uma função e declarar que ela também lança (&lt;em&gt;throw&lt;/em&gt;) um erro. Além disso, precisamos marcar a(s) chamada(s) que podem lançar erros com &lt;code class=&quot;highlighter-rouge&quot;&gt;try&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addContacts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;permission&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mainBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pathForResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vcard&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ofType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vcf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;contentsOfFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//ignoramos o return&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;tratar-o-erro-com-do-catch&quot;&gt;Tratar o erro com do-catch&lt;/h3&gt;

&lt;p&gt;Você pode tratar um erro diretamente usando o &lt;code class=&quot;highlighter-rouge&quot;&gt;do-catch&lt;/code&gt;. Basicamente, você encapsula o código que pode lançar um erro dentro de um escopo &lt;code class=&quot;highlighter-rouge&quot;&gt;do&lt;/code&gt;, marca as chamadas pra funções que lançam erro com &lt;code class=&quot;highlighter-rouge&quot;&gt;try&lt;/code&gt; e captura os erros com &lt;code class=&quot;highlighter-rouge&quot;&gt;catch&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;permission&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mainBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pathForResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vcard&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ofType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vcf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;contentsOfFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NotAuthorized&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// Mostra um alert dizendo que não temos permissão e mostrando como dar permissão de acesso à agenda.&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ContactCouldNotBeCreated&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// Mostra um alert de que algo deu errado, mas que não sabemos exatamente o motivo.&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note que &lt;strong&gt;não&lt;/strong&gt; precisamos ter uma cláusula &lt;code class=&quot;highlighter-rouge&quot;&gt;catch&lt;/code&gt; para cada erro que possa ser lançado. Ao invés disso, podemos ter uma cláusula &lt;code class=&quot;highlighter-rouge&quot;&gt;catch&lt;/code&gt; que captura todos os demais erros (semelhante a um &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; no &lt;code class=&quot;highlighter-rouge&quot;&gt;switch&lt;/code&gt;) ou até mesmo tratar alguns erros e propagar outros (para isso, precisaríamos marcar nossa função com &lt;code class=&quot;highlighter-rouge&quot;&gt;throws&lt;/code&gt; novamente). Veja os exemplos:&lt;/p&gt;

&lt;p&gt;Aqui, capturamos todos os erros e tratamos da mesma forma:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;permission&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mainBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pathForResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vcard&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ofType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vcf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vCardData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;contentsOfFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// Aqui capturamos todos os erros da mesma forma.&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Aqui, tratamos um tipo de erro, mas propagamos os outros:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addContacts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;permission&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mainBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pathForResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vcard&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ofType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vcf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    	&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AddressBookPermission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NotAuthorized&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;c1&quot;&gt;// Tratamos esse caso&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;converter-erros-para-valores-opcionais&quot;&gt;Converter erros para valores opcionais&lt;/h3&gt;

&lt;p&gt;Você pode usar a sintaxe &lt;code class=&quot;highlighter-rouge&quot;&gt;try?&lt;/code&gt; para tratar o erro convertendo ele para um valor opcional. Isso quer dizer que, se um erro for lançado durante uma expressão marcada com &lt;code class=&quot;highlighter-rouge&quot;&gt;try?&lt;/code&gt;, o valor da expressão será &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt; (porém, você vai perder qualquer informação relacionada ao erro lançado, uma vez que usando &lt;code class=&quot;highlighter-rouge&quot;&gt;try?&lt;/code&gt; você abdica da capacidade de capturar o erro. Nosso código ficaria assim:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Caso um erro seja lançado, o valor de &lt;code class=&quot;highlighter-rouge&quot;&gt;ids&lt;/code&gt; será &lt;code class=&quot;highlighter-rouge&quot;&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;forar-no-erro&quot;&gt;Forçar “não-erro”&lt;/h3&gt;

&lt;p&gt;Seja porque você tem certeza que uma função não vai lançar um erro ou seja por pura displicência, você pode também usar a seguinte sintaxe para desabilitar completamente a propagação de erros. Note que, usando essa sintaxe, caso um erro seja lançado, você vai ter um erro de tempo de execução (e, claro, um crash):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;try!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permission&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addContactsFromVcard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vCardData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;defer&quot;&gt;Defer&lt;/h3&gt;

&lt;p&gt;Quando você declara uma função que pode lançar um erro, você pode usar o &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; para executar comandos momentos antes da execução do código deixar o bloco de código atual. O &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; é muito útil para garantir que um um certo código irá rodar independentemente de como o seu código terminou a execução (seja por um &lt;code class=&quot;highlighter-rouge&quot;&gt;return&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;throw&lt;/code&gt;, ou &lt;code class=&quot;highlighter-rouge&quot;&gt;break&lt;/code&gt;). Caso você tenha múltiplos &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt;, os códigos dentro de &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; são executados na ordem inversa da qual eles são declarados, ou seja, o código no primeiro &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; vai rodar depois do código no segundo &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; e assim por diante. Veja esse exemplo retirado do &lt;a href=&quot;https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html&quot;&gt;Swift Programming Language&lt;/a&gt;. Nesse código, o &lt;code class=&quot;highlighter-rouge&quot;&gt;defer&lt;/code&gt; garante que o arquivo será fechado:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;table style=&quot;border-spacing: 0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot; style=&quot;text-align: right&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;processFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;defer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;readline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Work with the file.&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// close(file) is called here, at the end of the scope.&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;isso--importante-mesmo&quot;&gt;Isso é importante mesmo?&lt;/h2&gt;

&lt;p&gt;Apesar do Swift 2 ser recente,  já existem muitos artigos e exemplos sobre tratamentos de erros em Swift. Além disso, com a promessa do Swift ter seu código aberto até o fim do ano, entender todas as capacidades da linguagem, o seu funcionamento e sua biblioteca padrão podem ser importantes mesmo se você não desenvolve ou não tem planos para desenvolver especificamente para o ecossistema da Apple. E tratamento de erros está enraizado tanto na filosofia como nas boas práticas do Swift.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Bruno Koga &lt;br /&gt;
&lt;a href=&quot;http://twitter.com/brunokoga&quot;&gt;@brunokoga&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>UIScrollView ao resgate, não tão rápido...</title>
   <link href="http://invariante.com/2015/09/20/UIScrollView-ao-resgate-nao-tao-rapido/"/>
   <updated>2015-09-20T00:00:00+00:00</updated>
   <id>http://invariante.com/2015/09/20/UIScrollView-ao-resgate-nao-tao-rapido</id>
   <content type="html">&lt;p&gt;Bem vindo ao Invariante, este é o nosso primeiro &lt;em&gt;post&lt;/em&gt;. A idéia do blog é postar no mínimo dois artigos por mês, se quiser saber mais sobre a gente vá em &lt;a href=&quot;/sobre&quot;&gt;Sobre&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;A cada ano aumenta a variedade de dispositivos iOS com tamanhos de telas diferentes e assim o &lt;em&gt;Auto Layout&lt;/em&gt; se torna cada vez mais importante no desenvolvimento. Já usei muito &lt;em&gt;autoresizingMask&lt;/em&gt; e calculei muito &lt;em&gt;frame&lt;/em&gt; na mão, mas tenho apreciado cada vez mais o &lt;em&gt;Auto Layout&lt;/em&gt; e tenho feito dele minha principal ferramenta de &lt;em&gt;layout&lt;/em&gt;.
Entretanto essa semana me deparei com um problema imune ao &lt;em&gt;Auto Layout&lt;/em&gt;, talvez devido minha falta de habilidade ¯\_(ツ)_/¯.&lt;/p&gt;

&lt;p&gt;A idéia é ter uma &lt;code class=&quot;highlighter-rouge&quot;&gt;View2&lt;/code&gt; que pertence a um &lt;em&gt;view controller&lt;/em&gt; 2 dentro de uma &lt;code class=&quot;highlighter-rouge&quot;&gt;View1&lt;/code&gt; pertencente a um &lt;em&gt;view controller&lt;/em&gt; 1. A &lt;code class=&quot;highlighter-rouge&quot;&gt;View2&lt;/code&gt; pode ter um tamanho arbitrário definido pelo &lt;em&gt;view controller&lt;/em&gt; 1.
A &lt;code class=&quot;highlighter-rouge&quot;&gt;View2&lt;/code&gt; irá conter uma imagem que deve ser centralizada, o tamanho dessa imagem é arbitrário e deve ser redimensionado de maneira que a distância do lado maior mais próximo da borda seja de &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; pontos.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/uiscrollview-1.jpg&quot; alt=&quot;UIScrollView1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Até ai nada de complicado, mas também é necessário que seja possível fazer &lt;em&gt;zoom&lt;/em&gt; e &lt;em&gt;scroll&lt;/em&gt; da imagem e a margem de &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; pontos seja mantida independente da ampliação.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/uiscrollview-2.jpg&quot; alt=&quot;UIScrollView2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bom nossa boa e velha amiga &lt;code class=&quot;highlighter-rouge&quot;&gt;UIScrollView&lt;/code&gt; parece ser uma ótima candidata para salvar o dia mas, para isso, precisamos entender melhor com ela funciona. Uma ótima referência é um artigo da edição sobre &lt;em&gt;views&lt;/em&gt; do objc.io, &lt;a href=&quot;https://www.objc.io/issues/3-views/scroll-view/&quot;&gt;Understanding Scroll Views&lt;/a&gt;. Vou resumir alguns conceitos básicos e colocar um pouco da minha visão mas o recomendo a leitura do artigo, assim como os outros artigos dessa edição sobre &lt;em&gt;views&lt;/em&gt;. Para entender como uma &lt;em&gt;scroll view&lt;/em&gt; funciona precisamos entender o que significam 3 propriedades: &lt;code class=&quot;highlighter-rouge&quot;&gt;contentOffset&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;contentInset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/uiscrollview-3.jpg&quot; alt=&quot;UIScrollView3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;##&lt;code class=&quot;highlighter-rouge&quot;&gt;contentOffset&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;O &lt;code class=&quot;highlighter-rouge&quot;&gt;contentOffset&lt;/code&gt; define a posição do &lt;em&gt;scroll&lt;/em&gt;, isto é, o deslocamento das &lt;em&gt;sub views&lt;/em&gt; da &lt;em&gt;scroll view&lt;/em&gt;. Na prática ela é a &lt;code class=&quot;highlighter-rouge&quot;&gt;origin&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;bounds&lt;/code&gt; da &lt;em&gt;scroll view&lt;/em&gt;, mas alguém poderia perguntar: a origem não é sempre &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0,0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;? Nem sempre, um ponto qualquer (&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;xS,yS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;) de uma &lt;code class=&quot;highlighter-rouge&quot;&gt;subView&lt;/code&gt; é convertido para o sistema de coordenadas (&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;x,y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;) de sua &lt;em&gt;super view&lt;/em&gt; (&lt;code class=&quot;highlighter-rouge&quot;&gt;view&lt;/code&gt;) da seguinte forma:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;x = xS + subView.frame.origin.x + view.bounds.origin.x
y = yS + subView.frame.origin.y + view.bounds.origin.y&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Como normalmente &lt;code class=&quot;highlighter-rouge&quot;&gt;view.bounds.origin = {0,0}&lt;/code&gt; para calcular a posição de um ponto qualquer da &lt;code class=&quot;highlighter-rouge&quot;&gt;subView &lt;/code&gt; na &lt;code class=&quot;highlighter-rouge&quot;&gt;view&lt;/code&gt; é só somar a origem do &lt;code class=&quot;highlighter-rouge&quot;&gt;frame&lt;/code&gt; da &lt;code class=&quot;highlighter-rouge&quot;&gt;subView&lt;/code&gt;.
Isso significa que quando mudamos a &lt;code class=&quot;highlighter-rouge&quot;&gt;origin&lt;/code&gt; do &lt;code class=&quot;highlighter-rouge&quot;&gt;bounds&lt;/code&gt; de uma &lt;em&gt;view&lt;/em&gt;, todas as suas &lt;em&gt;sub views&lt;/em&gt; vão ser deslocadas pela a mesma quantidade, truque maroto!&lt;/p&gt;

&lt;p&gt;Se consideramos que a &lt;code class=&quot;highlighter-rouge&quot;&gt;UIImageView&lt;/code&gt; tem &lt;code class=&quot;highlighter-rouge&quot;&gt;origin = {0,0}&lt;/code&gt; o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentOffset&lt;/code&gt; é a distância entre o canto superior esquerdo da &lt;em&gt;image view&lt;/em&gt; e o da &lt;em&gt;scroll view&lt;/em&gt;, como ilustrado na figura acima.&lt;/p&gt;

&lt;p&gt;##&lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;É o tamanho do conteúdo apresentado, no caso da figura o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt; é igual o &lt;code class=&quot;highlighter-rouge&quot;&gt;frame.size&lt;/code&gt; da &lt;em&gt;image view&lt;/em&gt;. Num caso geral ele só depende do tamanho e disposição das &lt;em&gt;sub views&lt;/em&gt;, nunca da &lt;em&gt;scroll view&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;##&lt;code class=&quot;highlighter-rouge&quot;&gt;contentInset&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Usado para definir uma margem para apresentação do conteúdo, por padrão seu valor é &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0,0,0,0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;, e portanto o tamanho da área que pode apresentar conteúdo é igual à &lt;code class=&quot;highlighter-rouge&quot;&gt;scrollView.frame&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quando o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt; for menor que o tamanho da &lt;em&gt;scroll view&lt;/em&gt; isso significa que as &lt;em&gt;sub views&lt;/em&gt; irão ficar no canto superior esquerda, fixas. Uma maneira de centralizar o conteúdo é colocar um &lt;em&gt;inset&lt;/em&gt; como metade da diferença de tamanho entre a &lt;em&gt;scroll view&lt;/em&gt; e o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;CGFloat xInset = (CGRectGetWidth(scrollView.frame) - scrollView.contentSize.width)/2.;
CGFloat yInset = (CGRectGetHeight(scrollView.frame) - scrollView.contentSize.height)/2.;

scrollView.contentInset = UIEdgeInsetsMake(yInset, xInset, yInset, xInset);&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Quando o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt; for maior que que a &lt;em&gt;scroll view&lt;/em&gt; o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentInset&lt;/code&gt; define os limites máximos de &lt;em&gt;scroll&lt;/em&gt;. Por exemplo no caso da &lt;code class=&quot;highlighter-rouge&quot;&gt;UIImageView&lt;/code&gt; que tem a &lt;code class=&quot;highlighter-rouge&quot;&gt;frame.origin = {0,0}&lt;/code&gt;, os limites da &lt;code class=&quot;highlighter-rouge&quot;&gt;UIImageView&lt;/code&gt; não podem “entrar” na área definida pelo &lt;code class=&quot;highlighter-rouge&quot;&gt;frame&lt;/code&gt; da &lt;em&gt;scrool view&lt;/em&gt; descontado o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentInset&lt;/code&gt;. A figura abaixo deve deixar isso mais claro.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/imgs/uiscrollview-4.jpg&quot; alt=&quot;UIScrollView4&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ok, agora fica fácil escrever o código que adiciona uma imagem à uma &lt;em&gt;scroll view&lt;/em&gt; e define essas propriedades corretamente:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;- (void)updateWithImage:(UIImage *)image
{
    UIScrollView *scrollView = self.scrollView;
    UIImageView *imageView = self.imageView;
    
    imageView.image = image;
    CGSize imageSize = image.size;
    CGRect imageFrame = CGRectMake(0, 0, imageSize.width, imageSize.height);
    
    imageView.frame = imageFrame;
    scrollView.contentSize = imageSize;
    
    CGRect scrollViewFrame = scrollView.frame;
    
    // Set Inset
    UIEdgeInsets insets = self.scrollViewDefaultInset;
    insets = [self insetsForContentFrame:imageFrame
               insideScrollViewWithFrame:scrollViewFrame
                       withDefaultInsets:insets];
    scrollView.contentInset = insets;
    
    // Set Zoom
    CGSize scrollViewSize = CGSizeMake(CGRectGetWidth(scrollViewFrame) - insets.left - insets.right,
                                       CGRectGetHeight(scrollViewFrame) - insets.top - insets.bottom);
    CGFloat xMinZoomScale = scrollViewSize.width/(imageSize.width + 2. * kMargin);
    CGFloat yMinZoomScale = scrollViewSize.height/(imageSize.height + 2. * kMargin);
    CGFloat minimumZoomScale = MIN(xMinZoomScale, yMinZoomScale);
    scrollView.minimumZoomScale = minimumZoomScale;
    scrollView.maximumZoomScale = minimumZoomScale * kMaxZoomFactor;
    
    // Fit on screen
    scrollView.zoomScale = minimumZoomScale;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Sendo que função que calcula os &lt;em&gt;insets&lt;/em&gt; é:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;- (UIEdgeInsets)insetsForContentFrame:(CGRect)contentFrame
            insideScrollViewWithFrame:(CGRect)scrollViewFrame
                    withDefaultInsets:(UIEdgeInsets)insets
{
    CGSize contentSize = contentFrame.size;
    CGSize scrollViewSize = CGSizeMake(CGRectGetWidth(scrollViewFrame) - insets.left - insets.right,
                                       CGRectGetHeight(scrollViewFrame) - insets.top - insets.bottom);
    CGFloat margin = kMargin;
    
    CGFloat xInset = MAX((scrollViewSize.width - contentSize.width)/2., margin);
    CGFloat yInset = MAX((scrollViewSize.height - contentSize.height)/2., margin);
    
    insets.left += xInset;
    insets.right += xInset;
    insets.top += yInset;
    insets.bottom += yInset;

    return insets;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Para habilitar o &lt;em&gt;zoom&lt;/em&gt; só falta implementar um método do &lt;code class=&quot;highlighter-rouge&quot;&gt;UIScrollViewDelegate&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Esse método apenas retorna qual a &lt;em&gt;view&lt;/em&gt; que será aplicado o &lt;em&gt;zoom&lt;/em&gt;, da primeira vez que vi achei muito estranho, mas entender como a &lt;code class=&quot;highlighter-rouge&quot;&gt;UIScrollView&lt;/code&gt; faz o &lt;em&gt;zoom&lt;/em&gt; tudo ficou muito mais claro.&lt;/p&gt;

&lt;p&gt;##Bônus: &lt;code class=&quot;highlighter-rouge&quot;&gt;zoomScale&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;UIScrollView&lt;/code&gt; faz &lt;em&gt;zoom&lt;/em&gt; aplicando uma transformação na &lt;em&gt;view&lt;/em&gt; retornada pelo método do &lt;em&gt;delagate&lt;/em&gt; descrito acima. Isto é, 
aplica uma &lt;code class=&quot;highlighter-rouge&quot;&gt;CGAffineTransform&lt;/code&gt; do tipo &lt;code class=&quot;highlighter-rouge&quot;&gt;CGAffineTransformMakeScale(zoomScale, zoomScale)&lt;/code&gt; na &lt;em&gt;subview&lt;/em&gt;. Isso faz com que o &lt;code class=&quot;highlighter-rouge&quot;&gt;frame&lt;/code&gt; da &lt;code class=&quot;highlighter-rouge&quot;&gt;subView&lt;/code&gt; seja alterado! E, portanto, o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt; da &lt;code class=&quot;highlighter-rouge&quot;&gt;scrollView&lt;/code&gt;, por isso sempre que o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentSize&lt;/code&gt; e, consequentemente, o &lt;code class=&quot;highlighter-rouge&quot;&gt;zoomScale&lt;/code&gt; forem alterados o &lt;code class=&quot;highlighter-rouge&quot;&gt;contentInset&lt;/code&gt; deve ser recalculado. Isso pode ser feito facilmente implementando mais um método do &lt;em&gt;delegate&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot; data-lang=&quot;objective-c&quot;&gt;- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
    UIEdgeInsets insets = self.scrollViewDefaultInset;
    
    insets = [self insetsForContentFrame:self.imageView.frame
               insideScrollViewWithFrame:scrollView.frame
                       withDefaultInsets:insets];
    
    scrollView.contentInset = insets;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A &lt;code class=&quot;highlighter-rouge&quot;&gt;UIScrollView&lt;/code&gt; é uma classe muito importante no &lt;code class=&quot;highlighter-rouge&quot;&gt;UIKit&lt;/code&gt;, seu funcionamento é muito simples, mas entender como ela exatamente funciona pode não ser uma tarefa muito simples.&lt;/p&gt;

&lt;p&gt;Um exemplo dessa solução funcionando pode ser encontrada no repositório &lt;a href=&quot;https://github.com/diogot/UIScrollView-Center&quot;&gt;UIScrollView-Center&lt;/a&gt;.
Qualquer dúvida, críticas e comentários são bem vindos, a maneira mais fácil de me encontrar é no &lt;a href=&quot;http://twitter.com/diogot&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Diogo Tridapalli &lt;br /&gt;
&lt;a href=&quot;http://twitter.com/diogot&quot;&gt;@diogot&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 

</feed>
