<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Konstantinos’s Substack]]></title><description><![CDATA[My personal Substack]]></description><link>https://codingwithkonsta.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!X05u!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a6260c3-a80c-4258-9c99-cfb9416dcc63_276x276.png</url><title>Konstantinos’s Substack</title><link>https://codingwithkonsta.substack.com</link></image><generator>Substack</generator><lastBuildDate>Mon, 18 May 2026 10:02:11 GMT</lastBuildDate><atom:link href="https://codingwithkonsta.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Konstantinos Nikoloutsos]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[codingwithkonsta@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[codingwithkonsta@substack.com]]></itunes:email><itunes:name><![CDATA[Konstantinos Nikoloutsos]]></itunes:name></itunes:owner><itunes:author><![CDATA[Konstantinos Nikoloutsos]]></itunes:author><googleplay:owner><![CDATA[codingwithkonsta@substack.com]]></googleplay:owner><googleplay:email><![CDATA[codingwithkonsta@substack.com]]></googleplay:email><googleplay:author><![CDATA[Konstantinos Nikoloutsos]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Understanding Parameter Packs in Swift With a Real Example]]></title><description><![CDATA[How a small compiler error reveals a big evolution in the language.]]></description><link>https://codingwithkonsta.substack.com/p/understanding-parameter-packs-in</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/understanding-parameter-packs-in</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Fri, 06 Feb 2026 01:36:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7Mnz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7Mnz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7Mnz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7Mnz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7Mnz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7Mnz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7Mnz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2650597,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/187035932?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7Mnz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7Mnz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7Mnz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7Mnz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb090e9da-e718-44c1-8be5-0a8cd1d590e3_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Today I was writing some code for a client that was using <a href="https://github.com/mxcl/PromiseKit">PromiseKit</a>, a third-party library similar to Combine for handling async operations. Basically PromiseKit is working with Promise objects, hence the name, and each Promise is something that will be fulfilled later on (useful for async operations) - similar to Future for Combine friends.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>So in PromiseKit there is a function called when(..) that takes as parameter many Promises inside, and it appears to accept any number of Promises, similar to a variadic argument where you can pass as many Promises as you want.</p><h3><br>The compiler error</h3><p>Little did I know, until I added a sixth parameter, and the compiler was nagging about the when() function. It was giving me an error because it could only support up to 5 arguments.</p><p>So I took a look at the library and I saw this.</p><blockquote><p>The reason the arguments are generic is because a promise can carry any type. E.g Promise&lt;Int&gt; or Promise&lt;String&gt;</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vKrk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vKrk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 424w, https://substackcdn.com/image/fetch/$s_!vKrk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 848w, https://substackcdn.com/image/fetch/$s_!vKrk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 1272w, https://substackcdn.com/image/fetch/$s_!vKrk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vKrk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png" width="1456" height="353" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:353,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:138197,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/187035932?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vKrk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 424w, https://substackcdn.com/image/fetch/$s_!vKrk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 848w, https://substackcdn.com/image/fetch/$s_!vKrk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 1272w, https://substackcdn.com/image/fetch/$s_!vKrk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23429771-3830-428b-a6ba-b92c1ae2ddd4_1643x398.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3><strong>The Naive Solution</strong></h3><p>Instinctively, my first thought was to contribute to the library by adding a new function with 6 generic arguments. But.. what if later we need 7? <br>But wait a second, this looks like repetitive code, it sounds overkill to have to implement a new function for each parameter count number.</p><h3><br><strong>Hello Parameter packs</strong></h3><p>This got me curious, so then I searched and I found out that from <strong>swift 5.9+</strong> we are able to use a new feature called <strong>parameter packs</strong> (or <strong>variadic generics</strong>)</p><p>And all the code you see above could basically be replaced by the following:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jnd1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jnd1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 424w, https://substackcdn.com/image/fetch/$s_!Jnd1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 848w, https://substackcdn.com/image/fetch/$s_!Jnd1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 1272w, https://substackcdn.com/image/fetch/$s_!Jnd1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jnd1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png" width="897" height="110" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:110,&quot;width&quot;:897,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:40701,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/187035932?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jnd1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 424w, https://substackcdn.com/image/fetch/$s_!Jnd1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 848w, https://substackcdn.com/image/fetch/$s_!Jnd1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 1272w, https://substackcdn.com/image/fetch/$s_!Jnd1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d20a927-4548-43c4-8410-7e35ec61df2b_897x110.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Wow, that was my first reaction when I finished writing that, first of all it looks like it is not swift at all because of the new keywords. Well, let&#8217;s see this together.<br><br>First let&#8217;s analyze the function signature.</p><ul><li><p>The when() is a generic function because we see the &lt;&gt; characters.</p></li><li><p>&#8221;&lt;each U: Thenable&gt;&#8221; declares a <strong>type parameter pack</strong>, a placeholder for one or more types. The number of parameters will be decided at the call site (inferred later from the function parameters). The <code>: Thenable</code> constraint ensures each type in the pack conforms to the Thenable protocol.</p></li><li><p>&#8220;repeat each U&#8220; is where the pack expansion happens, this allows the compiler to expect from 0 or more generic arguments as parameters on call site. For example if caller uses 3 parameters the equivalent without parameter packs would be &#8220;_genericParam1: U, _ genericParam2: V, _ genericParam3: W&#8220;.</p></li><li><p>The return is also using pack expansion. It expands into a <code>Promise</code> wrapping a tuple of each promise's resolved type. For example, if you pass <code>Promise&lt;Int&gt;</code> and <code>Promise&lt;String&gt;</code>, the return type becomes <code>Promise&lt;(Int, String)&gt;</code>."</p></li></ul><p></p><p>Now that we have covered the function signature we can continue with the implementation. As you can see we are using</p><pre><code>repeat voidPromises.append((each fulfilled).asVoid())

// Which is equivalent to 
voidPromises.append((parameter1).asVoid())
voidPromises.append((parameter2).asVoid())
voidPromises.append((parameter3).asVoid())
....</code></pre><p>The rest is just PromiseKit internal implementation so it&#8217;s skipped from this article.<br>And that&#8217;s how powerful the compiler can be.</p><h3><strong>When Will You Need This?</strong></h3><p>Now you might be wondering, &#8220;how often will I actually need this?&#8221; <br>Honestly, in a typical iOS codebase, probably never. But if you are building a library, parameter packs can save you from maintaining dozens of overloads and your users from hitting arbitrary argument limits like I did.</p><p>If you are interested in learning more I would recommend taking a look at the following WWDC.</p><div id="youtube2-Uw8tK8na3Dg" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;Uw8tK8na3Dg&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/Uw8tK8na3Dg?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Thanks for reading, feel free to share your thoughts in the comment section see you in the next article &#128075;&#128640;<br>await nextArticleCodingWithKonsta()</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Your Swift Tests Are Great. Until a Mutant Shows Up]]></title><description><![CDATA[Mutation score in Swift measures what code coverage can&#8217;t.]]></description><link>https://codingwithkonsta.substack.com/p/your-tests-are-great-until-a-mutant</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/your-tests-are-great-until-a-mutant</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Sun, 25 Jan 2026 21:40:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!fsJO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fsJO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fsJO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!fsJO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!fsJO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!fsJO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fsJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2659539,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/184911673?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fsJO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!fsJO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!fsJO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!fsJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ead48bf-ecb0-4a85-a1f2-320122b54e37_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Don&#8217;t worry zombie apocalypse hasn&#8217;t happen yet&#129503;&#8205;&#9794;&#65039; <br>But after reading this article, you&#8217;ll learn a new metric for assessing the <em>real</em> quality of your unit tests.</p><p><br>I&#8217;ve worked on teams where <strong>code coverage</strong> was considered one of the most important metrics. And yet, even as coverage increased, the codebase didn&#8217;t necessarily become healthier.</p><p>In this article, I&#8217;ll introduce a metric that measures something code coverage doesn&#8217;t&#8230; &#128071;</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Hey, sorry if I scared you with my zombie face. Support my work by subscribing for free in codingWithKonstantinos</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong> Code-Coverage</strong></h2><p>Every&#8217;s developers nightmare is to ship a bug in production. A strong CI pipeline and a <strong>reliable</strong> test suite builds confidence and speeds up deliveries.</p><p>And <strong>reliable</strong> is the key word here. </p><p>A good friend and coworker once told me:</p><div class="pullquote"><p>If you want to introduce something to the team, it needs to be measurable.</p></div><p>So that raises an important question:</p><p><strong>How do you measure whether your tests are actually good or bad?</strong> &#129300;</p><p>Do you just wait until customers start complaining about bugs they find? <br>Code coverage may look great on paper&#8230;but reliability is what actually protects production.</p><p>There has to be a better way&#8230;</p><blockquote><p>The problem becomes even worse if your team is scaling up. How do you know that tests written are reliable?  And then&#8230; you end up with having many regression bugs although you&#8217;ve hit your code-coverage team goal &#128561;</p></blockquote><h2>Mutation Testing</h2><blockquote><p>Mutation testing is not a mobile-only concept.<br>After reading this article, ask your backend, web friends if they use it.</p></blockquote><p>Konsta what is this about? Is this just a fancy name? Give me an example.<br>Sure, and let me explain, in order to do this type of test you need a mutant.</p><p><strong>A mutant</strong> is a change (a bug) that you create in your codebase by changing your production code.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y67h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y67h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 424w, https://substackcdn.com/image/fetch/$s_!y67h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 848w, https://substackcdn.com/image/fetch/$s_!y67h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 1272w, https://substackcdn.com/image/fetch/$s_!y67h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y67h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png" width="671" height="319" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:319,&quot;width&quot;:671,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:132380,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/184911673?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y67h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 424w, https://substackcdn.com/image/fetch/$s_!y67h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 848w, https://substackcdn.com/image/fetch/$s_!y67h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 1272w, https://substackcdn.com/image/fetch/$s_!y67h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9315f0-1904-4ed2-a8bb-2a1152c0c1d4_671x319.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><h4><strong>What kinds of mutations exist?</strong></h4><p>Mutants are usually small, realistic changes such as</p><ul><li><p>swapping operators (&gt;= &#8594; &lt;)</p></li><li><p>flipping logical expressions (&amp;&amp; &#8594; ||)</p></li><li><p>replacing constants (true &#8594; false)</p></li><li><p>deleting function calls, especially when return values are discarded.</p><p></p></li></ul><p>Once the mutant is inserted, we run the test suite.</p><ul><li><p>If test suite failed it&#8217;s a good sign and it means that mutant was eliminated  (this increases the mutation score.)  This happens when there is a test case that is testing against the age &lt; 18.</p></li><li><p>If tests succeeded means that mutant survived and this lowers the mutation score. (which implies there was no test that captured the bug/mutant we introduced above)<br><br></p></li></ul><p>&#8505;&#65039; The mutation score is:</p><blockquote><p>eliminated mutants / total mutants</p></blockquote><p>A mutation score of ~<strong>0%</strong> in code-covered areas probably means the tests are&#8230; &#128465;&#65039;&#128517;</p><p></p><p>Now, we&#8217;ve described the process for a single mutation. But how do we generate <em>many</em> mutants automatically and summarize the results in a clean report? </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jMST!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jMST!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 424w, https://substackcdn.com/image/fetch/$s_!jMST!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 848w, https://substackcdn.com/image/fetch/$s_!jMST!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 1272w, https://substackcdn.com/image/fetch/$s_!jMST!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jMST!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png" width="427" height="304.3995077932732" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:869,&quot;width&quot;:1219,&quot;resizeWidth&quot;:427,&quot;bytes&quot;:143273,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/184911673?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jMST!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 424w, https://substackcdn.com/image/fetch/$s_!jMST!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 848w, https://substackcdn.com/image/fetch/$s_!jMST!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 1272w, https://substackcdn.com/image/fetch/$s_!jMST!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77476913-0642-40a3-9a4d-167fba0b9452_1219x869.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mutation score &#128640;</figcaption></figure></div><h2>Muter CLI &#129503;</h2><p>Automated mutation testing for Swift <br><a href="https://github.com/muter-mutation-testing/muter">https://github.com/muter-mutation-testing/muter</a></p><p>It&#8217;s really easy for anyone to use:</p><ol><li><p>Install the CLI via homebrew </p></li><li><p>Provide a muter.conf.yml (this tells Muter how to run your tests)</p></li><li><p>Run it on your most important files and see how well tested they are &#129310;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MsOh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MsOh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 424w, https://substackcdn.com/image/fetch/$s_!MsOh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 848w, https://substackcdn.com/image/fetch/$s_!MsOh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 1272w, https://substackcdn.com/image/fetch/$s_!MsOh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MsOh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png" width="418" height="238.27692307692308" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:704,&quot;width&quot;:1235,&quot;resizeWidth&quot;:418,&quot;bytes&quot;:209977,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/184911673?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!MsOh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 424w, https://substackcdn.com/image/fetch/$s_!MsOh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 848w, https://substackcdn.com/image/fetch/$s_!MsOh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 1272w, https://substackcdn.com/image/fetch/$s_!MsOh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1742159-581c-4e5a-bace-eb4668140d0b_1235x704.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Muter gives a detailed report that you can use to understand the weak spots on your test.</figcaption></figure></div></li></ol><p></p><blockquote><p>This can also be applied on the CI level to run on changed files. This can give valuable feedback to the reviewer/author. This is possible with the --files-to-mutate flag.</p></blockquote><p><strong>Practical Advice <br></strong><br>One important thing to keep in mind. Mutation testing can become slow depending on how many files you mutate.</p><p>So I recommend starting small &#9989; run it selectively on files with heavy business logic first instead of trying to mutate your entire codebase from first run.</p><h2>Last thoughts &#128173;</h2><p>Mutation testing is still not very popular in the Swift community, especially compared to ecosystems like JavaScript..<br><br>But I genuinely believe it provides that &#8220;extra something&#8221; an additional layer of confidence when writing tests (whether you write them yourself or with a little help from AI &#128517;).</p><blockquote><p>I hope in the future Xcode support more customization so that mutation score was an option on Xcode to show directly in editor as codecoverage is doing already.</p></blockquote><p></p><p>Once you start thinking in terms of <em>&#8220;<strong>would my tests actually catch a bug?</strong>&#8221;</em> instead of just <em>&#8220;<strong>did this line execute?</strong>&#8221;</em>, it becomes clear why mutation testing is such a powerful addition to your testing toolbox.<br><br>Looking ahead to hear your thoughts and ideas<br>See you in the next article &#128640; </p><p>Konstantinos Nikoloutsos</p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The Git Trick That Will Attract Recruiters 🚀]]></title><description><![CDATA[Don't let an "empty" Github contribution graph cost you an interview.]]></description><link>https://codingwithkonsta.substack.com/p/the-git-trick-that-will-attract-recruiters</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/the-git-trick-that-will-attract-recruiters</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Fri, 09 Jan 2026 08:01:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!R5ml!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!R5ml!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!R5ml!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!R5ml!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!R5ml!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!R5ml!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!R5ml!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1869208,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/183968083?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!R5ml!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!R5ml!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!R5ml!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!R5ml!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1895596f-daca-4bdb-a93c-ac90d3a7920e_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Before I start, happy new year to you and your families&#127881;.<br>New year, new goals, new job listings&#8230;, and I want to make sure you are ready for them &#127919;</p><h3>The Problem: The &#8220;Invisible&#8221; Work &#128123;</h3><p>I was scrolling through LinkedIn recently and noticed:<br>many job descriptions ask for an "<strong>active GitHub account</strong>".<br>Recruiters often use that green contribution graph as a quick "pulse check" to see if a candidate "loves writing code &#129489;&#8205;&#128187;" </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>But here is the reality: many of us work for companies that use <strong>Azure DevOps</strong>, <strong>Bitbucket</strong>, or internal <strong>GitLab</strong> instances (I know the pain &#129326;). You might be writing high-quality code for 8+ hours a day, but because it&#8217;s not on your personal GitHub account, your profile looks like a  The Upside Down from stranger things &#128520;.<br>When a company has hundreds of candidates to screen, an empty graph might be the reason you may not pass the initial screening phase &#128542;</p><h3>Let&#8217;s make our commit Graph Greener &#129001;</h3><blockquote><p><strong>Disclaimer:</strong> Please don&#8217;t tell recruiters about this &#128517;</p></blockquote><ul><li><p>Make a private repository on Github and clone it locally.</p></li><li><p>Open terminal and make your first commit (e.g on january first of 2025) </p></li></ul><blockquote><p><code>git commit --date=1735689600 -m "&#9198;&#65039;&#9200;"<br>(* The magic number is the timestamp &#128070;)</code></p></blockquote><ul><li><p>Yea that&#8217;s it, now if you &#8220;<em>git log&#8221; you will see a commit on 01/01/2025, congrats &#128079; </em> Well now you know what&#8217;s the next step, just iterate step 2 with different timestamp &#128257;</p></li><li><p>Once you finish, push the changes. and enjoy an increased interview success rate.</p><p></p></li></ul><p>My best friend Claude Code already create a simple script that you can find in the end of this article (anthropic &#10084;&#65039;)</p><h3>Bonus Points: The Artist&#8217;s Touch &#127912;</h3><p><br>For the creative people in our community, you can take this even further. By precisely timing your commits, you can actually "draw" on your contribution graph or even spell out your name. It&#8217;s a fancy way to impress someone &#128640;<br><br>For doing that I recommend using this <a href="https://github.com/gelstudios/gitfiti">open source-library</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p1GU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p1GU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 424w, https://substackcdn.com/image/fetch/$s_!p1GU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 848w, https://substackcdn.com/image/fetch/$s_!p1GU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 1272w, https://substackcdn.com/image/fetch/$s_!p1GU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p1GU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png" width="692" height="197" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69288e32-b519-4321-9d27-007aa859f0cd_692x197.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:197,&quot;width&quot;:692,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;screenshot of gitfiti&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="screenshot of gitfiti" title="screenshot of gitfiti" srcset="https://substackcdn.com/image/fetch/$s_!p1GU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 424w, https://substackcdn.com/image/fetch/$s_!p1GU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 848w, https://substackcdn.com/image/fetch/$s_!p1GU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 1272w, https://substackcdn.com/image/fetch/$s_!p1GU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69288e32-b519-4321-9d27-007aa859f0cd_692x197.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3>Let&#8217;s be realistic &#129417;</h3><p>Now that I drew your attention about git, let&#8217;s be honest, git is a power-tool. </p><p>If you don't know how to handle a rebase, fix a conflict, or manage a new release, your "green graph" is a lie that will be exposed in the first week of your new job.</p><p>In the upcoming post I will share with you some of my must-have git commands that everyone should know.</p><p>Let&#8217;s make our profiles look pro, but let&#8217;s make our skills undeniable &#128170;<br>Konstantinos Nikoloutsos</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! &#10084;&#65039;Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="github-gist" data-attrs="{&quot;innerHTML&quot;:&quot;<div id=\&quot;gist144313927\&quot; class=\&quot;gist\&quot;>\n    <div class=\&quot;gist-file\&quot; translate=\&quot;no\&quot; data-color-mode=\&quot;light\&quot; data-light-theme=\&quot;light\&quot;>\n      <div class=\&quot;gist-data\&quot;>\n        <div class=\&quot;js-gist-file-update-container js-task-list-container\&quot;>\n  <div id=\&quot;file-git_commit_script-sh\&quot; class=\&quot;file my-2\&quot;>\n    \n    <div itemprop=\&quot;text\&quot;\n      class=\&quot;Box-body p-0 blob-wrapper data type-shell  \&quot;\n      style=\&quot;overflow: auto\&quot; tabindex=\&quot;0\&quot; role=\&quot;region\&quot;\n      aria-label=\&quot;git_commit_script.sh content, created by Nikoloutsos on 11:56PM yesterday.\&quot;\n    >\n\n        \n<div class=\&quot;js-check-hidden-unicode js-blob-code-container blob-code-content\&quot;>\n\n  <template class=\&quot;js-file-alert-template\&quot;>\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash flash-warn flash-full d-flex flex-items-center\&quot;>\n  <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.co/hiddenchars\&quot; target=\&quot;_blank\&quot;>Learn more about bidirectional Unicode characters</a>\n    </span>\n\n\n  <div data-view-component=\&quot;true\&quot; class=\&quot;flash-action\&quot;>        <a href=\&quot;{{ revealButtonHref }}\&quot; data-view-component=\&quot;true\&quot; class=\&quot;btn-sm btn\&quot;>    Show hidden characters\n</a>\n</div>\n</div></template>\n<template class=\&quot;js-line-alert-template\&quot;>\n  <span aria-label=\&quot;This line has hidden Unicode characters\&quot; data-view-component=\&quot;true\&quot; class=\&quot;line-alert tooltipped tooltipped-e\&quot;>\n    <svg aria-hidden=\&quot;true\&quot; height=\&quot;16\&quot; viewBox=\&quot;0 0 16 16\&quot; version=\&quot;1.1\&quot; width=\&quot;16\&quot; data-view-component=\&quot;true\&quot; class=\&quot;octicon octicon-alert\&quot;>\n    <path d=\&quot;M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\&quot;></path>\n</svg>\n</span></template>\n\n  <table data-hpc class=\&quot;highlight tab-size js-file-line-container\&quot; data-tab-size=\&quot;4\&quot; data-paste-markdown-skip data-tagsearch-path=\&quot;git_commit_script.sh\&quot;>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L1\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;1\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC1\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#!</span>/bin/bash</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L2\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;2\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC2\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L3\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;3\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC3\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Starting timestamp: January 1, 2025 00:00:00 UTC</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L4\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;4\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC4\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>start_timestamp=1735689600</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L5\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;5\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC5\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L6\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;6\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC6\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Ending timestamp: January 1, 2026 00:00:00 UTC</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L7\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;7\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC7\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>end_timestamp=1767225600</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L8\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;8\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC8\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L9\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;9\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC9\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Current timestamp</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L10\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;10\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC10\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>current=<span class=\&quot;pl-smi\&quot;>$start_timestamp</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L11\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;11\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC11\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L12\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;12\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC12\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Counter for commit messages</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L13\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;13\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC13\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>counter=1</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L14\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;14\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC14\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L15\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;15\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC15\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Loop through timestamps</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L16\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;16\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC16\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>while</span> [ <span class=\&quot;pl-smi\&quot;>$current</span> <span class=\&quot;pl-k\&quot;>-le</span> <span class=\&quot;pl-smi\&quot;>$end_timestamp</span> ]<span class=\&quot;pl-k\&quot;>;</span> <span class=\&quot;pl-k\&quot;>do</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L17\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;17\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC17\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Create a dummy change</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L18\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;18\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC18\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c1\&quot;>echo</span> <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>Commit <span class=\&quot;pl-smi\&quot;>$counter</span> at timestamp <span class=\&quot;pl-smi\&quot;>$current</span><span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span> <span class=\&quot;pl-k\&quot;>&amp;gt;&amp;gt;</span> activity.txt</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L19\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;19\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC19\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  </td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L20\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;20\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC20\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Stage the change</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L21\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;21\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC21\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  git add activity.txt</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L22\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;22\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC22\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  </td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L23\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;23\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC23\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Commit with custom date</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L24\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;24\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC24\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  git commit --date=<span class=\&quot;pl-smi\&quot;>$current</span> -m <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>Activity commit #<span class=\&quot;pl-smi\&quot;>$counter</span><span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L25\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;25\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC25\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  </td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L26\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;26\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC26\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c1\&quot;>echo</span> <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>Created commit #<span class=\&quot;pl-smi\&quot;>$counter</span> for timestamp <span class=\&quot;pl-smi\&quot;>$current</span><span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L27\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;27\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC27\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  </td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L28\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;28\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC28\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Generate random increment between 0.6 and 2 days in seconds</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L29\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;29\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC29\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> 0.6 days = 51840 seconds</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L30\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;30\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC30\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> 2 days = 172800 seconds</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L31\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;31\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC31\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Range = 172800 - 51840 = 120960 seconds</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L32\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;32\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC32\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  random_increment=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>$((</span><span class=\&quot;pl-c1\&quot;>51840</span> <span class=\&quot;pl-k\&quot;>+</span> RANDOM <span class=\&quot;pl-k\&quot;>%</span> <span class=\&quot;pl-c1\&quot;>120961</span><span class=\&quot;pl-pds\&quot;>))</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L33\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;33\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC33\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  </td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L34\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;34\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC34\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  <span class=\&quot;pl-c\&quot;><span class=\&quot;pl-c\&quot;>#</span> Increment timestamp by random amount</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L35\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;35\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC35\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  current=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>$((</span>current <span class=\&quot;pl-k\&quot;>+</span> random_increment<span class=\&quot;pl-pds\&quot;>))</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L36\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;36\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC36\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>  counter=<span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>$((</span>counter <span class=\&quot;pl-k\&quot;>+</span> <span class=\&quot;pl-c1\&quot;>1</span><span class=\&quot;pl-pds\&quot;>))</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L37\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;37\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC37\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-k\&quot;>done</span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L38\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;38\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC38\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;>\n</td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L39\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;39\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC39\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c1\&quot;>echo</span> <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>Done! Created <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>$((</span>counter <span class=\&quot;pl-k\&quot;>-</span> <span class=\&quot;pl-c1\&quot;>1</span><span class=\&quot;pl-pds\&quot;>))</span></span> commits<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n        <tr>\n          <td id=\&quot;file-git_commit_script-sh-L40\&quot; class=\&quot;blob-num js-line-number js-blob-rnum\&quot; data-line-number=\&quot;40\&quot;></td>\n          <td id=\&quot;file-git_commit_script-sh-LC40\&quot; class=\&quot;blob-code blob-code-inner js-file-line\&quot;><span class=\&quot;pl-c1\&quot;>echo</span> <span class=\&quot;pl-s\&quot;><span class=\&quot;pl-pds\&quot;>&amp;quot;</span>Run &amp;#39;git push&amp;#39; to push to your repository<span class=\&quot;pl-pds\&quot;>&amp;quot;</span></span></td>\n        </tr>\n  </table>\n</div>\n\n\n    </div>\n\n  </div>\n</div>\n\n      </div>\n      <div class=\&quot;gist-meta\&quot;>\n        <a href=\&quot;https://gist.github.com/Nikoloutsos/c227c00b00c223393321306346791310/raw/290a49b6e02d69594531e6f56701655deaa4408e/git_commit_script.sh\&quot; style=\&quot;float:right\&quot; class=\&quot;Link--inTextBlock\&quot;>view raw</a>\n        <a href=\&quot;https://gist.github.com/Nikoloutsos/c227c00b00c223393321306346791310#file-git_commit_script-sh\&quot; class=\&quot;Link--inTextBlock\&quot;>\n          git_commit_script.sh\n        </a>\n        hosted with &amp;#10084; by <a class=\&quot;Link--inTextBlock\&quot; href=\&quot;https://github.com\&quot;>GitHub</a>\n      </div>\n    </div>\n</div>\n&quot;,&quot;stylesheet&quot;:&quot;https://github.githubassets.com/assets/gist-embed-68783a026c0c.css&quot;}" data-component-name="GitgistToDOM"><link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-68783a026c0c.css"><div id="gist144313927" class="gist">
    <div class="gist-file" data-color-mode="light" data-light-theme="light">
      <div class="gist-data">
        <div class="js-gist-file-update-container js-task-list-container">
  <div id="file-git_commit_script-sh" class="file my-2">
    
    <div itemprop="text" class="Box-body p-0 blob-wrapper data type-shell  " style="overflow:auto">

        
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">

  
  <div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  
    

    <span>
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
    </span>


  <div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters
</a>
</div>
</div>

  <span data-view-component="true" class="line-alert tooltipped tooltipped-e">
    
    

</span>

  <table data-hpc="" class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip="" data-tagsearch-path="git_commit_script.sh">
        <tbody><tr>
          <td id="file-git_commit_script-sh-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
          <td id="file-git_commit_script-sh-LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#!</span>/bin/bash</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
          <td id="file-git_commit_script-sh-LC2" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
          <td id="file-git_commit_script-sh-LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#</span> Starting timestamp: January 1, 2025 00:00:00 UTC</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
          <td id="file-git_commit_script-sh-LC4" class="blob-code blob-code-inner js-file-line">start_timestamp=1735689600</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
          <td id="file-git_commit_script-sh-LC5" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
          <td id="file-git_commit_script-sh-LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#</span> Ending timestamp: January 1, 2026 00:00:00 UTC</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
          <td id="file-git_commit_script-sh-LC7" class="blob-code blob-code-inner js-file-line">end_timestamp=1767225600</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
          <td id="file-git_commit_script-sh-LC8" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
          <td id="file-git_commit_script-sh-LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#</span> Current timestamp</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
          <td id="file-git_commit_script-sh-LC10" class="blob-code blob-code-inner js-file-line">current=<span class="pl-smi">$start_timestamp</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
          <td id="file-git_commit_script-sh-LC11" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
          <td id="file-git_commit_script-sh-LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#</span> Counter for commit messages</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
          <td id="file-git_commit_script-sh-LC13" class="blob-code blob-code-inner js-file-line">counter=1</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
          <td id="file-git_commit_script-sh-LC14" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
          <td id="file-git_commit_script-sh-LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">#</span> Loop through timestamps</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
          <td id="file-git_commit_script-sh-LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-k">while</span> [ <span class="pl-smi">$current</span> <span class="pl-k">-le</span> <span class="pl-smi">$end_timestamp</span> ]<span class="pl-k">;</span> <span class="pl-k">do</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
          <td id="file-git_commit_script-sh-LC17" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> Create a dummy change</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
          <td id="file-git_commit_script-sh-LC18" class="blob-code blob-code-inner js-file-line">  <span class="pl-c1">echo</span> <span class="pl-s"><span class="pl-pds">"</span>Commit <span class="pl-smi">$counter</span> at timestamp <span class="pl-smi">$current</span><span class="pl-pds">"</span></span> <span class="pl-k">&gt;&gt;</span> activity.txt</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
          <td id="file-git_commit_script-sh-LC19" class="blob-code blob-code-inner js-file-line">  </td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
          <td id="file-git_commit_script-sh-LC20" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> Stage the change</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
          <td id="file-git_commit_script-sh-LC21" class="blob-code blob-code-inner js-file-line">  git add activity.txt</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
          <td id="file-git_commit_script-sh-LC22" class="blob-code blob-code-inner js-file-line">  </td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
          <td id="file-git_commit_script-sh-LC23" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> Commit with custom date</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
          <td id="file-git_commit_script-sh-LC24" class="blob-code blob-code-inner js-file-line">  git commit --date=<span class="pl-smi">$current</span> -m <span class="pl-s"><span class="pl-pds">"</span>Activity commit #<span class="pl-smi">$counter</span><span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
          <td id="file-git_commit_script-sh-LC25" class="blob-code blob-code-inner js-file-line">  </td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
          <td id="file-git_commit_script-sh-LC26" class="blob-code blob-code-inner js-file-line">  <span class="pl-c1">echo</span> <span class="pl-s"><span class="pl-pds">"</span>Created commit #<span class="pl-smi">$counter</span> for timestamp <span class="pl-smi">$current</span><span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
          <td id="file-git_commit_script-sh-LC27" class="blob-code blob-code-inner js-file-line">  </td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
          <td id="file-git_commit_script-sh-LC28" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> Generate random increment between 0.6 and 2 days in seconds</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
          <td id="file-git_commit_script-sh-LC29" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> 0.6 days = 51840 seconds</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
          <td id="file-git_commit_script-sh-LC30" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> 2 days = 172800 seconds</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
          <td id="file-git_commit_script-sh-LC31" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> Range = 172800 - 51840 = 120960 seconds</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
          <td id="file-git_commit_script-sh-LC32" class="blob-code blob-code-inner js-file-line">  random_increment=<span class="pl-s"><span class="pl-pds">$((</span><span class="pl-c1">51840</span> <span class="pl-k">+</span> RANDOM <span class="pl-k">%</span> <span class="pl-c1">120961</span><span class="pl-pds">))</span></span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
          <td id="file-git_commit_script-sh-LC33" class="blob-code blob-code-inner js-file-line">  </td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
          <td id="file-git_commit_script-sh-LC34" class="blob-code blob-code-inner js-file-line">  <span class="pl-c"><span class="pl-c">#</span> Increment timestamp by random amount</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
          <td id="file-git_commit_script-sh-LC35" class="blob-code blob-code-inner js-file-line">  current=<span class="pl-s"><span class="pl-pds">$((</span>current <span class="pl-k">+</span> random_increment<span class="pl-pds">))</span></span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
          <td id="file-git_commit_script-sh-LC36" class="blob-code blob-code-inner js-file-line">  counter=<span class="pl-s"><span class="pl-pds">$((</span>counter <span class="pl-k">+</span> <span class="pl-c1">1</span><span class="pl-pds">))</span></span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
          <td id="file-git_commit_script-sh-LC37" class="blob-code blob-code-inner js-file-line"><span class="pl-k">done</span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
          <td id="file-git_commit_script-sh-LC38" class="blob-code blob-code-inner js-file-line">
</td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
          <td id="file-git_commit_script-sh-LC39" class="blob-code blob-code-inner js-file-line"><span class="pl-c1">echo</span> <span class="pl-s"><span class="pl-pds">"</span>Done! Created <span class="pl-s"><span class="pl-pds">$((</span>counter <span class="pl-k">-</span> <span class="pl-c1">1</span><span class="pl-pds">))</span></span> commits<span class="pl-pds">"</span></span></td>
        </tr>
        <tr>
          <td id="file-git_commit_script-sh-L40" class="blob-num js-line-number js-blob-rnum" data-line-number="40"></td>
          <td id="file-git_commit_script-sh-LC40" class="blob-code blob-code-inner js-file-line"><span class="pl-c1">echo</span> <span class="pl-s"><span class="pl-pds">"</span>Run 'git push' to push to your repository<span class="pl-pds">"</span></span></td>
        </tr>
  </tbody></table>
</div>


    </div>

  </div>
</div>

      </div>
      <div class="gist-meta">
        <a href="https://gist.github.com/Nikoloutsos/c227c00b00c223393321306346791310/raw/290a49b6e02d69594531e6f56701655deaa4408e/git_commit_script.sh" style="float:right" class="Link--inTextBlock">view raw</a>
        <a href="https://gist.github.com/Nikoloutsos/c227c00b00c223393321306346791310#file-git_commit_script-sh" class="Link--inTextBlock">
          git_commit_script.sh
        </a>
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
    </div>
</div>
</div>]]></content:encoded></item><item><title><![CDATA[Stop Throwing Error: Typed Throws in Swift 6]]></title><description><![CDATA[How making errors explicit improves readability, safety, and API design]]></description><link>https://codingwithkonsta.substack.com/p/stop-throwing-error-typed-throws</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/stop-throwing-error-typed-throws</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Fri, 26 Dec 2025 22:34:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!g7A6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g7A6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g7A6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!g7A6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!g7A6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!g7A6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g7A6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2679250,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182657464?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!g7A6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!g7A6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!g7A6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!g7A6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb62a175-f495-48b7-8ab1-2d28db7fd618_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><br>How angry <code>&#128548;</code> would you be if you tried to understand what a function does and it returned Any?</p><pre><code><code>func nextScreen() -&gt; Any</code></code></pre><p>When you see a method, you usually have <strong>a few seconds</strong> to understand it at a high level based on its signature. You look at:</p><ul><li><p>the name, scope</p></li><li><p>the parameters</p></li><li><p>the return type (+ whether it&#8217;s async or not &#128517;)</p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>The problem with throws</strong></h2><p>Traditionally in Swift, a throwing function looks like this:</p><pre><code>func makeSantaGift(kidName: String) throws -&gt; Gift</code></pre><p>But the function signature doesn&#8217;t tell you. The error type is effectively any Error &#128553;</p><h2><strong>Typed throws to the rescue &#127876;</strong></h2><p>Starting with <strong>Swift 6.0</strong>, <strong><a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md">Typed Throw</a></strong> jumped in.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n119!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n119!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 424w, https://substackcdn.com/image/fetch/$s_!n119!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 848w, https://substackcdn.com/image/fetch/$s_!n119!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 1272w, https://substackcdn.com/image/fetch/$s_!n119!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!n119!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png" width="1456" height="570" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:570,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213234,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182657464?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!n119!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 424w, https://substackcdn.com/image/fetch/$s_!n119!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 848w, https://substackcdn.com/image/fetch/$s_!n119!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 1272w, https://substackcdn.com/image/fetch/$s_!n119!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2dbb9af-3a0b-41b5-b428-018e293bbf63_1558x610.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Now the signature tells a much clearer story.</figcaption></figure></div><p>Function&#8217;s <strong>signature is enhanced (1) (2)</strong> with more information.</p><p>The compiler now <strong>knows all possible error cases</strong>. And <strong>exhaustivity</strong> is the best part &#128071;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G0uo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G0uo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 424w, https://substackcdn.com/image/fetch/$s_!G0uo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 848w, https://substackcdn.com/image/fetch/$s_!G0uo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 1272w, https://substackcdn.com/image/fetch/$s_!G0uo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G0uo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png" width="1456" height="354" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:354,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:134614,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182657464?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!G0uo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 424w, https://substackcdn.com/image/fetch/$s_!G0uo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 848w, https://substackcdn.com/image/fetch/$s_!G0uo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 1272w, https://substackcdn.com/image/fetch/$s_!G0uo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6a04c5-113d-477b-80d4-6961ae8819ad_1956x476.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">An alternative. error is already of type SantaError</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!F5gF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!F5gF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 424w, https://substackcdn.com/image/fetch/$s_!F5gF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 848w, https://substackcdn.com/image/fetch/$s_!F5gF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 1272w, https://substackcdn.com/image/fetch/$s_!F5gF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!F5gF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png" width="1456" height="274" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:274,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:148809,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182657464?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!F5gF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 424w, https://substackcdn.com/image/fetch/$s_!F5gF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 848w, https://substackcdn.com/image/fetch/$s_!F5gF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 1272w, https://substackcdn.com/image/fetch/$s_!F5gF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5512ddc6-ec16-46c1-b674-15b57a4ff921_2404x452.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption"><code>It's still a mystery to me why compiler is not able to recognize that all enum cases have been considered. &#129300;</code></figcaption></figure></div><pre><code><code>&#128173;That means if the library adds a new error case in the future, your code will fail to compile until you handle it.</code></code></pre><p></p><p>Personally, I think <strong>Typed Throws</strong> significantly reduce the time it takes to understand what a function does without opening its implementation. Making it ideal for libraries and generally units/functions of high <a href="https://stackoverflow.com/questions/4092228/design-principle-high-fan-in-vs-high-fan-out">fan-in</a>.</p><p>Have you ever used this in your company? If not, I&#8217;d love to hear the reasons  drop a comment in the discussion section &#128071;</p><p>And since this is probably my last post of the year&#8230;<br>See you in the next article and Happy New Year &#129395;</p><p>Konstantinos Nikoloutsos</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[That One Closure That Made SwiftUI Slow]]></title><description><![CDATA[Why closures can trigger unnecessary SwiftUI re-evaluations and how to avoid it.]]></description><link>https://codingwithkonsta.substack.com/p/that-one-closure-that-made-swiftui</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/that-one-closure-that-made-swiftui</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Wed, 24 Dec 2025 00:05:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7e8q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7e8q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7e8q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7e8q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7e8q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7e8q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7e8q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1856904,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182465715?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7e8q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7e8q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7e8q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7e8q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd193c7f8-6b84-441c-9674-554d9422886b_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>SwiftUI and generally declarative UI allows us to ship screens faster than ever. But writing UI code quickly doesn&#8217;t automatically mean our app performs well.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>One of the most common performance issues in SwiftUI is excessive view re-evaluation, meaning that body property get recalculated more often than needed. Well what&#8217;s the problem? This can lead to FPS decrease and make app scroll not smooth &#128034;.</p><p>&#128073;After this article you will know why some people believe that closures are evil to SwiftUI and we will take a look at some suggestion both by community and Apple itself.</p><h2><strong>When does SwiftUI re-evaluates a view?</strong></h2><p>To understand the problem, we need to clarify <strong>when SwiftUI actually re-evaluates a view</strong>. A view is re-evaluated <strong>only when one of its dependencies changes</strong>.</p><pre><code>By dependencies we mean the properties the view&#8217;s body depends on.</code></pre><p>If none of those properties change, SwiftUI can skip that view during diffing and reuse the previous View &#9889;&#65039;. </p><pre><code>&#8505;&#65039; This is why it is considered a good approach to split your View into smaller ones. So that SwiftUI diffing can skip views that need no re-evaluated.</code></pre><h2>Re-evaluation &#8800; Re-render<strong> (A common mistake)</strong></h2><p>If a view is Re-rendered it has been re-evaluated. But the opposite is not true.<br>In SwiftUI, <strong>re-evaluation</strong> (recomputing the <code>body</code>) happens frequently when dependencies change and is cheap since it just creates lightweight structs. </p><p><strong>Re-rendering</strong> (updating pixels on screen &#127912;) only occurs when SwiftUI's diffing detects actual changes, but most re-evaluations produce identical views and skip rendering, which is critical because constantly re-rendering would drop FPS and make iOS apps not happy.</p><p><br>Thanks to <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Michael Long&quot;,&quot;id&quot;:16859817,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d94e4d9c-aa6f-4790-be70-8914133cdc03_785x785.jpeg&quot;,&quot;uuid&quot;:&quot;836470a0-5047-4c0c-adc5-304af08fcd5a&quot;}" data-component-name="MentionToDOM"></span> and <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;AJ Rivera&quot;,&quot;id&quot;:270960475,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dc9cd9e6-562f-460a-9cab-8010835634d4_1024x1024.png&quot;,&quot;uuid&quot;:&quot;a72e4ea8-b24e-4f6f-89b0-d9672081b999&quot;}" data-component-name="MentionToDOM"></span> for pointing this one out.</p><h2><strong>The problem &#129488;</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9HQL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9HQL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 424w, https://substackcdn.com/image/fetch/$s_!9HQL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 848w, https://substackcdn.com/image/fetch/$s_!9HQL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 1272w, https://substackcdn.com/image/fetch/$s_!9HQL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9HQL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png" width="1456" height="862" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:862,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:357159,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182465715?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9HQL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 424w, https://substackcdn.com/image/fetch/$s_!9HQL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 848w, https://substackcdn.com/image/fetch/$s_!9HQL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 1272w, https://substackcdn.com/image/fetch/$s_!9HQL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff069beeb-7c69-45e3-86a6-d2662bab85b1_2242x1328.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You have:</p><ul><li><p>a parent view</p></li><li><p>a ChildView</p></li><li><p>a closure passed from the parent to the child</p></li><li><p>a button that triggers a redraw</p></li></ul><p>What do you think should happen when you tap the <strong>&#8220;Redraw&#8221;</strong> button?<br>Should ChildView be re-evaluated?  Take your time &#9201;&#65039;</p><p>Let&#8217;s use <strong>Self._PrintChanges() </strong>and tap the button 8 times and see what happens.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9LrH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9LrH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 424w, https://substackcdn.com/image/fetch/$s_!9LrH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 848w, https://substackcdn.com/image/fetch/$s_!9LrH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 1272w, https://substackcdn.com/image/fetch/$s_!9LrH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9LrH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png" width="856" height="706" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:706,&quot;width&quot;:856,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:164957,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182465715?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9LrH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 424w, https://substackcdn.com/image/fetch/$s_!9LrH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 848w, https://substackcdn.com/image/fetch/$s_!9LrH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 1272w, https://substackcdn.com/image/fetch/$s_!9LrH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79f2e36b-61f8-4d09-8344-622ce4bc5322_856x706.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>ChildView is re-evaluated <strong>every single time</strong>, even though none of its visible data changed. &#128561;</p><pre><code>&#10071;&#65039;Imagine the cost of something like that on a DashboardScreen that has many components inside.</code></pre><h2><strong>Why is this happening?</strong></h2><p>The root cause of the problem is that swift closures and equitability doesn&#8217;t go well together. </p><div class="callout-block" data-callout="true"><p>Stay to the end to see what Apple engineers recommended in their recent Q&amp;A session.</p></div><p>At this point you might be thinking &#8220;<em>How many closures have I passed to my views?</em>&#8220; Well you are not alone &#128517;</p><h2>Solution:</h2><p>One of the quickest solutions is to wrap the closure and provide your own Equitability. This will make SwiftUI diffing life so much easier but the developer will have to explicitly change the properties that define the equitability (the id in this case) so that the childView takes the updated closure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YDOZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YDOZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 424w, https://substackcdn.com/image/fetch/$s_!YDOZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 848w, https://substackcdn.com/image/fetch/$s_!YDOZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 1272w, https://substackcdn.com/image/fetch/$s_!YDOZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YDOZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png" width="1208" height="902" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:902,&quot;width&quot;:1208,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:208800,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/182465715?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YDOZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 424w, https://substackcdn.com/image/fetch/$s_!YDOZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 848w, https://substackcdn.com/image/fetch/$s_!YDOZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 1272w, https://substackcdn.com/image/fetch/$s_!YDOZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F082bfb9f-41fe-4a41-83dc-036158b396b1_1208x902.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Read more <a href="https://medium.com/@kurtlee/swiftui-closure-is-evil-7e7b740bd4cc">here</a></figcaption></figure></div><p><br><strong>So&#8230; are closures the real problem?</strong></p><p>Short answer: <strong>not really &#129300;</strong></p><p>This isn&#8217;t something Apple can &#8220;just fix&#8221;. The real issue is <em>what closures capture</em>. In our example, the closure implicitly captured <code>self</code> because it depended on <code>foo</code> property .That means the closure effectively depends on <strong>the entire view value</strong>, not just one property and that explains probable the reasoning behind closures and equitability.</p><pre><code>For the shake of this article I did some experiments and explicitly added foo in the capture list and the body was not recalculated every time &#11088;&#65039;</code></pre><h2>What Apple engineers said?</h2><h4><strong>Q: Is there a good pattern to pass an action closure to a view while minimizing impact, given that closures are hard to compare? Is there a more performant alternative?</strong></h4><p>A: Try to capture as little as possible in closures&#8212;for example, by not relying on implicit captures (which usually capture self and therefore depend on the whole view value) and instead capturing only the properties of the view value that you actually need in the closure.</p><p></p><p>Big thanks to <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Anton Gubarenko&quot;,&quot;id&quot;:123970311,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1eb672de-f6cd-47a2-98b2-6de3f5be6ffe_2316x3088.jpeg&quot;,&quot;uuid&quot;:&quot;b456668c-8327-4f19-812d-4cccd1a26ba8&quot;}" data-component-name="MentionToDOM"></span> for writing the <a href="https://antongubarenko.substack.com/p/optimize-your-apps-speed-and-efficiency">Q&amp;A</a> from <strong>Optimize Your App&#8217;s Speed and Efficiency session.</strong></p><div id="youtube2-yXAQTIKR8fk" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;yXAQTIKR8fk&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/yXAQTIKR8fk?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>See you in the next article, till then I wish you have many productive coding sessions &#11088;&#65039; </p><p>Konstantinos Nikoloutsos</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Testing async code in Swift Testing: Why confirmation() is not working?]]></title><description><![CDATA[Learn why confirmation() doesn&#8217;t behave like XCTestExpectation and what to use instead.]]></description><link>https://codingwithkonsta.substack.com/p/testing-async-code-in-swift-testing</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/testing-async-code-in-swift-testing</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Mon, 13 Oct 2025 07:35:27 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!UMOi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UMOi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UMOi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 424w, https://substackcdn.com/image/fetch/$s_!UMOi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 848w, https://substackcdn.com/image/fetch/$s_!UMOi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 1272w, https://substackcdn.com/image/fetch/$s_!UMOi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UMOi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png" width="1125" height="750" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:750,&quot;width&quot;:1125,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:529749,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://codingwithkonsta.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UMOi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 424w, https://substackcdn.com/image/fetch/$s_!UMOi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 848w, https://substackcdn.com/image/fetch/$s_!UMOi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 1272w, https://substackcdn.com/image/fetch/$s_!UMOi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38676112-2247-40e3-bc2c-e5866740cf98_1125x750.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>With the new Swift Testing framework, Apple introduced the <a href="https://developer.apple.com/documentation/testing/confirmation">Confirmation API</a> which many developers treat as interchangeable with <a href="https://developer.apple.com/documentation/xctest/xctestexpectation">XCTExpectation</a>. </p><blockquote><p>This is a common misconception, even myself before learning it.</p></blockquote><p>Suppose that we want to test for the following code. How would you write a test? </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!APsL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!APsL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 424w, https://substackcdn.com/image/fetch/$s_!APsL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 848w, https://substackcdn.com/image/fetch/$s_!APsL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 1272w, https://substackcdn.com/image/fetch/$s_!APsL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!APsL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png" width="1456" height="736" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:736,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:200007,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://importkostasniks.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!APsL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 424w, https://substackcdn.com/image/fetch/$s_!APsL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 848w, https://substackcdn.com/image/fetch/$s_!APsL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 1272w, https://substackcdn.com/image/fetch/$s_!APsL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91d6eb76-b51f-4ca0-ad67-b63f29a9836c_1536x776.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If your first thought was to use XCTExpectation then that would work fine and the test would pass &#9989;.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0tQK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0tQK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 424w, https://substackcdn.com/image/fetch/$s_!0tQK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 848w, https://substackcdn.com/image/fetch/$s_!0tQK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 1272w, https://substackcdn.com/image/fetch/$s_!0tQK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0tQK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png" width="1456" height="692" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:692,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:241998,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://importkostasniks.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0tQK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 424w, https://substackcdn.com/image/fetch/$s_!0tQK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 848w, https://substackcdn.com/image/fetch/$s_!0tQK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 1272w, https://substackcdn.com/image/fetch/$s_!0tQK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d733b3b-5711-44f4-bf1f-b64d7f6d0c56_1486x706.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But what would be the swift testing equivalent &#129300; </p><h1>The problem</h1><p><br>Let&#8217;s try migrating the above test to Swift Testing using Confirmation.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sywg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sywg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 424w, https://substackcdn.com/image/fetch/$s_!sywg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 848w, https://substackcdn.com/image/fetch/$s_!sywg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 1272w, https://substackcdn.com/image/fetch/$s_!sywg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sywg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png" width="1456" height="390" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac400727-e4e7-48a0-be52-bd190d605670_2216x594.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:390,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:221829,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://importkostasniks.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sywg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 424w, https://substackcdn.com/image/fetch/$s_!sywg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 848w, https://substackcdn.com/image/fetch/$s_!sywg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 1272w, https://substackcdn.com/image/fetch/$s_!sywg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac400727-e4e7-48a0-be52-bd190d605670_2216x594.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Wait a second, why is it failing? Shouldn&#8217;t the confirmation wait until the <em>confirmation.confirm()</em> is called? What have we done wrong?</p><p>Nothing is wrong, it is just expected behavior from confirmation, as <a href="https://developer.apple.com/documentation/testing/migratingfromxctest">Apple documentation</a> clearly states the following:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NzK_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NzK_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 424w, https://substackcdn.com/image/fetch/$s_!NzK_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 848w, https://substackcdn.com/image/fetch/$s_!NzK_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 1272w, https://substackcdn.com/image/fetch/$s_!NzK_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NzK_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png" width="1166" height="108" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:108,&quot;width&quot;:1166,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32919,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://importkostasniks.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NzK_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 424w, https://substackcdn.com/image/fetch/$s_!NzK_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 848w, https://substackcdn.com/image/fetch/$s_!NzK_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 1272w, https://substackcdn.com/image/fetch/$s_!NzK_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f03c057-b7f1-433b-acc7-053fa54100d8_1166x108.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This means that confirmation is not waiting until <em>confirmation.confirm()</em> is called. In addition, it asserts if <em>confirmation.confirm()</em> was called once the closure provided exits.</p><pre><code>&#9888;&#65039; Some developers might say: &#8220;Well, userLikedVideo() should have been async so we avoid uncontrolled tasks after the function exits.&#8221;

That&#8217;s a valid point in many cases, but sometimes you want a fire and forget approach.</code></pre><h1>The solution</h1><p>We basically need a way to synchronize some asynchronous code in the testing. That sounds something that <a href="https://developer.apple.com/documentation/swift/withcheckedcontinuation(isolation:function:_:)">withCheckedContinuation</a> could do. Let&#8217;s see it in action &#127937;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OI0f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OI0f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 424w, https://substackcdn.com/image/fetch/$s_!OI0f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 848w, https://substackcdn.com/image/fetch/$s_!OI0f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 1272w, https://substackcdn.com/image/fetch/$s_!OI0f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OI0f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png" width="1456" height="600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:600,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:230086,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://importkostasniks.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OI0f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 424w, https://substackcdn.com/image/fetch/$s_!OI0f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 848w, https://substackcdn.com/image/fetch/$s_!OI0f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 1272w, https://substackcdn.com/image/fetch/$s_!OI0f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334d2b8e-fec2-4ee7-92c6-fe082b71ff4c_1582x652.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>(1) We await until withCheckedContinuation is resumed/finished.<br>(2) When the asynchronous operation finish we call resume() to proceed to assertion/expectation phase.<br>(3) We do an action that we want to unit test.<br>(4) We do the assertion and it is guaranteed that the asynchronous code has finished &#127881;</p><h1>Bonus points &#127920;</h1><p>Let&#8217;s say we ship this code. Months later, a developer reports that tests are taking too long &#9200;.<br><br>Why? &#129318;&#8205;&#9794;&#65039;</p><p>Because we assumed step (2),  the call to resume(),  would always happen. If production code changes and stops calling trackVideoLiked() then the test will hang until the timeout is reached.</p><p>And here&#8217;s the tricky part:</p><p>You might think, <em>&#8220;I&#8217;ll just set the Swift test limit trait to 2 seconds.&#8221;<br></em>Unfortunately, that&#8217;s not possible as the <strong>minimum</strong> timeout per test is 1 minute. You can read more about this in the <a href="https://developer.apple.com/documentation/testing/limitingexecutiontime">documentation</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-lOP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-lOP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 424w, https://substackcdn.com/image/fetch/$s_!-lOP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 848w, https://substackcdn.com/image/fetch/$s_!-lOP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 1272w, https://substackcdn.com/image/fetch/$s_!-lOP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-lOP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png" width="1456" height="143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:143,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50923,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://importkostasniks.substack.com/i/170113840?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-lOP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 424w, https://substackcdn.com/image/fetch/$s_!-lOP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 848w, https://substackcdn.com/image/fetch/$s_!-lOP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 1272w, https://substackcdn.com/image/fetch/$s_!-lOP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F924d5924-7437-4a84-b5ab-3df282d3ee7e_1470x144.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">The time developer has to wait until he realizes that test failed.</figcaption></figure></div><p><br>So what are we doing now? We give up? One solution that I&#8217;ve seen on the community is <a href="https://gist.github.com/janodev/32217b09f307da8c96e2cf629c31a8eb">this</a> by Alejandro Ramirez which allows defining a maxtime to wait.</p><p>My personal recommendation is first try to refactor your code not to have uncontrolled asynchronous code just like we had in this article with the Task being created inside the function. And if there is nothing else you can do feel free to use the withCheckedContinuation as an alternative.</p><pre><code>&#10071;&#65039;Sometimes it&#8217;s not a bad idea to stick with XCTest if something is hard to test with Swift Testing. Having stable and reliable tests can be more valuable than always using the latest technology.</code></pre><p>If you&#8217;ve encountered something similar, I&#8217;d love to hear your thoughts in the comments.</p><p>See you in the next article! &#128075;&#128170;<br>Konstantinos Nikoloutsos</p><p></p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Konstantinos&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Coming soon]]></title><description><![CDATA[This is Konstantinos&#8217;s Substack.]]></description><link>https://codingwithkonsta.substack.com/p/coming-soon</link><guid isPermaLink="false">https://codingwithkonsta.substack.com/p/coming-soon</guid><dc:creator><![CDATA[Konstantinos Nikoloutsos]]></dc:creator><pubDate>Sun, 03 Aug 2025 14:52:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!X05u!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a6260c3-a80c-4258-9c99-cfb9416dcc63_276x276.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is Konstantinos&#8217;s Substack.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://codingwithkonsta.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://codingwithkonsta.substack.com/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item></channel></rss>