<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://manu.show/feed.xml" rel="self" type="application/atom+xml" /><link href="https://manu.show/" rel="alternate" type="text/html" /><updated>2026-02-01T10:30:24-05:00</updated><id>https://manu.show/feed.xml</id><title type="html">manu.show</title><subtitle>Software Engineering practices, tips, and general things that I&apos;ve learned over the years and want to share with the world.</subtitle><author><name>Manu</name></author><entry><title type="html">Good Work</title><link href="https://manu.show/2026-02-01-ep091-good-work/" rel="alternate" type="text/html" title="Good Work" /><published>2026-02-01T05:00:00-05:00</published><updated>2026-02-01T05:00:00-05:00</updated><id>https://manu.show/ep091-good-work</id><content type="html" xml:base="https://manu.show/2026-02-01-ep091-good-work/"><![CDATA[<p>These are some hand-written notes about the book <code class="language-plaintext highlighter-rouge">Good Work</code> by Paul Millerd.</p>

<p><img src="/resources/ep091-good-work/cover.webp" width="50%" /></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-notes">The Notes</a></li>
  <li><a href="#personal-takes">Personal Takes</a></li>
  <li><a href="#related-articles">Related Articles</a></li>
</ul>

<h1 id="the-notes">The Notes</h1>

<p><img src="/resources/ep091-good-work/good-work.webp" alt="notes" /></p>

<h1 id="personal-takes">Personal Takes</h1>

<p>Something that I found interesting about this book is that it seems written for people that don’t like their actual job situation, and that’s not something that happened to me during my 12 years of working in tech.</p>

<p>However, it talks about some interesting points, like the importance of facing your fears, and the relationship between money and time.</p>

<p>Even though I’ve always like being in the tech world, there are some thinking processes that this book triggered on me. For example, during this new era of AI development, my day to day work has changed, it’s more automated, and it doesn’t require as much grind as before (which could also be caused by being inside the industry for many years).</p>

<p>One example of something that used to cause my joy, but now it’s not as much, is the debugging process of a really hard problem. For example, debugging an issue for 3 days, losing my head, only to find out that the answer was a single line of code, was both frustrating and rewarding. Lately, I haven’t had experiences like that, and it’s not as much of a joy.</p>

<p>Another thing to consider regarding <code class="language-plaintext highlighter-rouge">Good Work</code> is that it’s not just about the job, but also about the people you work with. I’ve always liked the people I work with, but I think it’s important to consider the environment you work in, and the people you interact with. Having friends at work is always an extra motivation to perform at top level to not let them down. I’ve experienced this first hand over the past few years at different companies.</p>

<p>The book talks about taking some sabbatical time to reflect on your life and career. I honestly never thought about that, given I’ve always enjoyed my job. That’s not to say that I always have fun, I’ve my ups and downs, but I never reached the completely burnout point of thinking about sabbatical time.</p>

<p>The relationship about money and time is something I do think about often, I’m in my early 30s and I know that my energy now is really high, so it’s important to think about enjoying these years and not getting too focused on money. On the other side, compound interest is a topic that I’ve always liked, so turning down money now is not a smart decision. In conclusion, balance is really important, and it’s something that I consider from time to time, I tend to adapt my situation based on the current conditions, and my prediction of the near future.</p>

<p>I do recommend you to read this book, whether you like your current situation or not, given it’ll trigger some deep thinking processes that will benefit you anyways.</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-04-26-ep85-deep-work/">Deep Work</a></li>
  <li><a href="/2023-07-16-the-compound-effect/">The Compound Effect</a></li>
  <li><a href="/2023-06-11-die-with-zero/">Die with Zero</a></li>
  <li><a href="/2023-05-20-the-joy-of-less/">The Joy of Less</a></li>
  <li><a href="/2025-05-19-ep088-the-one-thing/">The ONE Thing</a></li>
  <li><a href="/2025-06-17-ep090-the-great-mental-models-1/">The Great Mental Models - Volume I</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Good Work | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="Good Work" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="These are some hand-written notes about the book Good Work by Paul Millerd." />

<meta property="og:description" content="These are some hand-written notes about the book Good Work by Paul Millerd." />

<link rel="canonical" href="https://manu.show/2026-02-01-ep091-good-work/" />

<meta property="og:url" content="https://manu.show/2026-02-01-ep091-good-work/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2026-02-01T05:00:00-05:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="Good Work" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2026-02-01T05:00:00-05:00","datePublished":"2026-02-01T05:00:00-05:00","description":"These are some hand-written notes about the book Good Work by Paul Millerd.","headline":"Good Work","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2026-02-01-ep091-good-work/"},"url":"https://manu.show/2026-02-01-ep091-good-work/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="books" /><summary type="html"><![CDATA[These are some hand-written notes about the book Good Work by Paul Millerd.]]></summary></entry><entry><title type="html">The Great Mental Models - Volume I</title><link href="https://manu.show/2025-06-17-ep090-the-great-mental-models-1/" rel="alternate" type="text/html" title="The Great Mental Models - Volume I" /><published>2025-06-17T06:00:00-04:00</published><updated>2025-06-17T06:00:00-04:00</updated><id>https://manu.show/ep090-the-great-mental-models-1</id><content type="html" xml:base="https://manu.show/2025-06-17-ep090-the-great-mental-models-1/"><![CDATA[<p>These are some hand-written notes about the book <code class="language-plaintext highlighter-rouge">The Great Mental Models - Volume I</code> by Shane Parrish.</p>

<p>This book was a recommendation from my great friend <a href="https://blog.nico.ninja/">Nico</a>. Go check out his blog if you are into home-automation, electronics, cybersecurity, habits, radio, or to find out about his latest obsession.</p>

<p><img src="/resources/ep090-the-great-mental-models-1/cover.webp" width="50%" /></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-notes">The Notes</a></li>
  <li><a href="#personal-takes">Personal Takes</a></li>
  <li><a href="#related-articles">Related Articles</a></li>
</ul>

<h1 id="the-notes">The Notes</h1>

<p><img src="/resources/ep090-the-great-mental-models-1/notes1.webp" alt="notes-1" />
<img src="/resources/ep090-the-great-mental-models-1/notes2.webp" alt="notes-2" /></p>

<h1 id="personal-takes">Personal Takes</h1>

<p>The book was really easy to read, I will continue to read the next volumes in the near future.</p>

<p>I will start applying the <code class="language-plaintext highlighter-rouge">Second-Order Thinking</code> model to my daily life. In combination with the <code class="language-plaintext highlighter-rouge">Inversion</code> model, I think it will be a great way to get more serious in terms of my diet, exercise, and overall fitness.</p>

<p>Another thing that I will keep in mind is the <code class="language-plaintext highlighter-rouge">Causation vs Correlation</code> relation. I will try to avoid making assumptions based on correlation, and instead try to understand the real causation behind it.</p>

<p>Finally, <code class="language-plaintext highlighter-rouge">Hanlon's Razor</code> is something that from time to time I forget, in particular, when driving, I tend to always be frustrated about other people’s behavior, but probably 99% of the time it’s not their fault, as they are just doing what they think is best.</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-04-26-ep85-deep-work/">Deep Work</a></li>
  <li><a href="/2023-07-16-the-compound-effect/">The Compound Effect</a></li>
  <li><a href="/2023-06-11-die-with-zero/">Die with Zero</a></li>
  <li><a href="/2023-05-20-the-joy-of-less/">The Joy of Less</a></li>
  <li><a href="/2025-05-19-ep088-the-one-thing/">The ONE Thing</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>The Great Mental Models - Volume I | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="The Great Mental Models - Volume I" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="These are some hand-written notes about the book The Great Mental Models - Volume I by Shane Parrish." />

<meta property="og:description" content="These are some hand-written notes about the book The Great Mental Models - Volume I by Shane Parrish." />

<link rel="canonical" href="https://manu.show/2025-06-17-ep090-the-great-mental-models-1/" />

<meta property="og:url" content="https://manu.show/2025-06-17-ep090-the-great-mental-models-1/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-06-17T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="The Great Mental Models - Volume I" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-06-17T06:00:00-04:00","datePublished":"2025-06-17T06:00:00-04:00","description":"These are some hand-written notes about the book The Great Mental Models - Volume I by Shane Parrish.","headline":"The Great Mental Models - Volume I","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-06-17-ep090-the-great-mental-models-1/"},"url":"https://manu.show/2025-06-17-ep090-the-great-mental-models-1/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="books" /><summary type="html"><![CDATA[These are some hand-written notes about the book The Great Mental Models - Volume I by Shane Parrish.]]></summary></entry><entry><title type="html">Skeleton Modifier</title><link href="https://manu.show/2025-06-15-ep089-skeleton-modifier/" rel="alternate" type="text/html" title="Skeleton Modifier" /><published>2025-06-15T06:00:00-04:00</published><updated>2025-06-15T06:00:00-04:00</updated><id>https://manu.show/ep089-skeleton-modifier</id><content type="html" xml:base="https://manu.show/2025-06-15-ep089-skeleton-modifier/"><![CDATA[<p>This is a simple modifier to add a shimmer-style animation to any SwiftUI view.</p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-code">The Code</a>
    <ul>
      <li><a href="#usage">Usage</a></li>
    </ul>
  </li>
  <li><a href="#demo">Demo</a></li>
</ul>

<h1 id="the-code">The Code</h1>

<script src="https://gist.github.com/mdb1/60dfd39fae233152ddcc01e569bab253.js"></script>

<h2 id="usage">Usage</h2>

<p>If you build your “loaded” state using parameters, like this:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">charactersView</span><span class="p">(</span><span class="nv">characters</span><span class="p">:</span> <span class="p">[</span><span class="kt">CharacterModel</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kt">ScrollView</span> <span class="p">{</span>
        <span class="kt">ForEach</span><span class="p">(</span><span class="n">characters</span><span class="p">,</span> <span class="nv">id</span><span class="p">:</span> <span class="p">\</span><span class="o">.</span><span class="n">id</span><span class="p">)</span> <span class="p">{</span> <span class="n">character</span> <span class="k">in</span>
            <span class="kt">ImageAndTextRow</span><span class="p">(</span>
                <span class="nv">imageURLString</span><span class="p">:</span> <span class="n">character</span><span class="o">.</span><span class="n">image</span><span class="p">,</span>
                <span class="nv">title</span><span class="p">:</span> <span class="n">character</span><span class="o">.</span><span class="n">fullName</span>
            <span class="p">)</span>
            <span class="o">.</span><span class="nf">padding</span><span class="p">(</span><span class="o">.</span><span class="n">horizontal</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
            <span class="o">.</span><span class="n">onTapGesture</span> <span class="p">{</span>
                <span class="n">router</span><span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="o">.</span><span class="nf">character</span><span class="p">(</span><span class="n">character</span><span class="p">))</span>
            <span class="p">}</span>
            <span class="kt">Divider</span><span class="p">()</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Then you can build your “loading” state using mocked information:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">loadingView</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="nf">charactersView</span><span class="p">(</span>
        <span class="nv">characters</span><span class="p">:</span> <span class="p">[</span>
            <span class="o">.</span><span class="nf">mock</span><span class="p">(</span><span class="nv">index</span><span class="p">:</span> <span class="mi">1</span><span class="p">),</span>
            <span class="o">.</span><span class="nf">mock</span><span class="p">(</span><span class="nv">index</span><span class="p">:</span> <span class="mi">2</span><span class="p">),</span>
            <span class="o">.</span><span class="nf">mock</span><span class="p">(</span><span class="nv">index</span><span class="p">:</span> <span class="mi">3</span><span class="p">)</span>
        <span class="p">]</span>
    <span class="p">)</span>
    <span class="o">.</span><span class="nf">skeleton</span><span class="p">()</span>
    <span class="o">.</span><span class="n">task</span> <span class="p">{</span>
        <span class="k">await</span> <span class="n">viewModel</span><span class="o">.</span><span class="nf">fetchCharacters</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="demo">Demo</h1>

<video style="width: 70%; @media (max-width: 768px) { width: 50%; }" controls="">
    <source src="/resources/ep089-skeleton-modifier/demo.mp4" type="video/mp4" />
</video>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2023-01-03-new-app-view-modifiers/">ViewModifiers</a></li>
  <li><a href="/2023-10-12-shrink-modifiers/">ShrinkModifiers</a></li>
  <li><a href="/2025-06-15-ep089-skeleton-modifier/">SkeletonModifier</a></li>
  <li><a href="/2025-02-27-simple-modularization-setup/">Simple Modularization Setup for a New App</a></li>
  <li><a href="/2024-02-29-centralized-dependencies/">Centralized Dependencies</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Skeleton Modifier | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="Skeleton Modifier" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="This is a simple modifier to add a shimmer-style animation to any SwiftUI view." />

<meta property="og:description" content="This is a simple modifier to add a shimmer-style animation to any SwiftUI view." />

<link rel="canonical" href="https://manu.show/2025-06-15-ep089-skeleton-modifier/" />

<meta property="og:url" content="https://manu.show/2025-06-15-ep089-skeleton-modifier/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-06-15T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="Skeleton Modifier" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-06-15T06:00:00-04:00","datePublished":"2025-06-15T06:00:00-04:00","description":"This is a simple modifier to add a shimmer-style animation to any SwiftUI view.","headline":"Skeleton Modifier","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-06-15-ep089-skeleton-modifier/"},"url":"https://manu.show/2025-06-15-ep089-skeleton-modifier/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="ios" /><category term="swiftui" /><summary type="html"><![CDATA[This is a simple modifier to add a shimmer-style animation to any SwiftUI view.]]></summary></entry><entry><title type="html">The ONE Thing</title><link href="https://manu.show/2025-05-19-ep088-the-one-thing/" rel="alternate" type="text/html" title="The ONE Thing" /><published>2025-05-19T06:00:00-04:00</published><updated>2025-05-19T06:00:00-04:00</updated><id>https://manu.show/ep088-the-one-thing</id><content type="html" xml:base="https://manu.show/2025-05-19-ep088-the-one-thing/"><![CDATA[<p>These are some hand-written notes about the book <code class="language-plaintext highlighter-rouge">The ONE Thing</code> by Gary Keller and Jay Papasan.</p>

<p><img src="/resources/ep088-the-one-thing/cover.webp" width="50%" /></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-notes">The Notes</a></li>
  <li><a href="#personal-takes">Personal Takes</a></li>
  <li><a href="#related-articles">Related Articles</a></li>
</ul>

<h1 id="the-notes">The Notes</h1>

<p><img src="/resources/ep088-the-one-thing/notes1.webp" alt="notes-1" />
<img src="/resources/ep088-the-one-thing/notes2.webp" alt="notes-2" />
<img src="/resources/ep088-the-one-thing/notes3.webp" alt="notes-3" /></p>

<h1 id="personal-takes">Personal Takes</h1>

<p>The question I take to ask myself each time I feel I am not giving my best is:</p>

<p><code class="language-plaintext highlighter-rouge">Are you doing this to simply do the best you can do, or are you doing this to do it the best it can be done?</code></p>

<p>Most of the other advice, even though great, goes in the same line as other <code class="language-plaintext highlighter-rouge">Habits</code> books.</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-04-26-ep85-deep-work/">Deep Work</a></li>
  <li><a href="/2023-07-16-the-compound-effect/">The Compound Effect</a></li>
  <li><a href="/2023-06-11-die-with-zero/">Die with Zero</a></li>
  <li><a href="/2023-05-20-the-joy-of-less/">The Joy of Less</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>The ONE Thing | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="The ONE Thing" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="These are some hand-written notes about the book The ONE Thing by Gary Keller and Jay Papasan." />

<meta property="og:description" content="These are some hand-written notes about the book The ONE Thing by Gary Keller and Jay Papasan." />

<link rel="canonical" href="https://manu.show/2025-05-19-ep088-the-one-thing/" />

<meta property="og:url" content="https://manu.show/2025-05-19-ep088-the-one-thing/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-05-19T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="The ONE Thing" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-05-19T06:00:00-04:00","datePublished":"2025-05-19T06:00:00-04:00","description":"These are some hand-written notes about the book The ONE Thing by Gary Keller and Jay Papasan.","headline":"The ONE Thing","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-05-19-ep088-the-one-thing/"},"url":"https://manu.show/2025-05-19-ep088-the-one-thing/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="books" /><summary type="html"><![CDATA[These are some hand-written notes about the book The ONE Thing by Gary Keller and Jay Papasan.]]></summary></entry><entry><title type="html">Sheets Manipulation</title><link href="https://manu.show/2025-05-03-ep087-sheets-manipulation/" rel="alternate" type="text/html" title="Sheets Manipulation" /><published>2025-05-03T06:00:00-04:00</published><updated>2025-05-03T06:00:00-04:00</updated><id>https://manu.show/ep087-sheets-manipulation</id><content type="html" xml:base="https://manu.show/2025-05-03-ep087-sheets-manipulation/"><![CDATA[<p>We will discuss about which approach is better for each scenario. Enum-based vs Boolean-based.</p>

<p>We will add some documentation on usage on top of the SwiftUI built-in framework for sheets.</p>

<p><code class="language-plaintext highlighter-rouge">iOS 17.0+</code></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-code">The Code</a></li>
  <li><a href="#usage">Usage</a>
    <ul>
      <li><a href="#boolean-based">Boolean-based</a></li>
      <li><a href="#enum-based">Enum-based</a></li>
    </ul>
  </li>
  <li><a href="#state-vs-observable">@State vs @Observable</a></li>
  <li><a href="#adding-navigation-to-the-presented-sheets">Adding Navigation to the presented sheets</a></li>
  <li><a href="#related-articles">Related Articles</a>
    <ul>
      <li><a href="#featured-in">Featured in</a></li>
      <li><a href="#related-reading">Related Reading</a></li>
    </ul>
  </li>
</ul>

<h1 id="the-code">The Code</h1>

<p>Let’s start out with the code:</p>

<script src="https://gist.github.com/mdb1/f41a7b677af6e8b00e47cfa35136bd22.js"></script>

<ul>
  <li>In the snippet, we are just adding a ViewModifier + a View extension to add a close button modifier to a Navigation Bar. Nothing Fancy.</li>
  <li>What’s interesting about the snippet is the documentation we added on top of the code.</li>
  <li>Explaining when to go for <code class="language-plaintext highlighter-rouge">sheet(isPresented: Boolean)</code> vs <code class="language-plaintext highlighter-rouge">sheet(item: Enum)</code>.</li>
  <li>It will serve as the base for sheet manipulation for the whole app.</li>
</ul>

<h1 id="usage">Usage</h1>

<h2 id="boolean-based">Boolean-based</h2>

<p>If your screen can only present one type of sheet, then the easiest way is to use <code class="language-plaintext highlighter-rouge">sheet(isPresented:)</code>. We only need to manage one state property, so there is no need for the enum-based approach.</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">SomeScreen</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">isPresentingSheet</span><span class="p">:</span> <span class="kt">Bool</span> <span class="o">=</span> <span class="kc">false</span>

  <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kt">Button</span><span class="p">(</span><span class="s">"Present Sheet"</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">isPresentingSheet</span> <span class="o">=</span> <span class="kc">true</span>
    <span class="p">}</span>
    <span class="o">.</span><span class="nf">sheet</span><span class="p">(</span><span class="nv">isPresented</span><span class="p">:</span> <span class="err">$</span><span class="n">isPresentingSheet</span><span class="p">)</span> <span class="p">{</span>
      <span class="kt">Text</span><span class="p">(</span><span class="s">"Presented sheet"</span><span class="p">)</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="enum-based">Enum-based</h2>

<p>If your screen can present multiple types of sheets, then the best way is to use <code class="language-plaintext highlighter-rouge">sheet(item:)</code>. We need to manage an enum property, so there is no need for the enum-based approach.</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">SomeScreen</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kd">enum</span> <span class="kt">Sheet</span><span class="p">:</span> <span class="kt">String</span><span class="p">,</span> <span class="kt">Identifiable</span> <span class="p">{</span>
    <span class="k">case</span> <span class="n">firstPresentedScreen</span><span class="p">,</span> <span class="n">secondScreen</span><span class="p">,</span> <span class="n">thirdScreen</span>
    <span class="k">var</span> <span class="nv">id</span><span class="p">:</span> <span class="kt">String</span> <span class="p">{</span> <span class="n">rawValue</span> <span class="p">}</span>
  <span class="p">}</span>
  <span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">presentedSheet</span><span class="p">:</span> <span class="kt">Sheet</span><span class="p">?</span>

  <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kt">VStack</span> <span class="p">{</span>
      <span class="kt">Button</span><span class="p">(</span><span class="s">"Present Sheet"</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">presentedSheet</span> <span class="o">=</span> <span class="o">.</span><span class="n">firstPresentedScreen</span>
      <span class="p">}</span>
      <span class="kt">Button</span><span class="p">(</span><span class="s">"Present Second Sheet"</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">presentedSheet</span> <span class="o">=</span> <span class="o">.</span><span class="n">secondScreen</span>
      <span class="p">}</span>
      <span class="kt">Button</span><span class="p">(</span><span class="s">"Present Third Sheet"</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">presentedSheet</span> <span class="o">=</span> <span class="o">.</span><span class="n">thirdScreen</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="o">.</span><span class="nf">sheet</span><span class="p">(</span><span class="nv">item</span><span class="p">:</span> <span class="err">$</span><span class="n">presentedSheet</span><span class="p">)</span> <span class="p">{</span> <span class="n">sheet</span> <span class="k">in</span>
      <span class="k">switch</span> <span class="n">sheet</span> <span class="p">{</span>
      <span class="k">case</span> <span class="o">.</span><span class="nv">firstPresentedScreen</span><span class="p">:</span>
        <span class="kt">Text</span><span class="p">(</span><span class="s">"First presented screen"</span><span class="p">)</span>
      <span class="k">case</span> <span class="o">.</span><span class="nv">secondScreen</span><span class="p">:</span>
        <span class="kt">Text</span><span class="p">(</span><span class="s">"Second screen"</span><span class="p">)</span>
      <span class="k">case</span> <span class="o">.</span><span class="nv">thirdScreen</span><span class="p">:</span>
        <span class="kt">Text</span><span class="p">(</span><span class="s">"Third screen"</span><span class="p">)</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Something interesting about the <code class="language-plaintext highlighter-rouge">sheet(item:)</code> approach is that the system will take care of dismissing the current sheet, if by some reason, another sheet is presented using the same property.</p>

<p>Example:</p>

<ul>
  <li>SomeScreen’s presentedSheet is set to <code class="language-plaintext highlighter-rouge">.firstPresentedScreen</code></li>
  <li>The FirstPresentedScreen is presented as a sheet</li>
  <li>SomeScreen’s presentedSheet is set to <code class="language-plaintext highlighter-rouge">.secondScreen</code></li>
  <li>The FirstPresentedScreen is dismissed</li>
  <li>The SecondScreen is presented as a sheet</li>
</ul>

<h1 id="state-vs-observable">@State vs @Observable</h1>

<p>In most cases, managing the state of the sheets directly on the SwiftUI views as a <code class="language-plaintext highlighter-rouge">@State</code> property should be enough. However, if there is some business logic involved, it might be a good idea to move the state to an <code class="language-plaintext highlighter-rouge">@Observable</code> object. The benefit of the <code class="language-plaintext highlighter-rouge">@Observable</code> object is that it can be shared with other views, and it can be used to trigger some actions when the state changes + we could add some unit tests over the logic.</p>

<h1 id="adding-navigation-to-the-presented-sheets">Adding Navigation to the presented sheets</h1>

<p>It’s really straight forward to add an stack-based navigation system to the presented sheets. We can just follow the same approach explained in the <a href="/2025-04-24-ep84-navigation-router/">NavigationRouter article</a> for the Router of the Sheet-presented flow.</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-04-24-ep84-navigation-router/">NavigationRouter</a></li>
  <li><a href="/2025-02-27-simple-modularization-setup/">Simple Modularization Setup</a></li>
  <li><a href="/2022-12-24-new-app-checklist/">New App Checklist</a></li>
  <li><a href="/2023-03-04-view-state-controller/">ViewStateController</a></li>
  <li><a href="/2023-02-03-enhancing-testability-without-protocols/">Enhancing Testability without Protocols</a></li>
</ul>

<h2 id="featured-in">Featured in</h2>

<ul>
  <li><a href="https://www.ioscoffeebreak.com/issue/issue43">iOS Coffee Break #43</a></li>
  <li><a href="https://iosdevweekly.com/issues/711">iOS Dev Weekly #711</a></li>
</ul>

<h2 id="related-reading">Related Reading</h2>

<ul>
  <li><a href="https://developer.apple.com/documentation/swiftui/view/sheet(ispresented:ondismiss:content:)">sheet(isPresented:ondismiss:content:)</a></li>
  <li><a href="https://developer.apple.com/documentation/swiftui/view/sheet(item:ondismiss:content:)">sheet(item:ondismiss:content:)</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Sheets Manipulation | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="Sheets Manipulation" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="We will discuss about which approach is better for each scenario. Enum-based vs Boolean-based." />

<meta property="og:description" content="We will discuss about which approach is better for each scenario. Enum-based vs Boolean-based." />

<link rel="canonical" href="https://manu.show/2025-05-03-ep087-sheets-manipulation/" />

<meta property="og:url" content="https://manu.show/2025-05-03-ep087-sheets-manipulation/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-05-03T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="Sheets Manipulation" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-05-03T06:00:00-04:00","datePublished":"2025-05-03T06:00:00-04:00","description":"We will discuss about which approach is better for each scenario. Enum-based vs Boolean-based.","headline":"Sheets Manipulation","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-05-03-ep087-sheets-manipulation/"},"url":"https://manu.show/2025-05-03-ep087-sheets-manipulation/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="ios" /><summary type="html"><![CDATA[We will discuss about which approach is better for each scenario. Enum-based vs Boolean-based.]]></summary></entry><entry><title type="html">Localization - Pluralizations</title><link href="https://manu.show/2025-04-29-ep86-localization-handling-plurals/" rel="alternate" type="text/html" title="Localization - Pluralizations" /><published>2025-04-29T06:00:00-04:00</published><updated>2025-04-29T06:00:00-04:00</updated><id>https://manu.show/ep86-localization-handling-plurals</id><content type="html" xml:base="https://manu.show/2025-04-29-ep86-localization-handling-plurals/"><![CDATA[<p>The String Catalogs file have built-in support for pluralization.</p>

<p><a href="https://developer.apple.com/documentation/xcode/localizing-and-varying-text-with-a-string-catalog">Official Apple Docs</a></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#string-catalogs">String Catalogs</a></li>
  <li><a href="#handling-plurals">Handling Plurals</a>
    <ul>
      <li><a href="#usage">Usage</a></li>
    </ul>
  </li>
  <li><a href="#related-articles">Related Articles</a>
    <ul>
      <li><a href="#featured-in">Featured in</a></li>
    </ul>
  </li>
</ul>

<h1 id="string-catalogs">String Catalogs</h1>

<p>Adding a String Catalog to your app is as simple as creating the file:</p>

<p><img src="/resources/ep086-localization-handling-plurals/string-catalog.png" alt="string-catalog" /></p>

<p>For a detailed guide on how to add the <code class="language-plaintext highlighter-rouge">localizable</code> extension to <code class="language-plaintext highlighter-rouge">String</code>, read <a href="/2022-12-27-new-app-localization/">this Localization article</a>.</p>

<h1 id="handling-plurals">Handling Plurals</h1>

<p>Handling plurals has never been easier, the String Catalog has built-in support:</p>

<p><img src="/resources/ep086-localization-handling-plurals/vary-by-plural.png" alt="vary-by-plural" /></p>

<p><img src="/resources/ep086-localization-handling-plurals/pluralization.png" alt="pluralization" /></p>

<p>Forget about the <code class="language-plaintext highlighter-rouge">if/else</code> statements for good 🙌</p>

<h2 id="usage">Usage</h2>

<p>Using it is as straight forward as using the in-line components:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">itemCount</span> <span class="o">=</span> <span class="mi">0</span>
<span class="kt">Text</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">itemCount</span><span class="se">)</span><span class="s"> Books"</span><span class="p">)</span> <span class="c1">// 0 Books, 1 Book, 2 Books</span>
</code></pre></div></div>

<p>Or, if you are using the String extensions from the <a href="/2022-12-27-new-app-localization/">previous localization article</a>:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">itemCount</span> <span class="o">=</span> <span class="mi">0</span>
<span class="kt">Text</span><span class="p">(</span><span class="s">"books"</span><span class="o">.</span><span class="nf">localized</span><span class="p">(</span><span class="nv">with</span><span class="p">:</span> <span class="p">[</span><span class="n">itemCount</span><span class="p">]))</span> <span class="c1">// 0 Books, 1 Book, 2 Books</span>
</code></pre></div></div>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2022-12-27-new-app-localization/">New App - Localization</a></li>
  <li><a href="/2023-10-07-adaptable-stack/">AdaptableStack</a></li>
  <li><a href="/2023-01-04-new-app-components/">Components</a></li>
  <li><a href="/2023-08-18-improve-build-times-in-spm-packages-and-in-your-apps/">Improve Build Times</a></li>
  <li><a href="/2023-01-27-new-app-xcode-templates/">Xcode Templates</a></li>
  <li><a href="/2025-03-03-useful-string-extensions/">String Extensions</a></li>
  <li><a href="/2023-03-04-view-state-controller/">ViewStateController</a></li>
  <li><a href="/2023-01-03-new-app-view-modifiers/">ViewModifiers</a></li>
</ul>

<h2 id="featured-in">Featured in</h2>

<ul>
  <li><a href="https://www.ioscoffeebreak.com/issue/issue43">iOS Coffee Break #43</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Localization - Pluralizations | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="Localization - Pluralizations" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="The String Catalogs file have built-in support for pluralization." />

<meta property="og:description" content="The String Catalogs file have built-in support for pluralization." />

<link rel="canonical" href="https://manu.show/2025-04-29-ep86-localization-handling-plurals/" />

<meta property="og:url" content="https://manu.show/2025-04-29-ep86-localization-handling-plurals/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-04-29T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="Localization - Pluralizations" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-04-29T06:00:00-04:00","datePublished":"2025-04-29T06:00:00-04:00","description":"The String Catalogs file have built-in support for pluralization.","headline":"Localization - Pluralizations","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-04-29-ep86-localization-handling-plurals/"},"url":"https://manu.show/2025-04-29-ep86-localization-handling-plurals/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="ios" /><summary type="html"><![CDATA[The String Catalogs file have built-in support for pluralization.]]></summary></entry><entry><title type="html">Deep Work</title><link href="https://manu.show/2025-04-26-ep85-deep-work/" rel="alternate" type="text/html" title="Deep Work" /><published>2025-04-26T06:00:00-04:00</published><updated>2025-04-26T06:00:00-04:00</updated><id>https://manu.show/ep85-deep-work</id><content type="html" xml:base="https://manu.show/2025-04-26-ep85-deep-work/"><![CDATA[<p>These are some hand-written notes about the book “Deep Work” by Cal Newport.</p>

<p>(Sorry for the formatting, I’ll try to improve it in the future)</p>

<p><img src="/resources/ep085-deep-work/cover.png" alt="cover" /></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-notes">The Notes</a></li>
  <li><a href="#my-takes">My Takes</a></li>
  <li><a href="#related-articles">Related Articles</a></li>
</ul>

<h1 id="the-notes">The Notes</h1>

<p><img src="/resources/ep085-deep-work/notes.png" alt="notes" /></p>

<h1 id="my-takes">My Takes</h1>

<p>I find this book to be very useful, in particular, the idea that you should focus on deep work instead of shallow work is really interesting for someone like me (a knowledge worker focused on providing value).</p>

<p>I agree with the idea of Quitting Social Media, personally:</p>
<ul>
  <li>I have been out of Instagram for the last 2 months (and don’t plan on coming back anytime soon).</li>
  <li>I have never had a TikTok account, I have never installed it on my phone</li>
  <li>I only use X to share my articles. I don’t have the app on my phone, and I’m not logged in in the browser.</li>
</ul>

<p>The downsides I have seen is that I cannot see the tweets/reels/tiktoks that people send in group chats, but I honestly think this has not been a big issue for me.</p>

<p>I have been planning my days for the last couple of weeks and it’s been a really nice practice that have allowed me to accomplish more, to be more mindful about rejecting shallow tasks, and to be more productive overall.</p>

<p>I’ve added the <code class="language-plaintext highlighter-rouge">Plan Next Day</code> practice into my workflow (you can read more about it <a href="/2023-11-26-streamlining-life/">here</a>).</p>

<p>My next reading will be <code class="language-plaintext highlighter-rouge">The One Thing</code>. Be on the lookout for the notes if you’re interested!</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2023-05-20-the-joy-of-less/">The Joy of Less</a></li>
  <li><a href="/2023-06-09-brain-rules/">Brain Rules</a></li>
  <li><a href="/2023-07-16-the-compound-effect/">The Compound Effect</a></li>
  <li><a href="/2023-05-24-excellent-advice-for-living/">Excellent Advice for Living</a></li>
  <li><a href="/2023-06-11-die-with-zero/">Die with Zero</a></li>
  <li><a href="/2022-09-26-the-charisma-myth/">The Charisma Myth</a></li>
  <li><a href="/2023-06-03-hyperfocus/">Hyperfocus</a></li>
  <li><a href="/2023-11-26-streamlining-life/">Streamlining my Life</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Deep Work | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="Deep Work" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="These are some hand-written notes about the book “Deep Work” by Cal Newport." />

<meta property="og:description" content="These are some hand-written notes about the book “Deep Work” by Cal Newport." />

<link rel="canonical" href="https://manu.show/2025-04-26-ep85-deep-work/" />

<meta property="og:url" content="https://manu.show/2025-04-26-ep85-deep-work/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-04-26T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="Deep Work" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-04-26T06:00:00-04:00","datePublished":"2025-04-26T06:00:00-04:00","description":"These are some hand-written notes about the book “Deep Work” by Cal Newport.","headline":"Deep Work","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-04-26-ep85-deep-work/"},"url":"https://manu.show/2025-04-26-ep85-deep-work/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="books" /><summary type="html"><![CDATA[These are some hand-written notes about the book “Deep Work” by Cal Newport.]]></summary></entry><entry><title type="html">NavigationRouter</title><link href="https://manu.show/2025-04-24-ep84-navigation-router/" rel="alternate" type="text/html" title="NavigationRouter" /><published>2025-04-24T06:00:00-04:00</published><updated>2025-04-24T06:00:00-04:00</updated><id>https://manu.show/ep84-navigation-router</id><content type="html" xml:base="https://manu.show/2025-04-24-ep84-navigation-router/"><![CDATA[<p>We will discuss about a simple stack-based navigation system for SwiftUI applications.</p>

<p><code class="language-plaintext highlighter-rouge">iOS 17.0+</code></p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#the-code">The Code</a></li>
  <li><a href="#usage">Usage</a></li>
  <li><a href="#find-a-place-to-store-the-routers">Find a place to store the routers</a></li>
  <li><a href="#-but-you-are-coupling-the-views-and-the-navigation">😡 But you are coupling the views and the navigation!</a></li>
  <li><a href="#adding-some-unit-tests">Adding some unit tests</a></li>
  <li><a href="#related-articles">Related Articles</a></li>
  <li><a href="#related-reading">Related Reading</a></li>
</ul>

<h1 id="the-code">The Code</h1>

<p>Let’s start out with the code:</p>

<script src="https://gist.github.com/mdb1/9eb7c3ee9bcad89fb0a83159b9c17b44.js"></script>

<ul>
  <li>We have a <code class="language-plaintext highlighter-rouge">generic</code> NavigationRouter</li>
  <li>The <code class="language-plaintext highlighter-rouge">class</code> is marked with the <code class="language-plaintext highlighter-rouge">@Observable</code> notation</li>
  <li>SwiftUI views can react to changes in the router’s properties.</li>
  <li>The router containts a <code class="language-plaintext highlighter-rouge">navigationPath</code> property, which will be an array of <code class="language-plaintext highlighter-rouge">Hashable</code> objects.</li>
  <li>We have some UIKit-ish named methods for <code class="language-plaintext highlighter-rouge">push</code>, <code class="language-plaintext highlighter-rouge">pop</code>, <code class="language-plaintext highlighter-rouge">pop(to:)</code>, and <code class="language-plaintext highlighter-rouge">popToRoot</code> which will manipulate the <code class="language-plaintext highlighter-rouge">path</code> array.</li>
  <li>The <code class="language-plaintext highlighter-rouge">push</code> method adds a new item to the end of the <code class="language-plaintext highlighter-rouge">navigationPath</code> array.</li>
  <li>The <code class="language-plaintext highlighter-rouge">pop</code> method removes the last item from the <code class="language-plaintext highlighter-rouge">navigationPath</code> array.</li>
  <li>The <code class="language-plaintext highlighter-rouge">pop(to:)</code> method removes all items from the <code class="language-plaintext highlighter-rouge">navigationPath</code> array, until it finds the given item.</li>
  <li>The <code class="language-plaintext highlighter-rouge">popToRoot</code> method removes all items from the <code class="language-plaintext highlighter-rouge">navigationPath</code> array.</li>
</ul>

<h1 id="usage">Usage</h1>

<p>Basic usage of this router, will consist on:</p>

<p><code class="language-plaintext highlighter-rouge">1.</code> Create an enum with all possible destinations:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">enum</span> <span class="kt">Route</span><span class="p">:</span> <span class="kt">Hashable</span> <span class="p">{</span>
    <span class="k">case</span> <span class="nf">detail</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="kt">Int</span><span class="p">)</span>
    <span class="k">case</span> <span class="n">profile</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">2.</code> We need to decide where the router will be stored, for example, if it’s a simple flow, it could live on the first screen. In other cases, we could store it on the app level, or in the first screen of each Tab. It will depend on the requirements:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">SomeScreen</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">router</span> <span class="o">=</span> <span class="kt">NavigationRouter</span><span class="o">&lt;</span><span class="kt">Route</span><span class="o">&gt;</span><span class="p">()</span> <span class="c1">// Define the Router</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">3.</code> Then we add a NavigationStack into the body:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kt">NavigationStack</span><span class="p">(</span><span class="nv">path</span><span class="p">:</span> <span class="err">$</span><span class="n">router</span><span class="o">.</span><span class="n">navigationPath</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Here we use the navigationPath from the Router</span>
    <span class="c1">// Will Fill this on point number 4</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">4.</code> Then, we add the possible navigationDestinations for the flow:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kt">NavigationStack</span><span class="p">(</span><span class="nv">path</span><span class="p">:</span> <span class="err">$</span><span class="n">router</span><span class="o">.</span><span class="n">navigationPath</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">BaseScreen</span><span class="p">()</span>
      <span class="o">.</span><span class="nf">navigationDestination</span><span class="p">(</span><span class="nv">for</span><span class="p">:</span> <span class="kt">Route</span><span class="o">.</span><span class="k">self</span><span class="p">)</span> <span class="p">{</span> <span class="n">destination</span> <span class="k">in</span>
        <span class="k">switch</span> <span class="n">destination</span> <span class="p">{</span> <span class="c1">// We define a destination for each case</span>
        <span class="k">case</span> <span class="o">.</span><span class="nf">detail</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="k">let</span> <span class="nv">id</span><span class="p">):</span>
            <span class="kt">DetailScreen</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="n">id</span><span class="p">)</span>
        <span class="k">case</span> <span class="o">.</span><span class="nv">profile</span><span class="p">:</span>
            <span class="kt">ProfileScreen</span><span class="p">()</span>
        <span class="p">}</span>
      <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">5.</code> We need to provide a way to share the router with the childs, we can do this using the <code class="language-plaintext highlighter-rouge">environment</code> modifier:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kt">NavigationStack</span><span class="p">(</span><span class="nv">path</span><span class="p">:</span> <span class="err">$</span><span class="n">router</span><span class="o">.</span><span class="n">navigationPath</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// content</span>
  <span class="p">}</span>
  <span class="o">.</span><span class="nf">environment</span><span class="p">(</span><span class="n">router</span><span class="p">)</span> <span class="c1">// Share the router with the children screens/views.</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">6.</code> Finally, in the child screens, we can access the router via the <code class="language-plaintext highlighter-rouge">@Environment</code> modifier:</p>

<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">ProfileScreen</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
  <span class="kd">@Environment</span><span class="p">(</span><span class="kt">NavigationRouter</span><span class="o">&lt;</span><span class="kt">Route</span><span class="o">&gt;.</span><span class="k">self</span><span class="p">)</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">router</span>

  <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kt">Button</span><span class="p">(</span><span class="s">"Push Detail"</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">router</span><span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="o">.</span><span class="nf">detail</span><span class="p">(</span><span class="nv">id</span><span class="p">:</span> <span class="mi">1</span><span class="p">))</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="find-a-place-to-store-the-routers">Find a place to store the routers</h1>

<p>It’s important to notice, that an app could have multiple routers, one for each tab, or one for each flow.</p>

<p>To this point, each app will have its own way of storing the routers. That way will depend basically on how the navigation happens on the app.</p>

<p>I’d say that the best way is to store the router on the first screen of the flow, or on the first screen of the tab. However, if, for some reason, some screen in the third tab can decide the navigation of another tab, we would need to move the routers up the view hierarchy.</p>

<p>My recommendation would be to store them as low in the view hierarchy as possible for each one, and move them up only if needed by the business decisions.</p>

<h1 id="-but-you-are-coupling-the-views-and-the-navigation">😡 But you are coupling the views and the navigation!</h1>

<p>One of the potential drawbacks of using this system is that the views are now tightly coupled with the navigation.</p>

<p>In any case, I believe this system is so simple that it shouldn’t be a big deal.</p>

<p>If you want to have logic over which view to present next, you can move that logic into a view model, and add unit tests over it.</p>

<p>If your flow is too complex, you could add automated testing, or UI testing, instead of unit testing.</p>

<p>The case in point here, is that this is a simple navigation system, and you probably won’t need anything more complex than this, so starting to geek out on abstractions to make a solution that works well with SwiftUI could be an overkill.</p>

<p>As most times, the rule of starting simple and only adding complexity as needed applies really well to this case.</p>

<h1 id="adding-some-unit-tests">Adding some unit tests</h1>

<p>Finally, we could add some basic unit tests to make sure the navigationPath is being modified correctly:</p>

<script src="https://gist.github.com/mdb1/64004c408e52e931b13cb846fa964f93.js"></script>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-05-03-ep087-sheets-manipulation/">Sheets Manipulation</a></li>
  <li><a href="/2025-02-27-simple-modularization-setup/">Simple Modularization Setup</a></li>
  <li><a href="/2022-12-24-new-app-checklist/">New App Checklist</a></li>
  <li><a href="/2023-02-03-enhancing-testability-without-protocols/">Enhancing Testability without Protocols</a></li>
  <li><a href="/2023-03-04-view-state-controller/">ViewStateController</a></li>
</ul>

<h1 id="related-reading">Related Reading</h1>

<ul>
  <li><a href="https://developer.apple.com/documentation/swiftui/navigationstack">NavigationStack</a></li>
  <li><a href="https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro">Migrating from the Observable Object protocol to the Observable macro</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>NavigationRouter | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="NavigationRouter" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="We will discuss about a simple stack-based navigation system for SwiftUI applications." />

<meta property="og:description" content="We will discuss about a simple stack-based navigation system for SwiftUI applications." />

<link rel="canonical" href="https://manu.show/2025-04-24-ep84-navigation-router/" />

<meta property="og:url" content="https://manu.show/2025-04-24-ep84-navigation-router/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-04-24T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="NavigationRouter" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-04-24T06:00:00-04:00","datePublished":"2025-04-24T06:00:00-04:00","description":"We will discuss about a simple stack-based navigation system for SwiftUI applications.","headline":"NavigationRouter","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-04-24-ep84-navigation-router/"},"url":"https://manu.show/2025-04-24-ep84-navigation-router/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="ios" /><summary type="html"><![CDATA[We will discuss about a simple stack-based navigation system for SwiftUI applications.]]></summary></entry><entry><title type="html">Should you automate your Design System?</title><link href="https://manu.show/2025-04-20-ep83-automate-design-system/" rel="alternate" type="text/html" title="Should you automate your Design System?" /><published>2025-04-20T06:00:00-04:00</published><updated>2025-04-20T06:00:00-04:00</updated><id>https://manu.show/ep83-automate-design-system</id><content type="html" xml:base="https://manu.show/2025-04-20-ep83-automate-design-system/"><![CDATA[<p>In this post, we’ll go through the standard process for automating the tokens of a design system. Starting from the Figma export, then the codegen. Finally, we’ll discuss wether it’s worth it or not to automate the process.</p>

<p>This is not a guide on how to set up the process, it’s a guide on wether you should or not do it.</p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#starting-point">Starting point</a></li>
  <li><a href="#transforming-tokens-to-code">Transforming Tokens to code</a></li>
  <li><a href="#the-benefits-of-automating">The benefits of automating</a></li>
  <li><a href="#the-drawbacks-of-automating">The drawbacks of automating</a></li>
  <li><a href="#should-you-automate-the-process">Should you Automate the process?</a>
    <ul>
      <li><a href="#you-maintain-only-1-app">You maintain only 1 app</a></li>
      <li><a href="#you-maintain-multiple-apps--sdks">You maintain multiple apps / SDKs</a></li>
      <li><a href="#the-tokens-change-too-often">The tokens change too often</a></li>
    </ul>
  </li>
  <li><a href="#related-articles">Related Articles</a>
    <ul>
      <li><a href="#related-reading">Related Reading</a></li>
      <li><a href="#featured-in">Featured in</a></li>
    </ul>
  </li>
</ul>

<h1 id="starting-point">Starting point</h1>

<p>The starting point for this post is the assumption that you are working with a Figma design system.</p>

<p>The design system is set up following the standard Design Tokens pattern.</p>

<p>So, it should be possible to use the <a href="https://www.figma.com/community/plugin/888356646278934516/design-tokens">Design Tokens</a> plugin to export the tokens from Figma to a json file.</p>

<p><a href="https://www.figma.com/design/2MQ759R5kJtzQn4qSHuqR7/Design-Tokens-for-Figma--Testing-file-?node-id=231-2">Here</a> is a Figma example of a design system.</p>

<p><em>A side note here</em>: Regardless of automating the process, using semantic names for the tokens is a good practice. i.e.: <code class="language-plaintext highlighter-rouge">primary</code> instead of <code class="language-plaintext highlighter-rouge">primaryBlue</code>. <code class="language-plaintext highlighter-rouge">accent</code> instead of <code class="language-plaintext highlighter-rouge">accentRed</code>.</p>

<h1 id="transforming-tokens-to-code">Transforming Tokens to code</h1>

<p>The idea of automating the Design System, is that we can transform the tokens from json file directly to iOS/Android/Web code using codegeneration scripts.</p>

<p>Given the json file should be compatible with the <strong>Amazon Style Dictionary</strong> style, we will be able to use <a href="https://github.com/amzn/style-dictionary">Amazon Repository</a> which contains JavaScript code to generate all the tokens.</p>

<p>It’s important to note that it’s not plug and play, and there is some overhead to make it work for all the platforms.</p>

<p>Once we have valid json files, and the code generation scripts fully setup, we can talk about some benefits and drawbacks.</p>

<h1 id="the-benefits-of-automating">The benefits of automating</h1>

<ul>
  <li><strong>Consistency</strong>: The 3 platforms will have the same tokens, the same names for each token, and the same values.</li>
  <li><strong>Speed</strong>: If the designers change the tokens, we can update the values running the codegen again.</li>
  <li><strong>Less Error Prone</strong>: We can avoid human-errors when updating the tokens in the code.</li>
  <li><strong>Less Code</strong>: We can avoid writing the same code in all the platforms.</li>
</ul>

<h1 id="the-drawbacks-of-automating">The drawbacks of automating</h1>

<ul>
  <li><strong>Buy-In</strong>: We need to pitch the idea to the team. Then we need everyone onboard, as this only works if all the parts are in place.</li>
  <li><strong>Cost</strong>: We need to invest some time up-front in setting up the process.</li>
  <li><strong>Complexity</strong>: We would have a more complex system. We might not need to write the same thing multiple times, but now we have new systems that could fail.</li>
  <li><strong>Maintenance</strong>: We would need to maintain the code generation scripts. Who will be responsible for this code if it fails?</li>
  <li><strong>Risk</strong>: Can different people maintain the process in the future? This question goes for Devs and Designers alike.</li>
</ul>

<h1 id="should-you-automate-the-process">Should you Automate the process?</h1>

<p>So, going back to the title of the post, <code class="language-plaintext highlighter-rouge">Should you automate the process or not?</code></p>

<p>For most cases, I lean towards not automating the process. The drawbacks are more strong than the benefits in my personal opinion.</p>

<p>I have seen this process fail, basically, an initial team sets everything up, after some initial setup, the process works fine. Everything is smooth for a while, but then, errors start to pop up. The lead designer might change companies. Now we have a team that does not follow the same process, and the process fails. We end up with a broken process. Then, the devs change companies, the new devs do not know how the entire system work, so they start changing tokens manually. Now we are in the worst world of all, we have a triple discrepancy between: Figma Tokens, the json file, and the codegenerated files.</p>

<p>Let’s go through some scenarios:</p>

<h2 id="you-maintain-only-1-app">You maintain only 1 app</h2>

<p>If you/your team are working only on 1 application, the benefits of automating the process are not worth it.</p>

<p>The design system tokens do not change that often, so the overall time spent on creating them at first and then maintaining them up to date is not that big.</p>

<h2 id="you-maintain-multiple-apps--sdks">You maintain multiple apps / SDKs</h2>

<p>If you/your team are working on multiple apps, and the base design system is shared for all of them, then the benefits of automating the process are worth it.</p>

<p>This is the scenario where I would vote for automating the process. Spend the time setting up the process, and the benefits will be huge. Pitch the idea to the team, educate everyone, write documentation on usage, and make sure everyone is on the same page.</p>

<p>Finally, keep an eye on how it evolves, if it becomes too complex, or if the process starts to fail, then it might be time to reevaluate the process.</p>

<h2 id="the-tokens-change-too-often">The tokens change too often</h2>

<p>If the design team tends to change the token regularly (<em>strange, but could happen</em>), then you should consider the automation, as the benefits outweigh the drawbacks.</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-02-27-simple-modularization-setup/">Simple Modularization Setup</a></li>
  <li><a href="/2023-08-25-ui-vs-api-models-different-layers/">UI vs API Models</a></li>
  <li><a href="/2022-12-24-new-app-checklist/">New App Checklist</a></li>
</ul>

<h2 id="related-reading">Related Reading</h2>
<ul>
  <li><a href="https://atomicdesign.bradfrost.com">Atomic Design Book by Brad Frost</a></li>
</ul>

<h2 id="featured-in">Featured in</h2>

<ul>
  <li><a href="https://thosewhoswift.substack.com/p/those-who-swift-issue-211">Those Who Swift #211</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Should you automate your Design System? | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="Should you automate your Design System?" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="In this post, we’ll go through the standard process for automating the tokens of a design system. Starting from the Figma export, then the codegen. Finally, we’ll discuss wether it’s worth it or not to automate the process." />

<meta property="og:description" content="In this post, we’ll go through the standard process for automating the tokens of a design system. Starting from the Figma export, then the codegen. Finally, we’ll discuss wether it’s worth it or not to automate the process." />

<link rel="canonical" href="https://manu.show/2025-04-20-ep83-automate-design-system/" />

<meta property="og:url" content="https://manu.show/2025-04-20-ep83-automate-design-system/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-04-20T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="Should you automate your Design System?" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-04-20T06:00:00-04:00","datePublished":"2025-04-20T06:00:00-04:00","description":"In this post, we’ll go through the standard process for automating the tokens of a design system. Starting from the Figma export, then the codegen. Finally, we’ll discuss wether it’s worth it or not to automate the process.","headline":"Should you automate your Design System?","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-04-20-ep83-automate-design-system/"},"url":"https://manu.show/2025-04-20-ep83-automate-design-system/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="ios" /><summary type="html"><![CDATA[In this post, we’ll go through the standard process for automating the tokens of a design system. Starting from the Figma export, then the codegen. Finally, we’ll discuss wether it’s worth it or not to automate the process.]]></summary></entry><entry><title type="html">DX: Only run unit tests for changed modules</title><link href="https://manu.show/2025-03-26-dx-changed-modules-tests/" rel="alternate" type="text/html" title="DX: Only run unit tests for changed modules" /><published>2025-03-26T06:00:00-04:00</published><updated>2025-03-26T06:00:00-04:00</updated><id>https://manu.show/dx-changed-modules-tests</id><content type="html" xml:base="https://manu.show/2025-03-26-dx-changed-modules-tests/"><![CDATA[<p>Here is a quick developer experience win: <code class="language-plaintext highlighter-rouge">Only run the unit tests for the modules with changes against a base branch</code>.</p>

<p>We’ll build upon the <a href="/2025-02-27-simple-modularization-setup/">Simple Modularization</a> post. In that repo, we added a lane to run all the tests of all the modules. Now, we will add a lane to only run the tests for the modules with changes, to speed up the process and improve the developer experience.</p>

<p>This will also save up precious CI time, as developers will get test failures on their machines, without the need to wait for the CI to run all the tests.</p>

<h4 id="table-of-contents">Table of Contents</h4>
<ul>
  <li><a href="#gathering-the-changed-packages">Gathering the changed packages</a></li>
  <li><a href="#running-the-tests">Running the tests</a></li>
  <li><a href="#related-articles">Related Articles</a></li>
  <li><a href="#featured-in">Featured in</a></li>
</ul>

<h1 id="gathering-the-changed-packages">Gathering the changed packages</h1>

<p>The first thing we need to do, is to add a method to check the diff between the current branch and the base branch.</p>

<p>We can do this by executing a really simple shell command:</p>

<p><code class="language-plaintext highlighter-rouge">git diff --name-only origin/main</code></p>

<p>This will return a list of files that have changed between the current branch and the base branch.</p>

<p>Example:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Packages/CoreLayer/APIModels/Sources/APIModels/APIModel.swift</code></li>
</ul>

<p>Then we need to extract the Scheme for the changed package and store all the changes packages.</p>

<p><img src="/resources/ep082-dx-changed-modules-tests/diff.png" alt="diff" /></p>

<h1 id="running-the-tests">Running the tests</h1>

<p>For this, we can leverage the <code class="language-plaintext highlighter-rouge">test_all_packages</code> lane that we already have, but modify it to receive an array of packages.</p>

<p>Check the complete diff in <a href="https://github.com/mdb1/ModularTemplate/commit/b2fa5110e9b961bd387cca2aae21938ca5fdd660">this commit</a>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; bundle exec fastlane test_changed_packages
---------------------------
--- Step: shell command ---
---------------------------
🔍 Found 1 changed packages: CoreLayer/APIModels
--------------------------------------------------
--- Step: Switch to ios test_all_packages lane ---
--------------------------------------------------
Cruising over to lane 'ios test_all_packages' 🚖
🚀 Running tests for specified packages: CoreLayer/APIModels
▶️ Testing APIModels...
▸ Test Succeeded
✅ APIModels: 1/1 tests passed
   Coverage: ⚠️ No coverage data

📊 Test Results Summary
✅ Passed: 1 packages, 1 tests
  • APIModels - 1/1 tests
    Coverage: ⚠️ No coverage data

📈 Overall Statistics
Total tests: 1
Passed: 1
Failed: 0
🎉 All tests passed successfully!
Cruising back to lane 'ios test_changed_packages' 🚘
fastlane.tools finished successfully 🎉
</code></pre></div></div>

<hr />

<p>With this new <code class="language-plaintext highlighter-rouge">test_changed_packages</code> lane, we can now speed up development, run the tests more often, and save valuable CI time.</p>

<hr />

<h1 id="related-articles">Related Articles</h1>

<ul>
  <li><a href="/2025-02-27-simple-modularization-setup/">Simple Modularization Setup</a></li>
  <li><a href="/2023-03-14-my-xcode-setup-and-shortcuts">My Xcode Setup and Shortcuts</a></li>
  <li><a href="/2022-12-24-new-app-checklist/">New App Checklist</a></li>
</ul>

<hr />

<h1 id="featured-in">Featured in</h1>
<ul>
  <li><a href="https://testableapple.com/newsletter/55/">TestableApple #55</a></li>
</ul>

<hr />

<!-- Do not remove - SEO meta tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>DX: Only run unit tests for changed modules | manu.show</title>
<meta name="generator" content="Jekyll v3.10.0" />

<meta property="og:title" content="DX: Only run unit tests for changed modules" />

<meta name="author" content="Manu" />

<meta property="og:locale" content="en_US" />

<meta name="description" content="Here is a quick developer experience win: Only run the unit tests for the modules with changes against a base branch." />

<meta property="og:description" content="Here is a quick developer experience win: Only run the unit tests for the modules with changes against a base branch." />

<link rel="canonical" href="https://manu.show/2025-03-26-dx-changed-modules-tests/" />

<meta property="og:url" content="https://manu.show/2025-03-26-dx-changed-modules-tests/" />

<meta property="og:site_name" content="manu.show" />

<meta property="og:type" content="article" />

<meta property="article:published_time" content="2025-03-26T06:00:00-04:00" />

<meta name="twitter:card" content="summary" />

<meta property="twitter:title" content="DX: Only run unit tests for changed modules" />

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Manu"},"dateModified":"2025-03-26T06:00:00-04:00","datePublished":"2025-03-26T06:00:00-04:00","description":"Here is a quick developer experience win: Only run the unit tests for the modules with changes against a base branch.","headline":"DX: Only run unit tests for changed modules","mainEntityOfPage":{"@type":"WebPage","@id":"https://manu.show/2025-03-26-dx-changed-modules-tests/"},"url":"https://manu.show/2025-03-26-dx-changed-modules-tests/"}</script>

<!-- End Jekyll SEO tag -->]]></content><author><name>Manu</name></author><category term="ios" /><summary type="html"><![CDATA[Here is a quick developer experience win: Only run the unit tests for the modules with changes against a base branch.]]></summary></entry></feed>