<?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[Jacob’s Tech Tavern]]></title><description><![CDATA[Learn advanced concurrency, agentic iOS engineering, and Swift performance for 10 minutes a week.]]></description><link>https://blog.jacobstechtavern.com</link><image><url>https://substackcdn.com/image/fetch/$s_!LJp-!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png</url><title>Jacob’s Tech Tavern</title><link>https://blog.jacobstechtavern.com</link></image><generator>Substack</generator><lastBuildDate>Sat, 11 Apr 2026 06:53:02 GMT</lastBuildDate><atom:link href="https://blog.jacobstechtavern.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Jacob Bartlett]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jacobbartlett@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[jacobbartlett@substack.com]]></itunes:email><itunes:name><![CDATA[Jacob Bartlett]]></itunes:name></itunes:owner><itunes:author><![CDATA[Jacob Bartlett]]></itunes:author><googleplay:owner><![CDATA[jacobbartlett@substack.com]]></googleplay:owner><googleplay:email><![CDATA[jacobbartlett@substack.com]]></googleplay:email><googleplay:author><![CDATA[Jacob Bartlett]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Survive the AI tech hiring winter ⛄️]]></title><description><![CDATA[A comprehensive new eBook to get you through the grind &#128218;]]></description><link>https://blog.jacobstechtavern.com/p/survive-the-ai-tech-hiring-winter</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/survive-the-ai-tech-hiring-winter</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Mon, 06 Apr 2026 15:03:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gTM3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Late last year I went independent. My wife gave me 100 days to get to sustainability.</p><p>My numbers were going up and to the right, and I was on top of the world.</p><p>But then, in late December 2025, I got a job.</p><p>I never told you why. Really.</p><p>My first motivation was financial: I crunched some numbers on a spreadsheet, and I&#8217;d struggle to break even before going bankrupt. I know how it goes. </p><p>But that&#8217;s just short-term downside risk.</p><p>Long-term, <em>who the f&amp;ck knows what the job market is going to look like?</em></p><p>Best to hitch my wagon to a muscly horse. Or, in my case, <a href="https://www.granola.ai/blog/series-c">a unicorn</a> &#129412;</p><p>The way I see it, there&#8217;s two ways to safeguard your career future from the risk of AI disruption:</p><ul><li><p><strong>Play defence:</strong> Becoming way more knowledgeable than average.</p></li><li><p><strong>Play offence:</strong> Position yourself in a company that will survive.</p></li></ul><p>I&#8217;m here to help you with both of those things. </p><h4><strong>Introducing&#8230;</strong></h4><p><strong>Land your iOS Tech Job <br></strong>(Jacob&#8217;s survival guide for the modern interview grind)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gTM3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gTM3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 424w, https://substackcdn.com/image/fetch/$s_!gTM3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 848w, https://substackcdn.com/image/fetch/$s_!gTM3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 1272w, https://substackcdn.com/image/fetch/$s_!gTM3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gTM3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png" width="1456" height="732" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:732,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1041916,&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://blog.jacobstechtavern.com/i/191961676?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.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_!gTM3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 424w, https://substackcdn.com/image/fetch/$s_!gTM3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 848w, https://substackcdn.com/image/fetch/$s_!gTM3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.png 1272w, https://substackcdn.com/image/fetch/$s_!gTM3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac7954fc-a8c0-44f9-a96d-3dd3a1f447ba_2886x1450.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>This is a comprehensive 109-page guidebook helping you prep for each stage of the big tech hiring process: from technical screenings, to system design, and the mysterious &#8220;iOS coding&#8221; interview.</p><p>It&#8217;s informed by my 10 years of iOS experience, conversations with senior engineers at Meta and Snap, and my personal experience from my own grind: 30 technical interviews across big tech and hot startups in December 2025.</p><blockquote><p><em><strong>Because it&#8217;ll be a little awkward to expense this to your company, I&#8217;m pricing it at a special reduced price of $19.99 this month only.</strong> </em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://payhip.com/b/tvoug&quot;,&quot;text&quot;:&quot;Buy the book now ($19)&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://payhip.com/b/tvoug"><span>Buy the book now ($19)</span></a></p><p>If you&#8217;re an existing paid subscriber? <strong>You get it for free. </strong>Thanks for the support!</p><p>Contact me if you&#8217;re a student, unemployed, or a layoff victim, and I&#8217;ll sort you out with a discount.</p><p><em>Cheers for reading Jacob&#8217;s Tech Tavern! &#127866;</em></p>]]></content:encoded></item><item><title><![CDATA[Oh sh*t, I have an "iOS coding" interview and don't know what to practice]]></title><description><![CDATA[A handy survival guide: drill, baby, drill!]]></description><link>https://blog.jacobstechtavern.com/p/ios-coding-interview</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/ios-coding-interview</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 31 Mar 2026 15:00:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!hYJG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.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_!hYJG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hYJG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!hYJG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!hYJG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!hYJG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hYJG!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4145335,&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://blog.jacobstechtavern.com/i/181215683?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hYJG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!hYJG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!hYJG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!hYJG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a7e8779-c643-4eb2-ad22-bb67bfcd1cb5_1680x1200.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>Landing a job is never easy. </p><p>There are a lot of themes you&#8217;ll encounter across many interview loops: take-home projects, system design, iOS knowledge, and LeetCode puzzles. These are pretty universal, and straightforward to prepare for. </p><p>In <a href="https://blog.jacobstechtavern.com/p/interview-grind">my interview grind</a> over December, I worked through ~30 individual technical interviews. Along the way, I encountered several rounds simply labelled <em>&#8220;iOS coding round&#8221;</em> or <em>&#8220;app building exercise&#8221;</em> or <em>&#8220;programming in iOS&#8221;</em>. I&#8217;d email the internal recruiter, and get zero details. Flying blind.</p><p><strong>Companies are being deliberately vague</strong>: They want to see you handle an unknown problem using your raw skills.</p><p>But, as a candidate, accepting the unknown is a crappy way to prepare for an interview. <strong>There is a way to train yourself</strong> to handle any curveball an iOS interview might throw at you: Drills.</p><p>Drilling a wide variety of problems helps train your engineering muscle memory and load up your cranial CPU caches, honing your ability to tackle any problem thrown your way. With practice, you can demonstrate your skills in the best light.</p><p>Today, I&#8217;ll detail the 5 broad archetypes of <em>&#8220;iOS coding&#8221;</em> interviews you&#8217;ll encounter. I&#8217;ll be sharing real practice problems <em>(and solutions)</em> that I used to land a tech job last month.</p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181215683/screen-building">Screen building</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181215683/component-design">Component design</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181215683/leetcode-lite">LeetCode-&#8220;lite&#8221;</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181215683/fundamentals">Fundamentals</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181215683/api-design">API design</a> </p></li></ul><p>This post comes packed with a fully-fledged sample project with drills to help you practice each class of interview problem. </p><div><hr></div><blockquote><p><em>Today is the last day of the Spring Sale for my Swift Concurrency eBook bundle. <strong>Get 55% off</strong> my paid-only concurrency masterclasses and <strong>own them forever</strong>.</em> </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://payhip.com/b/oAd3R&quot;,&quot;text&quot;:&quot;Master Concurrency for $29&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://payhip.com/b/oAd3R"><span>Master Concurrency for $29</span></a></p></blockquote><div><hr></div><h2>Categories of &#8220;iOS Coding&#8221; exercise </h2><p>If you&#8217;ve been out of the job market a while, you might be unfamiliar with the format. </p><p>Some companies, the stars, give you a highly detailed PDF explaining what they&#8217;ll interview you about, and what you can expect.</p><p>The vast majority are pretty taciturn when telling you what to expect. </p><p>If you know, you know. The email invite will look something like this:</p><ul><li><p><em>&#8220;An interview focused on programming and debugging in iOS.&#8221;</em></p></li><li><p><em>&#8220;An interview involving an app building exercise&#8221;</em></p></li><li><p><em>&#8220;An interview focusing on your experience with the iOS ecosystem, including core programming, architecture, and problem-solving.&#8221;</em></p></li><li><p><em>&#8220;An interview testing understanding of algorithms, data structures, and clean code&#8221;</em></p></li><li><p><em>&#8220;An interview on software engineering &amp; API-oriented programming.&#8221;</em></p></li></ul><p>Deciphering these is more art than science. </p><p>Some are mercifully transparent: <em>perhaps, for an app-building exercise, I should practice building an app</em>. Others are painfully opaque: <em>I guess it&#8217;s an interview about programming?</em>  </p><p>Across the 30 technical rounds I completed, I can map the generic <em>&#8220;iOS-programming&#8221;</em> style rounds to a few core categories, which dramatically focuses the scope of what you can do to prepare:</p><h4>Screen building </h4><p>This is the most straightforward challenge: you will be asked to build a screen from scratch with UIKit or SwiftUI. Practicing these is almost trivial: time yourself building various designs within 30 minutes or so.</p><h4>Component design </h4><p>You&#8217;ll be asked to build some kind of reusable UI component, demonstrating you can code, think about requirements, and recognise edge cases. Drilling is straightforward: practice building these components from scratch. </p><h4>LeetCode-&#8220;lite&#8221; </h4><p>Many companies say they&#8217;ll test you on algorithms and data structures, but <em>insist </em>that &#8220;<em>it&#8217;s not LeetCode&#8221;</em>. What they mean is that it&#8217;s not a <em>specific</em> LeetCode problem. But the only way to practice for these kinds of exercises is, you guessed it, practicing LeetCode. </p><h4>Fundamentals </h4><p>This is a broad category of problem where you&#8217;re asked to demonstrate something like <em>concurrency</em> skills, <em>debugging</em> skills, or <em>testing</em> skills. This is where AI tooling really shines in creating practice questions, with a little guiding hand.</p><h4>API design </h4><p>API design is a pretty uncommon format. It&#8217;s closer to a system design exercise, except you&#8217;re expected to show some code. You&#8217;ll be asked to design protocols to effectively implement a feature or system.</p><div><hr></div><p>Modern tooling makes it easier than ever to drill problems.</p><p>Agentic CLI tools like Claude Code and Codex will trivially generate sample projects for you and enable you to work through dozens of problems to practice your fundamentals, or develop your skills with a framework such as GCD. </p><p>Alternatively, it is helpful to poke holes in your own code, highlighting flaws, sloppy code, or missed edge cases. </p><p>Drilling random challenges train you to tackle unknown problems and allows you to shine in the interview.</p><p>Now I&#8217;ll give a worked example of each category of problem, sharing the sample code so you can drill for yourself. When you&#8217;re ready, you&#8217;ll have the power to generate and grade your own drills. </p><blockquote><p><em>Upgrade to unlock this article, plus much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/ios-coding-interview">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The SwiftUI Design System War: Composition vs Progressive Disclosure]]></title><description><![CDATA[My most controversial high-conviction opinion]]></description><link>https://blog.jacobstechtavern.com/p/the-design-system-war</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/the-design-system-war</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 17 Mar 2026 16:02:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!wQ0E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.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_!wQ0E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wQ0E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!wQ0E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!wQ0E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!wQ0E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wQ0E!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4401592,&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://blog.jacobstechtavern.com/i/180131484?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wQ0E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!wQ0E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!wQ0E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!wQ0E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c2500f9-590d-4b30-8899-0c864351e056_1680x1200.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>I&#8217;m no stranger to taking some heat when publishing my work. I got crucified for <a href="https://blog.jacobstechtavern.com/p/apple-is-killing-swift">Apple is Killing Swift</a>, and annoyed a <em>lot</em> of people with <a href="https://blog.jacobstechtavern.com/p/the-year-swiftui-died">2025: The Year SwiftUI Died</a>.</p><p>My 3rd-most-controversial post might surprise you: <a href="https://blog.jacobstechtavern.com/p/enums-and-design-systems">Swift Enums &#129309; Design Systems</a>. It was a friendly little number where I talked about my favourite approach for building design systems in SwiftUI, with a progressive-disclosure-inspired approach to my view component initialisers.</p><p>This reads like pretty reasonable stuff, until the terminally-online permafrost of SwiftUI zealots read it and admonished me: <em>&#8220;This is not idiomatic! You should be using view composition!&#8221;</em></p><p>They&#8217;re not wrong. My approach is not idiomatic. It&#8217;s <em>pragmatic</em>.</p><p>But you should really decide for yourself. </p><p>So I&#8217;m going to take my opinions and put them in my pocket, and coldly present the two approaches you can apply while building a design system in a large-scale SwiftUI project. You should use the approach that works for you. </p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/design-systems">Design Systems</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/the-sample-project">The Sample Project</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/how-to-composition">How to Composition</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/custom-buttonstyle">Custom ButtonStyle</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/shared-components">Shared Components</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/composition-in-action">Composition in action</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/progressive-disclosure">Progressive Disclosure</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/the-initialiser">The Initialiser</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/progressive-disclosure-in-action">Progressive Disclosure in action</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/the-really-important-things-with-design-systems">The Really Important Things With Design Systems</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/keeping-the-design-system-simple">Keeping the design system simple</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/extensibility">Extensibility</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/documentation">Documentation</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/preview">#Preview</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/is-it-marginal">Is it marginal?</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131484/last-orders">Last Orders</a>   </p></li></ul><div><hr></div><blockquote><p><strong>This week, I&#8217;m offering my 2-eBook concurrency bundle for 55% off</strong></p><p><strong>&#128216; The Complete Swift Concurrency Toolkit</strong> explains every facet of Swift Concurrency from async/await to the latest Swift 6.2 actor isolation changes. </p><p><strong>&#128213; Advanced Swift Concurrency Training</strong> takes you through 12 increasingly complex real-world problems, allowing you to lock-in practical knowledge.</p><p>By the end, you&#8217;ll have a finely-honed concurrency killer-instinct.</p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://payhip.com/b/oAd3R&quot;,&quot;text&quot;:&quot;Get the Swift Concurrency Bundle for $29&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://payhip.com/b/oAd3R"><span>Get the Swift Concurrency Bundle for $29</span></a></p><div><hr></div><blockquote><p><em><strong>Claim your free month</strong> to unlock this article, and much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?coupon=34c0e967&amp;utm_content=180131484&quot;,&quot;text&quot;:&quot;Get 30 day free trial&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?coupon=34c0e967&amp;utm_content=180131484"><span>Get 30 day free trial</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/the-design-system-war">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Is SwiftUI finally as fast as UIKit in iOS 26?]]></title><description><![CDATA[A scientific performance comparison. The final word.]]></description><link>https://blog.jacobstechtavern.com/p/swiftui-vs-uikit</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/swiftui-vs-uikit</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Mon, 09 Mar 2026 16:01:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1Jn9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif" 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_!1Jn9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1Jn9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 424w, https://substackcdn.com/image/fetch/$s_!1Jn9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 848w, https://substackcdn.com/image/fetch/$s_!1Jn9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 1272w, https://substackcdn.com/image/fetch/$s_!1Jn9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1Jn9!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4715352,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/184657452?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1Jn9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 424w, https://substackcdn.com/image/fetch/$s_!1Jn9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 848w, https://substackcdn.com/image/fetch/$s_!1Jn9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 1272w, https://substackcdn.com/image/fetch/$s_!1Jn9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fec517517-fbc1-4640-a984-33b4b9a0ade4_1680x1200.gif 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><figcaption class="image-caption">If anybody was on the fence about having kids, my four-year-old daughter saw this and started dancing along with the baby GIF.</figcaption></figure></div><p>I love SwiftUI; I hate SwiftUI. </p><p>I love UIKit; I hate UIKit. </p><p>When you&#8217;re as suggestible as me, it&#8217;s easy to be swayed based on the last blog post you read.</p><p>SwiftUI has forever been on a long journey to parity with UIKit, and the question of &#8220;is SwiftUI production-ready&#8221; has had a clear answer for years: <em>Yes, but</em>.</p><p><em>Yes, but</em> you will need to drop down to UIKit for stuff like the <a href="https://x.com/jacobtechtavern/status/1916947571974525169">Camera</a>.</p><p><em>Yes, but</em> some functionality like UIScrollViewDelegate scroll velocity is missing. </p><p><em>Yes, but</em> performance on an infinitely-scrolling feed will never be as good.</p><p>Performance. </p><p>Specifically, scroll performance.</p><p>At one time or another, we&#8217;ve all sat under the thumb of an imperious product manager or QA tester, demanding the single frame drop on their nan&#8217;s iPhone 4s be eliminated before you can go home.</p><p>But they do have a point:</p><p><strong>Performance is the final bastion of native iOS supremacy.</strong></p><p>You don&#8217;t want to hear it, but if we get comfortable shipping apps with noticeably mediocre performance on scroll-heavy screens, we might as well ship with React Native.</p><p>iOS 26 crosses the rubicon: in <a href="https://developer.apple.com/videos/play/wwdc2025/256/">WWDC 2025&#8217;s What&#8217;s New In SwiftUI</a>, Apple spent half the runtime explaining the improvements they made to List updates and scroll performance more widely.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZtDP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZtDP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 424w, https://substackcdn.com/image/fetch/$s_!ZtDP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 848w, https://substackcdn.com/image/fetch/$s_!ZtDP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 1272w, https://substackcdn.com/image/fetch/$s_!ZtDP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZtDP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png" width="1456" height="417" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:417,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:359951,&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://blog.jacobstechtavern.com/i/184657452?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.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_!ZtDP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 424w, https://substackcdn.com/image/fetch/$s_!ZtDP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 848w, https://substackcdn.com/image/fetch/$s_!ZtDP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.png 1272w, https://substackcdn.com/image/fetch/$s_!ZtDP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fa9818-cbe9-46e2-9100-d46804d59527_2458x704.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><blockquote><h5><strong>Sponsored Link</strong></h5><h4><strong><a href="https://www.revenuecat.com/state-of-subscription-apps/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=sosa-2026">How iOS apps actually make money</a></strong></h4><p>RevenueCat&#8217;s <a href="https://www.revenuecat.com/state-of-subscription-apps/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=sosa-2026">State of Subscription Apps</a> report is out, analyzing 115,000+ subscription apps and more than $16B in revenue. Use it to benchmark your pricing, trials, and conversion rates against what&#8217;s actually working across the app economy.</p></blockquote><p>These improvements aren&#8217;t theoretical: <a href="https://x.com/Dimillian">Thomas Ricouard&#8217;s</a> <a href="https://apps.apple.com/gb/app/ice-cubes-for-mastodon/id6444915884 Ice Cubes for Mastodon">Ice Cubes</a> app saw a substantial not-to-sniff-at drop in the scroll hitch rate since building against the iOS 26 SDK in version 2.0.0.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WBYn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WBYn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WBYn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WBYn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WBYn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WBYn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg" width="1456" height="887" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:887,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:247926,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/184657452?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg&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_!WBYn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WBYn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WBYn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WBYn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa164c63c-418b-4bb4-b101-17683e4da41f_3248x1978.jpeg 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"><em>Or, perhaps, all the most tight-fisted Mastodon users stubbornly holding onto their iPhone 4s suddenly upgraded en masse</em></figcaption></figure></div><p>Let&#8217;s put Apple&#8217;s claims to the test in the ultimate head-to-head battle of the scrolls.</p><p><strong>SwiftUI vs UIKit</strong>. </p><p>We&#8217;ll find out, once and for all, whether SwiftUI has hit parity on performance.</p><div><hr></div><ul><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/designing-the-most-ridiculous-feed-i-can-imagine">Designing the most ridiculous scroll view I can imagine</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/a-fair-test">A fair test</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/swiftui-performance-feat-list">SwiftUI performance (feat. List)</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/animation-performance-with-instruments">Animation performance with Instruments</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/memory-cpu-and-thermal-profile-with-xcode">Memory, CPU, and thermal profile with Xcode</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/the-swiftui-performance-instrument">The SwiftUI Performance instrument</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/uikit-performance-feat-uicollectionview">UIKit performance (feat. UICollectionView)</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/animation-performance-with-instruments">Animation performance with Instruments</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/memory-cpu-and-thermal-profile-with-xcode">Memory, CPU, and thermal profile with Xcode</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/the-elephant-in-the-room">The Elephant in the Room</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/what-the-future-looks-like-for-swiftui">What the future looks like for SwiftUI</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184657452/last-orders">Last Orders</a></p></li></ul><div><hr></div><h2>Designing the most ridiculous scroll view I can imagine </h2><p>If we want to meaningfully understand the performance characteristics of SwiftUI and UIKit scroll performance, we need to really put them to the test.</p><p>If you&#8217;re just rendering a simple storefront with a carousel of images, maybe with some text on each cell, then this isn&#8217;t the article for you. Both frameworks are probably fine.</p><p>But today I&#8217;m making the most complex scrolling feed I can imagine in SwiftUI.</p><p>What requirements are needed to make a UI truly ridiculous?</p><ul><li><p>High resolution images.</p></li><li><p>A complex view hierarchy of elements, text, and gradients.</p></li><li><p>Permanent autoplaying animations.</p></li><li><p>Variable-sized cells to force layout re-computation on cell reuse.</p></li><li><p>Multi-gesture UI interaction that update a data store in real-time.</p></li></ul><p>But how can we achieve this? </p><p><em>I have an idea. </em>With a little help from my friend, 2001&#8217;s 22,000 Animated Gifs CD-ROM.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QEf9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QEf9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 424w, https://substackcdn.com/image/fetch/$s_!QEf9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 848w, https://substackcdn.com/image/fetch/$s_!QEf9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 1272w, https://substackcdn.com/image/fetch/$s_!QEf9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QEf9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png" width="1456" height="1278" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1278,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3790065,&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://blog.jacobstechtavern.com/i/184657452?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.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_!QEf9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 424w, https://substackcdn.com/image/fetch/$s_!QEf9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 848w, https://substackcdn.com/image/fetch/$s_!QEf9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.png 1272w, https://substackcdn.com/image/fetch/$s_!QEf9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac34f089-3159-4a9f-91a8-af337a7e35bf_1672x1468.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"><a href="https://archive.org/details/22000Animatedgifs">Hell. Freakin&#8217;. Yeah.</a></figcaption></figure></div><blockquote><p><em>Uh, so this disc image is from 2001. I need to mount the .iso somehow&#8230; macOS won&#8217;t play along. You know what, this is below my pay grade. I&#8217;m gonna get Claude to dump it out and export me a folder of .gifs.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ApY4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ApY4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 424w, https://substackcdn.com/image/fetch/$s_!ApY4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 848w, https://substackcdn.com/image/fetch/$s_!ApY4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 1272w, https://substackcdn.com/image/fetch/$s_!ApY4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ApY4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp" width="533" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:533,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1042946,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/184657452?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ApY4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 424w, https://substackcdn.com/image/fetch/$s_!ApY4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 848w, https://substackcdn.com/image/fetch/$s_!ApY4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 1272w, https://substackcdn.com/image/fetch/$s_!ApY4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9df3303-d4bd-4b00-8874-1c73b3d4fc82_533x400.webp 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><em>Throwback to the early 90s when <a href="https://techcrunch.com/2014/06/15/a-brief-history-of-the-dancing-baby-meme/">dancing baby</a> was literally the funniest meme ever</em>.</p></blockquote><p>Now we have our secret sauce, I can build out twin chaotic UIs in both SwiftUI and UIKit. </p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;9d929566-24ab-4dd4-99a9-50dbc766500a&quot;,&quot;duration&quot;:null}"></div><p>These <strong>gifs</strong> are bananas. And yes, I <em>do</em> pronounce it just like you.</p><p>The complexity of this UI forces the screen to aim for the high-performance 120fps refresh rate, giving just 8.33ms to render each frame. There is no hiding from this in my performance profiles.</p><p>So. </p><p>Once and for all.</p><p>Is SwiftUI finally as performant as UIKit?</p><div><hr></div><blockquote><p><em>Upgrade to read this article right now, or wait until next month.</em></p><p><em>Paid members get several benefits:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/swiftui-vs-uikit">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[iOS System Design interviews in 2026]]></title><description><![CDATA[Practical prep advice based on three real-world interviews]]></description><link>https://blog.jacobstechtavern.com/p/system-design-interview</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/system-design-interview</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 03 Mar 2026 16:01:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!W376!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.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_!W376!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W376!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!W376!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!W376!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!W376!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W376!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:2870282,&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://blog.jacobstechtavern.com/i/184333119?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!W376!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!W376!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!W376!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!W376!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcf8c6d62-2c5e-46bf-be22-6e1a1a56b5b3_1680x1200.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>The best-paying tech companies administer a <strong>system design round</strong> as part of their final-stage interview rounds. This interview, the successor to the classic <em>whiteboarding exercise</em>, challenges you to architect a complex system on iOS:</p><ul><li><p><em>Show me how you&#8217;d architect an encrypted messaging app.</em></p></li><li><p><em>Demonstrate how you&#8217;d structure a news feed on a social app.</em></p></li><li><p><em>Design an SDK fit for a large analytics company.</em></p></li></ul><p>There are virtually no resources online <em>(aside from expensive coaching)</em> that teach you to tackle these interviews for iOS roles.</p><p>Until now.</p><p>I went through an <a href="https://blog.jacobstechtavern.com/p/interview-grind">extremely intensive interview grind</a> at the end of 2025, and faced down <strong>three system design challenges at three different companies</strong>. I&#8217;m coming to you today with personal, hard-won experience.</p><p>The real meat and potatoes here is a full worked example: a real system design interview, demonstrating what you can expect from a system design round today and how to tackle the problem. For dessert, I&#8217;ll highlight all the parts of prep work that were <em>actually useful</em>, so your own grind can be efficient and <em>(mostly)</em> painless.</p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/184333119/a-framework-to-structure-every-interview">A framework to structure every interview</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184333119/worked-example-ai-chat-app">A full worked example based on my recent interviews</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184333119/important-practical-prep-notes">Miscellaneous practical tips to help you prepare</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184333119/concepts-i-didnt-know-much-about">Common client-side design concepts I didn&#8217;t know about</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/184333119/last-orders">Last Orders (and a handy cheat sheet)</a></p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gRJn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gRJn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 424w, https://substackcdn.com/image/fetch/$s_!gRJn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 848w, https://substackcdn.com/image/fetch/$s_!gRJn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 1272w, https://substackcdn.com/image/fetch/$s_!gRJn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gRJn!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png" width="1200" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7107948a-33f8-41fc-b980-7c0b4dfcce67.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:3117296,&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://blog.jacobstechtavern.com/i/184333119?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gRJn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 424w, https://substackcdn.com/image/fetch/$s_!gRJn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 848w, https://substackcdn.com/image/fetch/$s_!gRJn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.png 1272w, https://substackcdn.com/image/fetch/$s_!gRJn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7107948a-33f8-41fc-b980-7c0b4dfcce67.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><figcaption class="image-caption">The enterprising free subscriber can avoid the paywall by skimming the sticky notes on my monitor.</figcaption></figure></div><h2>A framework to structure every interview </h2><p>A lot of interviewers these days will try to pretend that your interview is a casual chat. Don&#8217;t be fooled. Obviously, act natural, smile, but it will never hurt you to introduce some formality via a framework.</p><p>A framework is a simple structure you can follow to answer the problem. A reusable way of arranging your thoughts while you design the system. The framework goes like this:</p><ul><li><p>Scoping</p></li><li><p>Functional requirements</p></li><li><p>Non-functional requirements</p></li><li><p>Data model</p></li><li><p>API design</p></li><li><p>High-level design</p></li><li><p>Drill-down questions </p></li></ul><p>With system design, <strong>&#8220;measure twice, cut once&#8221;.</strong> You must understand the problem space and what needs to be designed before you draw anything. </p><p>As iOS developers, it&#8217;s tempting to dive straight into SwiftUI vs UIKit, MVVM vs MV vs VIPER, and your favourite concurrency toolkit. That&#8217;s a dangerous game: the system design interview is far more about data flow and structure than UI or frameworks.</p><p>Now let&#8217;s look at a full worked example of an interview, demonstrating how to tackle the interview systematically. This might be the best prep out there, because it&#8217;s based on three of the real final-stage panel interviews I did last month. </p><p>My worked example takes you through <strong>the most popular system design question out there today</strong>.</p><p>By the end, you&#8217;ll have the confidence to tackle your own iOS system design round. </p><blockquote><p><em>Upgrade to unlock this article, plus much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/system-design-interview">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The Most Complicated System I Ever Worked On ]]></title><description><![CDATA[A ludicrously elaborate pipeline of webscraping, parsing, persistence, processing, and polling]]></description><link>https://blog.jacobstechtavern.com/p/the-most-complex-system</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/the-most-complex-system</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 17 Feb 2026 16:01:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!96Sb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.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_!96Sb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!96Sb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!96Sb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!96Sb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!96Sb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!96Sb!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4561209,&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://blog.jacobstechtavern.com/i/180491995?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!96Sb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!96Sb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!96Sb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!96Sb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3930417-9b6f-4942-89a0-16818ac8d68c_1680x1200.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>Writing online is a lot like creating content on OnlyFans.</p><p>And I&#8217;m not just saying that because I&#8217;m very sexy.</p><p>I&#8217;m saying that because it has a strict power-law distribution. </p><p>There are several big names at the very top of the leaderboard that pull in millions of dollars a year. On the other side, there&#8217;s an incredibly long tail of people who make almost no money, perhaps with a tiny number of paid readers and/or simps.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HeQW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HeQW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 424w, https://substackcdn.com/image/fetch/$s_!HeQW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 848w, https://substackcdn.com/image/fetch/$s_!HeQW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 1272w, https://substackcdn.com/image/fetch/$s_!HeQW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HeQW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Image&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Image" title="Image" srcset="https://substackcdn.com/image/fetch/$s_!HeQW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 424w, https://substackcdn.com/image/fetch/$s_!HeQW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 848w, https://substackcdn.com/image/fetch/$s_!HeQW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.png 1272w, https://substackcdn.com/image/fetch/$s_!HeQW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F584a691c-6613-4199-bcd7-9866a66358f5_1600x900.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><figcaption class="image-caption">Wow, TIL Substack was even more top-heavy than OnlyFans (<a href="https://x.com/adamry_n/status/1571503586236051456">source</a>)</figcaption></figure></div><p>Between the extremes, a quiet middle class at <a href="https://substack.com/leaderboard/technology/paid">#88 on the technology leaderboard</a> who are probably pulling in something like minimum wage (p.s. that&#8217;s exactly where I&#8217;m at, hence my recent job-hunt). </p><p>This power-law distribution shows up everywhere. In software engineering, it manifests in the complexity of problems that we work on day-to-day. There is a very long tail of everyday &#8220;build this screen&#8221; or &#8220;investigate this bug&#8221; that you can largely perform on autopilot. </p><p>There are regular mid-level challenges in the middle, that crop up every month or two: profile this subtle performance problem, or help architect this new feature. </p><p>Once in a blue moon; maybe just once in your career; you have to pull off something nobody&#8217;s built before. Something with so many moving parts it needs constant work to prevent it overwhelming your team.</p><p>This rare peak challenge is what I&#8217;m bringing to you today. The hardest engineering challenge I have ever faced. A one-of-a-kind feature that orchestrated an automated, client-side, comprehensive, high-volume data ingestion pipeline.</p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180491995/webscraping-a-third-party-service">Webscraping a third party service</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180491995/long-running-downloading-jobs">Long-running downloading jobs</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180491995/parsing-and-storage-for-mb-of-data">Parsing and storage for ~200MB of data</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180491995/real-time-data-analysis">Real-time data analysis</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180491995/high-volume-data-upload-and-polling">High-volume data upload and polling</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180491995/a-year-of-whack-a-mole">And, finally, the year of whack-a-mole to keep it working</a> </p></li></ul><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;a88cb798-2048-42fb-8ba4-56c6afb826f5&quot;,&quot;duration&quot;:null}"></div><p><a href="https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/">Building a reliable system on top of an unreliable system</a> is always quite traumatic, so please excuse my occasional abrupt screams as I write this. </p><p>The original pipeline allowed you to fetch your Google data, which could reach Gigabyte scale for each user, the root of much of the complexity. For this example, however, I&#8217;m doing the same thing with <strong>my Spotify data</strong>, because open-sourcing my music search history in the sample project will be less likely to get me arrested.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8-ZR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8-ZR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 424w, https://substackcdn.com/image/fetch/$s_!8-ZR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 848w, https://substackcdn.com/image/fetch/$s_!8-ZR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 1272w, https://substackcdn.com/image/fetch/$s_!8-ZR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8-ZR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png" width="1456" height="1020" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1020,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:424409,&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://blog.jacobstechtavern.com/i/180491995?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.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_!8-ZR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 424w, https://substackcdn.com/image/fetch/$s_!8-ZR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 848w, https://substackcdn.com/image/fetch/$s_!8-ZR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.png 1272w, https://substackcdn.com/image/fetch/$s_!8-ZR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6dd20c-b243-4f1c-95bc-dbf3602df9de_1856x1300.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"><a href="https://www.youtube.com/watch?v=cNgyuHtBBW8&amp;list=RDcNgyuHtBBW8">It&#8217;s a certified banger, I swear</a></figcaption></figure></div><p>I didn&#8217;t build this bad boy from scratch. This system was inherited MVP form, by an engineer who is a lot more intelligent than me. I did, however, have the pleasure of spending a year hardening the pipeline from a neat (but fragile) pipeline into a battle-hardened production system that worked robustly.</p><p>This article comes complete with the full sample project, demoing the whole pipeline in its glory (with companion server code!)</p><p>Come and see the man-made horrors beyond your comprehension.</p><div><hr></div><blockquote><p><em>Paid members get the full article, and a lot more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/the-most-complex-system">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Agentic AI Engineering Workflows for iOS in 2026]]></title><description><![CDATA[Cargo culting the creator of Claude Code]]></description><link>https://blog.jacobstechtavern.com/p/agentic-ai-2026</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/agentic-ai-2026</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Mon, 09 Feb 2026 16:02:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!URlT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.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_!URlT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!URlT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!URlT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!URlT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!URlT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!URlT!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce76c33c-c026-43e7-a243-c87284820768_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:3510738,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!URlT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!URlT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!URlT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!URlT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce76c33c-c026-43e7-a243-c87284820768_1680x1200.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>The last 6 months have been the most tumultuous period ever in the field of software engineering. More than compilers. More than the internet. Maybe even more than the transistor.</p><p>In late 2025, a Rubicon was crossed. In March last year, we all laughed at the Anthropic CEO for his prediction that &#8220;within 6 months, <a href="https://news.ycombinator.com/item?id=44921825">90% of code will be written by AI</a>&#8221;. Today, among software engineers, there are 2 camps emerging: </p><ul><li><p>Default to AI, with a vast majority of code <em>not</em> hand-typed.</p></li><li><p>Still hand-coding by default, pasting into chat windows for help.</p></li></ul><p>I&#8217;ve heard this story more than once: a very senior, serious engineer at a company will trial AI for the first time, with a big refactor. After a few days, they&#8217;ll debrief the team, explaining that it isn&#8217;t quite what it&#8217;s cracked up to be, and a distraction. The punchline is they were using f*cking Copilot.</p><p>I had a recent, quite eye-opening, Twitter exchange: someone claimed <em>&#8220;AI is bad at programming&#8221;</em>, then proved it by showing me a half-baked prompt in a web chat, asking about a Steam API, and getting a hallucinated response.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0xRj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0xRj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 424w, https://substackcdn.com/image/fetch/$s_!0xRj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 848w, https://substackcdn.com/image/fetch/$s_!0xRj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 1272w, https://substackcdn.com/image/fetch/$s_!0xRj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0xRj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png" width="1456" height="849" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:849,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:178242,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.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_!0xRj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 424w, https://substackcdn.com/image/fetch/$s_!0xRj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 848w, https://substackcdn.com/image/fetch/$s_!0xRj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.png 1272w, https://substackcdn.com/image/fetch/$s_!0xRj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f214b95-8f47-4be0-bfae-c6a02e191a4a_1546x902.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>This was insane to me! How did this person not know to open Codex in a terminal, set high thinking mode, paste the link to the relevant documentation, and ask it to make the change in your codebase!? </p><div><hr></div><p>To use AI tooling effectively, you need experience. Specifically, finding a workflow that is effective for you. I became proficient with Claude Code over summer, and rapidly my entire daily workflow changed around it. </p><p>But things have moved really fast.</p><p>My default approach: <em>&#8220;big detailed prompt, oneshot, then optimise&#8221;</em> is great for <a href="https://blog.jacobstechtavern.com/p/the-design-system-war">sample projects</a> and <a href="https://blog.jacobstechtavern.com/p/interview-grind">takehome tests</a>, but is weaker for larger, more complex projects. </p><p>I need to optimise my workflow some more. </p><p>So. </p><p>Today I&#8217;m going to revisit the state of the art, address any FOMO you might have from boycotting Tech Twitter&#8482;, and discover the novel techniques I&#8217;m missing. <strong>Specifically, what&#8217;s useful for iOS development.</strong> </p><p>Next, I&#8217;m going to set up the workflow <a href="https://x.com/bcherny/status/2007179832300581177">used by Boris Cherny</a>, the guy who invented Claude Code, a <em>&#8220;vanilla&#8221;</em> approach involving orchestration between 15 parallel agents.</p><p>Finally, I&#8217;ll test drive this approach by building an app I first envisioned in 2020: <strong>Maxwell</strong>.</p><div><hr></div><h5><strong>Sponsored Link</strong></h5><h4><strong><a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">RevenueCat Paywalls: Build &amp; iterate subscription flows faster</a></strong></h4><blockquote><p>RevenueCat Paywalls just added a steady stream of new features: more templates, deeper customization, better previews, and new promo tools. <a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">Check the Paywalls changelog</a> and keep improving your subscription flows as new capabilities ship.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ywUg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ywUg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!ywUg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!ywUg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!ywUg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ywUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png" width="1024" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2580801,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.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_!ywUg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!ywUg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!ywUg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!ywUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1838418-3f4a-49e9-a95a-284d9a9cc30c_1024x1024.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><h2>Contents</h2><ul><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/the-state-of-the-art">The State of the Art</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/the-best-models">The Best Models</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/mcp-verification-and-xcode-263">MCP, Verification, and Xcode 26.3</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/multi-agent-and-orchestration">Multi-agent and Orchestration</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/agentsmd-and-skills">AGENTS.md and Skills</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/teleporting-sessions-to-the-web">Teleporting Sessions to the Web</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/tab-completion">Tab Completion</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/the-ralph-loop">The Ralph Loop</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/openclaw-aka-clawdbot">OpenClaw (aka Clawdbot)</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/cargo-culting-the-creator-of-claude-code">Cargo-Culting the Creator of Claude Code</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/building-maxwell-in-a-day">Building Maxwell in an afternoon</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/185165895/last-orders">Last Orders</a></p></li></ul><div><hr></div><h2>The State of the Art</h2><p>I already wrote about my early agentic workflow in September 2025. It&#8217;s a good piece. If you are unfamiliar with using agentic AI to code, it is a great introduction.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;2bdf2e81-9c70-4b0b-aa7d-7c0a158fb302&quot;,&quot;caption&quot;:&quot;50-100% productivity gains echoes the fantasy sold to you by grifters selling $997 AI courses on Twitter. If that&#8217;s the case, I&#8217;m missing a trick charging $12/month. Because it&#8217;s legit.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Claude Code has made me 50-100% more productive&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-09-02T15:02:30.684Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!mGPq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e800aa-9c34-4664-8949-b7c5af8bff70_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/claude-code-productivity&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170755884,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:16,&quot;comment_count&quot;:2,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>But there are a <em>ton</em> of new developments, innovations, and tools in the GPT-5.2 and Opus 4.5 era which massively impact your day-to-day, especially in iOS. </p><p>Let&#8217;s cover some:</p><div><hr></div><h4>The Best Models</h4><p><s>Codex (5.2) and Claude Code (Opus 4.5) are the best models </s><strong><s>by far</s></strong><s>. </s></p><p><s>At the time of writing, </s><strong><s>gpt-5.2-codex</s></strong><s> is unambiguously the best, thinks carefully, and makes fewer mistakes than other models.</s></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qHCc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qHCc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 424w, https://substackcdn.com/image/fetch/$s_!qHCc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 848w, https://substackcdn.com/image/fetch/$s_!qHCc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 1272w, https://substackcdn.com/image/fetch/$s_!qHCc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qHCc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png" width="1456" height="238" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:238,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:206955,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.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_!qHCc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 424w, https://substackcdn.com/image/fetch/$s_!qHCc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 848w, https://substackcdn.com/image/fetch/$s_!qHCc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 1272w, https://substackcdn.com/image/fetch/$s_!qHCc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faea1a93e-b7e3-49fe-8670-1656107a0c63_1984x324.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>Update the Friday before this published</strong>: <br><strong>Opus 4.6</strong> and <strong>Codex 5.3</strong> just came out! The jury&#8217;s out on which is better. This will be me over the weekend: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jFZx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jFZx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 424w, https://substackcdn.com/image/fetch/$s_!jFZx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 848w, https://substackcdn.com/image/fetch/$s_!jFZx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 1272w, https://substackcdn.com/image/fetch/$s_!jFZx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jFZx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png" width="908" height="1148" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1148,&quot;width&quot;:908,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1546399,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.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_!jFZx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 424w, https://substackcdn.com/image/fetch/$s_!jFZx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 848w, https://substackcdn.com/image/fetch/$s_!jFZx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.png 1272w, https://substackcdn.com/image/fetch/$s_!jFZx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffb7546b2-c2de-4029-86a9-c06de89e98ee_908x1148.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 can also configure the <em>reasoning level</em> which gives the model extra time to reason through a problem and think about each step carefully. I get really good results by defaulting to <em>High</em>. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G_YR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G_YR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 424w, https://substackcdn.com/image/fetch/$s_!G_YR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 848w, https://substackcdn.com/image/fetch/$s_!G_YR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 1272w, https://substackcdn.com/image/fetch/$s_!G_YR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G_YR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png" width="1456" height="215" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af13775f-1636-4c1a-8899-140f5b375da0_1982x292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:215,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:168697,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.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_!G_YR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 424w, https://substackcdn.com/image/fetch/$s_!G_YR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 848w, https://substackcdn.com/image/fetch/$s_!G_YR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 1272w, https://substackcdn.com/image/fetch/$s_!G_YR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf13775f-1636-4c1a-8899-140f5b375da0_1982x292.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>If you start to run out of weekly credits, you might consider dropping down to Medium. This will lead to a lot of really dumb mistakes&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pRE0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pRE0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 424w, https://substackcdn.com/image/fetch/$s_!pRE0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 848w, https://substackcdn.com/image/fetch/$s_!pRE0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 1272w, https://substackcdn.com/image/fetch/$s_!pRE0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pRE0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png" width="1456" height="931" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:931,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:269897,&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://blog.jacobstechtavern.com/i/185286257?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.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_!pRE0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 424w, https://substackcdn.com/image/fetch/$s_!pRE0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 848w, https://substackcdn.com/image/fetch/$s_!pRE0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.png 1272w, https://substackcdn.com/image/fetch/$s_!pRE0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62b18d1b-5736-4022-b0bb-500b624ecbaf_1786x1142.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>My beautiful team of crack nerds locked in a basement turns into a dim primary school class that can&#8217;t be left alone for 30 seconds.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QPa8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QPa8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 424w, https://substackcdn.com/image/fetch/$s_!QPa8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 848w, https://substackcdn.com/image/fetch/$s_!QPa8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 1272w, https://substackcdn.com/image/fetch/$s_!QPa8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QPa8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png" width="1456" height="468" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:468,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2754413,&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://blog.jacobstechtavern.com/i/185286257?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.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_!QPa8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 424w, https://substackcdn.com/image/fetch/$s_!QPa8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 848w, https://substackcdn.com/image/fetch/$s_!QPa8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.png 1272w, https://substackcdn.com/image/fetch/$s_!QPa8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff33a6dc6-9eb1-4068-b552-4e094e457a7e_2444x786.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>I guess I need to upgrade my plan.</p><div><hr></div><h4>MCP, Verification, and Xcode 26.3</h4><p>One of the most critical missing links in an AI workflow, especially on iOS, is a way for the agent to autonomously verify its work.</p><p>You can verify via compiles, running unit tests, or manually on the simulator. </p><p>Unfortunately, AI tools don&#8217;t get access to any of these <strong>xcodebuild</strong> functionalities by default, since Xcode and its underlying tools are sandboxed away from agent permissions. </p><p>That&#8217;s where XcodeBuildMCP (by <a href="https://x.com/camsoft2000">camsoft2000</a>) comes in: it enables agents to interact with Xcode tools, including compiling your code, testing, and even interacting with features in the simulator <em>(though recently <a href="https://x.com/camsoft2000/status/2010084485732413835">agents have learned</a> to at least compile)</em>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4LfU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4LfU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 424w, https://substackcdn.com/image/fetch/$s_!4LfU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 848w, https://substackcdn.com/image/fetch/$s_!4LfU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 1272w, https://substackcdn.com/image/fetch/$s_!4LfU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4LfU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png" width="1456" height="578" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:578,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2949079,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.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_!4LfU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 424w, https://substackcdn.com/image/fetch/$s_!4LfU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 848w, https://substackcdn.com/image/fetch/$s_!4LfU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.png 1272w, https://substackcdn.com/image/fetch/$s_!4LfU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fada2bc70-98e2-4814-b30a-4ce8c2b114e3_2590x1028.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"><a href="https://www.xcodebuildmcp.com">XcodeBuildMCP</a></figcaption></figure></div><p>Setting up this verification workflow is the #1 most important productivity unlock in agentic engineering. </p><p>If you don&#8217;t need to run the full simulator, <a href="https://x.com/twannl/status/2019398446671921224">SwiftLee</a> shared a neat trick: using the <a href="https://github.com/ldomaradzki/xcsift">xcsift</a> library runs xcodebuild commands for build and test, but drastically cuts down the token usage from the hefty build reports, to save your context window.</p><p>And, naturally, I have to mention the biggest, hot-off-the-press-the-paper-is-still-warm announcement: Xcode 26.3 and agentic coding.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!x_A5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x_A5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 424w, https://substackcdn.com/image/fetch/$s_!x_A5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 848w, https://substackcdn.com/image/fetch/$s_!x_A5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!x_A5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x_A5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png" width="1456" height="991" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:991,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:973655,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.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_!x_A5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 424w, https://substackcdn.com/image/fetch/$s_!x_A5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 848w, https://substackcdn.com/image/fetch/$s_!x_A5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!x_A5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd691a7e2-c547-4d20-88c2-bef5c838b19e_1758x1196.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">From <a href="https://www.apple.com/uk/newsroom/2026/02/xcode-26-point-3-unlocks-the-power-of-agentic-coding/">Apple Newsroom</a></figcaption></figure></div><p>Xcode 26.3 introduces its own first-party MCP support for verification, as well as introducing a support for Claude Code and Codex agents directly inside the GUI. I can only hope their harness doesn&#8217;t suck.</p><p>You can set up the MCP for any agent <a href="https://developer.apple.com/documentation/xcode/giving-agentic-coding-tools-access-to-xcode">using these docs</a>.</p><div><hr></div><h4>Multi-agent and Orchestration</h4><p>We&#8217;ve picked the best model, set the reasoning budget to &#8220;high&#8221;, and now we have the agent automatically verifying its work via XcodeBuildMCP. Amazing! </p><p>But now it&#8217;s taking 10 minutes to work after being asked to make a change.</p><p>How can we handle this latency? We introduce a multi-agent workflow! </p><p>This is exactly what it sounds: running multiple instances of the CLI and context-switching between tasks as they work in parallel.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0UYi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0UYi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 424w, https://substackcdn.com/image/fetch/$s_!0UYi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 848w, https://substackcdn.com/image/fetch/$s_!0UYi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 1272w, https://substackcdn.com/image/fetch/$s_!0UYi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0UYi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png" width="1456" height="892" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:892,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:464109,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.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_!0UYi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 424w, https://substackcdn.com/image/fetch/$s_!0UYi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 848w, https://substackcdn.com/image/fetch/$s_!0UYi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.png 1272w, https://substackcdn.com/image/fetch/$s_!0UYi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52aeadf1-dffb-4ab4-862a-bbe46cdf60c3_1698x1040.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><em>Orchestration</em> takes this further, automating multi-agent workflows via open-source tools. They spawn specialised agents under a supervisor with shared memory, task decomposition, and handoff, creating separate agents for tasks like planning, coding, testing, and review.</p><p>In my experience, multi-agent is very good and productive, with the engineer as the orchestrator. Automatic orchestration is a little too rich for my blood, but you can read <a href="https://maggieappleton.com/gastown">this great post about Gas Town</a> if you want the full scoop.</p><p>Unfortunately, on iOS at least, multi-agent and automatic verification can cause problems: with XcodeBuildMCP, only one build is allowed at once, and you can run into annoying DerivedData build errors with two simultaneous builds.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!owea!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!owea!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 424w, https://substackcdn.com/image/fetch/$s_!owea!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 848w, https://substackcdn.com/image/fetch/$s_!owea!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 1272w, https://substackcdn.com/image/fetch/$s_!owea!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!owea!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png" width="1456" height="393" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:393,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:164230,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.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_!owea!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 424w, https://substackcdn.com/image/fetch/$s_!owea!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 848w, https://substackcdn.com/image/fetch/$s_!owea!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.png 1272w, https://substackcdn.com/image/fetch/$s_!owea!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17329811-da68-4b3a-a04c-fb149cccfd3a_1688x456.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>Setting your terminal client to send notifications is a godsend with multi-agent, because you can immediately jump to the tab with completed tasks and re-prompt. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ME1d!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ME1d!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 424w, https://substackcdn.com/image/fetch/$s_!ME1d!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 848w, https://substackcdn.com/image/fetch/$s_!ME1d!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 1272w, https://substackcdn.com/image/fetch/$s_!ME1d!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ME1d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png" width="1456" height="323" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:323,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:374994,&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://blog.jacobstechtavern.com/i/185286257?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.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_!ME1d!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 424w, https://substackcdn.com/image/fetch/$s_!ME1d!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 848w, https://substackcdn.com/image/fetch/$s_!ME1d!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 1272w, https://substackcdn.com/image/fetch/$s_!ME1d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6b5e761-3b49-4526-b575-c80bf71d8968_3024x670.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><h4>AGENTS.md and Skills</h4><p>The open-source community has been taking iOS pain points and documenting them for posterity. Paul Hudson <a href="https://github.com/twostraws/SwiftAgents">open-sourced an AGENTS.md file</a> designed to guide LLMs to shed bad habits and write more idiomatic SwiftUI. Unfortunately, it&#8217;s not had a ton of community input since release. </p><p>What I was surprised by, is that the agents have become GOOD at following and remembering instructions in this file in the last few months. To the extent where it&#8217;s nearly pedantic: <em>no, you don&#8217;t need to write a plan when I ask you to checkout a new branch</em>.</p><p>They are also great at using their skills without being asked:</p><p><a href="https://developers.openai.com/codex/skills/">Codex</a> and <a href="https://code.claude.com/docs/en/skills">Claude Code</a> have Skills, a feature that allows you to pre-package instructions, resources, and scripts to improve performance on repeatable workflows</p><p>Thomas Ricouard (legend) has <a href="https://dimillian.github.io/Skills/">open-sourced a number of skills</a> useful in iOS including SwiftUI performance auditing, SPM app packaging, and Swift 6.2 Concurrency adoption.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CXmx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CXmx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 424w, https://substackcdn.com/image/fetch/$s_!CXmx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 848w, https://substackcdn.com/image/fetch/$s_!CXmx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 1272w, https://substackcdn.com/image/fetch/$s_!CXmx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CXmx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png" width="1456" height="643" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:643,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:311072,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.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_!CXmx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 424w, https://substackcdn.com/image/fetch/$s_!CXmx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 848w, https://substackcdn.com/image/fetch/$s_!CXmx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.png 1272w, https://substackcdn.com/image/fetch/$s_!CXmx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbde9af90-d1f4-4ee1-8644-7512d836d3ea_2246x992.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">From <a href="https://github.com/Dimillian/Skills/blob/main/swift-concurrency-expert/SKILL.md">swift-concurrency-expert</a> by Thomas Richard</figcaption></figure></div><p>What Codex 5.2 does better than any model before: it actually reliably uses skills when appropriate, and follows the instructions you configure. You can set up your AGENTS.md file with a specific workflow: </p><ul><li><p>Always pull main and check out a new branch before work.</p></li><li><p>Always document a plan and get my sign-off before changing code.</p></li><li><p>Always verify your work via compile/test/run with XcodeBuildMCP.</p></li></ul><p>And it will follow this to the letter!</p><p>Recently, sites like <strong>skills.sh</strong> have collected together open-sourced skills in a discoverable format, making them installable via a simple shell command, like this:</p><pre><code>npx skills add https://github.com/avdlee/swiftui-agent-skill --skill swiftui-expert-skill</code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2P8X!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2P8X!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 424w, https://substackcdn.com/image/fetch/$s_!2P8X!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 848w, https://substackcdn.com/image/fetch/$s_!2P8X!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 1272w, https://substackcdn.com/image/fetch/$s_!2P8X!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2P8X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png" width="1456" height="862" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.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;:113128,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.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_!2P8X!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 424w, https://substackcdn.com/image/fetch/$s_!2P8X!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 848w, https://substackcdn.com/image/fetch/$s_!2P8X!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.png 1272w, https://substackcdn.com/image/fetch/$s_!2P8X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7983c2f0-8585-4ce9-abea-424456fb84ba_1716x1016.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"><a href="https://skills.sh/?q=swift">skills.sh</a></figcaption></figure></div><p>Annoyingly, Anthropic still hasn&#8217;t bothered to adopt the standard AGENTS.md and .agent/skills formats yet, but you can create a simple file-path alias inside your CLAUDE.md pointing at the main file as a source of truth. </p><div><hr></div><h4>Teleporting Sessions to the Web</h4><p>Claude Code and Codex live in your CLI. But they can also live in the cloud!</p><p>Paid users can connect their GitHub repos to their web client at <a href="http://claude.ai/code">claude.ai/code</a> or <a href="http://chatgpt.com/codex">chatgpt.com/codex</a> to get that lovely agentic goodness on-the-go</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LHzQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LHzQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 424w, https://substackcdn.com/image/fetch/$s_!LHzQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 848w, https://substackcdn.com/image/fetch/$s_!LHzQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 1272w, https://substackcdn.com/image/fetch/$s_!LHzQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LHzQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png" width="1456" height="603" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:603,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:110180,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.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_!LHzQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 424w, https://substackcdn.com/image/fetch/$s_!LHzQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 848w, https://substackcdn.com/image/fetch/$s_!LHzQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.png 1272w, https://substackcdn.com/image/fetch/$s_!LHzQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc52cd7e6-d31c-4615-8d33-7c5f10f1bf72_1970x816.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>The win here isn&#8217;t immediately obvious.</p><p>But consider the workflow it unlocks:</p><ul><li><p>Set up your team, <strong>including non-technical</strong>, with Claude Code or Codex.</p></li><li><p>They find a bug and report it directly in a Codex session via the iOS app.</p></li><li><p>An agent could potentially <strong>diagnose</strong> the issue, <strong>fix</strong> it, and create a <strong>PR</strong>.</p></li></ul><p>Claude Code goes one step further: the <a href="https://code.claude.com/docs/en/claude-code-on-the-web">teleport</a> command enables you to jump a running CLI session to a web session. This is useful if you wanted to keep track of your agents at the work do, on the loo, or perhaps on a date with your boo.</p><div><hr></div><h4>Tab Completion</h4><p>Cursor is arguably the most successful AI application out there, allowing devs to pick between GPT-5.2 and Opus 4.5 models in a VS-Code-forked IDE.</p><p>But I kind of always felt iffy about it.</p><p>But when I tried it in early/mid 2025, it was objectively quite sh*t. </p><p>It was useless at gathering context across more than a trivially small codebase, and felt like it throttled, or perhaps lobotomised, the underlying models to squeeze them into a $20/mo subscription fee. </p><p>But I need to revisit it at some point, because people say it&#8217;s the gold standard for manually programming these days.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;9e8fda70-2a4f-4db1-9a2b-3d7915f3793b&quot;,&quot;duration&quot;:null}"></div><p>The <em>Tab Completion</em> workflow is considered both fast and accurate, often suggesting what you need. Just tap Tab to accept.</p><div><hr></div><h4>The Ralph Loop</h4><p>Ralph, and yes it&#8217;s named specifically after Ralph Wiggum, is a <a href="https://github.com/frankbria/ralph-claude-code">plugin</a> for getting your agent to continuously work until it&#8217;s actually finished.</p><p>When Claude Code finishes working on a task, the plugin stops it from completing, and re-sends the original prompt. It forces the agent to run in a loop until it converges on an optimal output. </p><p>The core idea is that a good prompt and multiple iterations on the same code tend to produce better results than one-shotting, as long as Claude Code can verify its work via tests or builds. The plugin itself automates this process, while also helping stop the loop from accidentally eating through all your credits.</p><p>I don&#8217;t have a dog in this fight, but <a href="https://x.com/steipete/status/2011886384102195265">some people reckon</a> that using a plugin to force Claude Code to verify its work is unnecessary when Codex can get it right first time.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HTtM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HTtM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HTtM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HTtM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HTtM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HTtM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg" width="803" height="500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:500,&quot;width&quot;:803,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:88976,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HTtM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HTtM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HTtM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HTtM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F219115c5-9a93-47f6-8987-964832d85e2e_803x500.jpeg 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><div><hr></div><h4><a href="https://blog.jacobstechtavern.com/i/185165895/openclaw-aka-clawdbot">OpenClaw (aka Clawdbot)</a></h4><p>A recent project by the legendary <a href="https://x.com/steipete">Peter Steinberger</a> took the internet by storm early this year. But, frankly, it took me a very long time to understand what it was.</p><p>In short (I&#8217;m criminally underexplaining here), it&#8217;s Claude + Memory + Texting. It links to messaging apps like WhatsApp or Telegram, and allows you to chat to the agent while on a date with your wife. Finally.</p><p>People have bought Mac Minis specifically for this <em>(you can just as easily get a <a href="https://www.hetzner.com/dedicated-rootserver?mtm_campaign=18515490449&amp;mtm_source=google&amp;mtm_keyword=hetzner&amp;mtm_medium=Brand_Search&amp;mtm_content=626298411305&amp;gad_source=1&amp;gad_campaignid=18515490449&amp;gbraid=0AAAAADoOjTUvV7pDvWfQmhVBxTqfMMN-r&amp;gclid=Cj0KCQiA-YvMBhDtARIsAHZuUzJkQn3cgFsCtD7p6P_mr4hSRg8KTuxUQztkcusNTffVbPy1PFKEEiAaAqFDEALw_wcB">Hetzner box</a> but that&#8217;s no fun) </em>and, to listen to them, <a href="https://x.com/AlexFinn/status/2017305997212323887">found God</a> <em>(or at least AGI)</em>. Someone claimed their agent paid for a phone number from Twilio, connected to the ChatGPT voice API, and rang the user.</p><p>It&#8217;s probably little ill-advised to give your credit card details to a robot, but it&#8217;s hella cool.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vtVi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vtVi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 424w, https://substackcdn.com/image/fetch/$s_!vtVi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 848w, https://substackcdn.com/image/fetch/$s_!vtVi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 1272w, https://substackcdn.com/image/fetch/$s_!vtVi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vtVi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png" width="1456" height="1257" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1257,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:931100,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.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_!vtVi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 424w, https://substackcdn.com/image/fetch/$s_!vtVi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 848w, https://substackcdn.com/image/fetch/$s_!vtVi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.png 1272w, https://substackcdn.com/image/fetch/$s_!vtVi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F328c2d0a-da44-4ec4-b9ab-1b4c92faff8b_1872x1616.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"><a href="https://openclaw.ai">OpenClaw</a></figcaption></figure></div><div><hr></div><h2>Cargo-Culting the Creator of Claude Code</h2><p>The first cargo cult originated in world war 2. Pacific tribes saw planes stocked with supplies and food landing, and began ritualistically imitating allied military practices in the hope of getting more planes to come with more supplies.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vax-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vax-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 424w, https://substackcdn.com/image/fetch/$s_!Vax-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 848w, https://substackcdn.com/image/fetch/$s_!Vax-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 1272w, https://substackcdn.com/image/fetch/$s_!Vax-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vax-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp" width="1024" height="776" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:776,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:103272,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Vax-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 424w, https://substackcdn.com/image/fetch/$s_!Vax-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 848w, https://substackcdn.com/image/fetch/$s_!Vax-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 1272w, https://substackcdn.com/image/fetch/$s_!Vax-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda428d84-ade6-4362-bc04-e2e12fc42d2a_1024x776.webp 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">Image source had no credit</figcaption></figure></div><p>&#8220;Cargo cult&#8221; is also my favourite metaphor in tech. It describes the classic fallacy:</p><blockquote><p><em>If we copy what big tech companies do, we will become a big tech company.</em></p></blockquote><p>Developers <em>love</em> introducing complexity, and need to be constantly hit to prevent them from introducing custom build systems, proprietary UI frameworks, and re-architecting to VIPER. Solutions designed for problems <em>&#8220;at scale&#8221;</em>, meaning tens of millions of users, and <em>not</em> a team of 3 devs in a basement.</p><p>But, sometimes, it can be handy to find out what the big boys are doing so we can cosplay. </p><p>So I&#8217;m going to replicate Boris Cherny&#8217;s Claude Code workflow. Along with some of the new techniques we learned about earlier. </p><div class="twitter-embed" data-attrs="{&quot;url&quot;:&quot;https://x.com/bcherny/status/2007179832300581177&quot;,&quot;full_text&quot;:&quot;I'm Boris and I created Claude Code. Lots of people have asked how I use Claude Code, so I wanted to show off my setup a bit.\n\nMy setup might be surprisingly vanilla! Claude Code works great out of the box, so I personally don't customize it much. There is no one correct way to&quot;,&quot;username&quot;:&quot;bcherny&quot;,&quot;name&quot;:&quot;Boris Cherny&quot;,&quot;profile_image_url&quot;:&quot;https://pbs.substack.com/profile_images/1902044548936953856/J2jeik0t_normal.jpg&quot;,&quot;date&quot;:&quot;2026-01-02T19:58:58.000Z&quot;,&quot;photos&quot;:[],&quot;quoted_tweet&quot;:{},&quot;reply_count&quot;:1253,&quot;retweet_count&quot;:6652,&quot;like_count&quot;:52129,&quot;impression_count&quot;:7523425,&quot;expanded_url&quot;:null,&quot;video_url&quot;:null,&quot;belowTheFold&quot;:true}" data-component-name="Twitter2ToDOM"></div><p>What is he doing? </p><ol><li><p>Running 5 Claude Code instances in parallel on the terminal </p></li><li><p>Regularly <a href="https://arach.io/til/claude-code-teleport-sessions/">teleporting to sandboxed web sessions</a> for background processing </p></li><li><p>Sticking religiously to the slowest, smartest thinking model</p></li><li><p>Maintaining a single, big, shared, CLAUDE.md in the repo </p></li><li><p>Using Github Actions to update CLAUDE.md as part of PRs </p></li><li><p>Starting sessions in plan mode, refining, then one-shotting </p></li><li><p>Creating <a href="https://code.claude.com/docs/en/slash-commands#bash-command-execution">slash commands</a> for commonly-used workflows, e.g. commits </p></li><li><p>Using a few <a href="https://code.claude.com/docs/en/sub-agents">subagents</a> for specific workflows, e.g. verification or simplifying </p></li><li><p>Using a PostToolUse hook to run linting on generated code </p></li><li><p>Avoid --dangerously-skip-permisisons, but allow permissions in settings.json</p></li><li><p>Configure MCP to interface with tools like Slack and SQL using mcp.json</p></li><li><p>For long-running tasks, ensure Claude verifies its work in the background </p></li><li><p>Solid verification is critical: tests, iOS simulator runs, or bash scripts</p></li></ol><p>Alright, let&#8217;s put this cargo-cult to the test, and build the one that got away: <strong>Maxwell</strong>.</p><div><hr></div><p>Oh, and he actually tweeted again recently. Things do move fast.</p><div class="twitter-embed" data-attrs="{&quot;url&quot;:&quot;https://x.com/bcherny/status/2017742741636321619?s=46&quot;,&quot;full_text&quot;:&quot;I'm Boris and I created Claude Code. I wanted to quickly share a few tips for using Claude Code, sourced directly from the Claude Code team. The way the team uses Claude is different than how I use it. Remember: there is no one right way to use Claude Code -- everyones' setup is&quot;,&quot;username&quot;:&quot;bcherny&quot;,&quot;name&quot;:&quot;Boris Cherny&quot;,&quot;profile_image_url&quot;:&quot;https://pbs.substack.com/profile_images/1902044548936953856/J2jeik0t_normal.jpg&quot;,&quot;date&quot;:&quot;2026-01-31T23:32:12.000Z&quot;,&quot;photos&quot;:[],&quot;quoted_tweet&quot;:{},&quot;reply_count&quot;:850,&quot;retweet_count&quot;:5552,&quot;like_count&quot;:49029,&quot;impression_count&quot;:8146822,&quot;expanded_url&quot;:null,&quot;video_url&quot;:null,&quot;belowTheFold&quot;:true}" data-component-name="Twitter2ToDOM"></div><p>What now? </p><ol><li><p>Use worktrees (or just multiple git checkouts) to run agents in parallel</p></li><li><p>Always start with a plan, then get another agent to review the plan <em>(personally I like to pit Claude Code against Codex!)</em></p></li><li><p>Ensure your AGENTS.md/CLAUDE.md is updated every time an agent makes a mistake </p></li><li><p>Create skills regularly and commit them to git, especially common daily tasks </p></li><li><p>Use Slack MCP to directly tell @Claude/@Codex to fix a bug and make a PR </p></li><li><p>Utilise these pro prompts:</p><ol><li><p>Ask the agent to grill you on changes so you understand</p></li><li><p>After a mediocre fix, tell it to scrap the change and re-implement </p></li><li><p>Write detailed specs with minimal ambiguity before handing off work</p></li></ol></li><li><p>Customise your terminal and utilise voice dictation (WisprFlow is best!)</p></li><li><p>Subagents can be useful to get more compute or preserve your context window </p></li><li><p>Agents can connect to analytics and databases to answer questions </p></li><li><p>You can have the agent explain the &#8220;why&#8221; behind the changes, and even present visual diagrams explaining your codebase. </p></li></ol><div><hr></div><h2>Building Maxwell in an afternoon</h2><p>Maxwell was conceived as part of a team building exercise, where we pitched a novel business idea. After discarding my original idea of anti-covid-branded hand sanitiser, I pivoted. </p><p>I&#8217;d just moved into my first home, and experienced the annoying hassle of lightbulb management for the first time. Lights are everywhere, bulbs fail intermittently, and there are dozens of fittings, styles, and colour temperatures you need to understand if you want to replace them.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1Wwk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1Wwk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 424w, https://substackcdn.com/image/fetch/$s_!1Wwk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 848w, https://substackcdn.com/image/fetch/$s_!1Wwk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 1272w, https://substackcdn.com/image/fetch/$s_!1Wwk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1Wwk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp" width="600" height="480" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:480,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:66012,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1Wwk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 424w, https://substackcdn.com/image/fetch/$s_!1Wwk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 848w, https://substackcdn.com/image/fetch/$s_!1Wwk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 1272w, https://substackcdn.com/image/fetch/$s_!1Wwk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1da7ccd0-00e0-4c84-a6ae-8a2258d97755_600x480.webp 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">Diagram from <a href="https://hirosarts.com/blog/common-lamp-holder-types/?srsltid=AfmBOoraojXT6OMs3zsJGIc3A5np5KdgOHkRSq773BG8fmI8JUX55mo-">Hirostart</a></figcaption></figure></div><p>Maxwell was born.</p><p>Map out the lightbulbs in your home. Track what needs replacing. And automatically replenish them. </p><p>24-year-old Jacob never got this off the ground, because in a shocking evolution of his maturity, he actually tried to verify the business side before building anything. </p><p>Unfortunately, this verification didn&#8217;t get much further than an email to B&amp;Q customer support and an InMail to their CEO. <em>He tried.</em> </p><p>Because he wasn&#8217;t able to get the drop-shipping side to work, he put the project on the permanent backburner. </p><p>Until now.</p><p>Er, hold on.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mho5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mho5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 424w, https://substackcdn.com/image/fetch/$s_!mho5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 848w, https://substackcdn.com/image/fetch/$s_!mho5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 1272w, https://substackcdn.com/image/fetch/$s_!mho5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mho5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png" width="1456" height="403" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:403,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:125391,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.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_!mho5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 424w, https://substackcdn.com/image/fetch/$s_!mho5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 848w, https://substackcdn.com/image/fetch/$s_!mho5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.png 1272w, https://substackcdn.com/image/fetch/$s_!mho5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4faf5932-34bb-4946-939e-092f6f5b8b60_1914x530.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>Okay, disregard what I said, I totally tried to build it back in 2020.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jThW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jThW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 424w, https://substackcdn.com/image/fetch/$s_!jThW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 848w, https://substackcdn.com/image/fetch/$s_!jThW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 1272w, https://substackcdn.com/image/fetch/$s_!jThW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jThW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png" width="1456" height="753" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:753,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:425332,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.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_!jThW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 424w, https://substackcdn.com/image/fetch/$s_!jThW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 848w, https://substackcdn.com/image/fetch/$s_!jThW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.png 1272w, https://substackcdn.com/image/fetch/$s_!jThW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f185511-91d6-4d40-9981-a9cd159f4f91_2592x1340.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>I hazily recall my quixotic quest to build a lightbulb fitting classifier ML model using CreateML. My rush to implement Stripe payments before even a hint of revenue. My zealot-like insistence on using Carthage as a dependency manager.</p><p>I also found my old logo! </p><p>The only half-valuable thing I got out of my Apple Pencil.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aisJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aisJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 424w, https://substackcdn.com/image/fetch/$s_!aisJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 848w, https://substackcdn.com/image/fetch/$s_!aisJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 1272w, https://substackcdn.com/image/fetch/$s_!aisJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aisJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png" width="1456" height="806" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:806,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1499111,&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://blog.jacobstechtavern.com/i/185165895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.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_!aisJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 424w, https://substackcdn.com/image/fetch/$s_!aisJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 848w, https://substackcdn.com/image/fetch/$s_!aisJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.png 1272w, https://substackcdn.com/image/fetch/$s_!aisJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F553cd95a-1b6f-4e4a-ac20-5ea5c6d1579b_2680x1484.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>I&#8217;m putting my updated workflow to the test to build out this project:</p><ul><li><p>I did all this work in Codex using the <strong>gpt-5.2-codex high</strong> model.</p></li><li><p>I set up XcodeBuildMCP with the intention of verifying all my work autonomously via tests and simulator runs.</p></li><li><p>The repo contains some open-sourced AGENTS.md, slash commands, and skills for SwiftUI and concurrency review.</p></li><li><p>I&#8217;m going to aim to run 5 instances of Codex in parallel, numbered, with each CLI window pinging me via system notification when they finish.</p></li><li><p>For each instance, I&#8217;ll carefully plan each feature before trying to one-shot.</p></li><li><p>I&#8217;m going to set up web sessions via the ChatGPT app and attempt to ship some QA fix PRs while eating dinner.</p></li><li><p>If I have time, I might install Cursor and implement some manual fixes, with my fingers, like it&#8217;s the 1970s.</p></li></ul><p>Here&#8217;s the full project!</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;15b856ea-74d9-4c2a-9625-c596fe2c3554&quot;,&quot;duration&quot;:null}"></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/jacobsapps/Maxwell&quot;,&quot;text&quot;:&quot;The sample project on GitHub&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://github.com/jacobsapps/Maxwell"><span>The sample project on GitHub</span></a></p><blockquote><p><em>Well, it&#8217;s not exactly finished, but I trust you not to PIP me. <br>Pretty good for an afternoon&#8217;s work, I reckon</em>.</p></blockquote><div><hr></div><h2><strong>Last Orders</strong></h2><p>I spent summer diving headfirst into agentic engineering using Claude Code (and later, Codex), realising they were finally very, very good.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;69727932-bb94-42e2-8bb7-7251915e3507&quot;,&quot;caption&quot;:&quot;50-100% productivity gains echoes the fantasy sold to you by grifters selling $997 AI courses on Twitter. If that&#8217;s the case, I&#8217;m missing a trick charging $12/month. Because it&#8217;s legit.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Claude Code has made me 50-100% more productive&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-09-02T15:02:30.684Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!mGPq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e800aa-9c34-4664-8949-b7c5af8bff70_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/claude-code-productivity&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170755884,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:16,&quot;comment_count&quot;:2,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>But they have not stopped in the last 6 months. I suspect I&#8217;ll have to make this a semi-regular post to ensure we stay ahead of the curve!</p><p>Frankly, while multi-agent workflows are the current razor&#8217;s edge for productivity, it&#8217;s actually a deeply suboptimal workaround to latency. If high-thinking-budget inference ran 100x faster, we would not need to perform this context-switching, and could simply roll a single agent as the fully-engaged human in the loop.</p><p>I reckon that&#8217;s where the next 6 months is going to go.</p><blockquote><p><em>If you liked my post, subscribe free to join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week.</em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h5><strong>Sponsored Link</strong></h5><h4><strong><a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">RevenueCat Paywalls: Build &amp; iterate subscription flows faster</a></strong></h4><blockquote><p>RevenueCat Paywalls just added a steady stream of new features: more templates, deeper customization, better previews, and new promo tools. <a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">Check the Paywalls changelog</a> and keep improving your subscription flows as new capabilities ship.</p></blockquote>]]></content:encoded></item><item><title><![CDATA[My (deeply stressful) big tech interview grind]]></title><description><![CDATA[A survival guide for the tech job market in 2026]]></description><link>https://blog.jacobstechtavern.com/p/interview-grind</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/interview-grind</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 03 Feb 2026 16:02:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ASyg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.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_!ASyg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ASyg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!ASyg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!ASyg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!ASyg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ASyg!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4022827,&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://blog.jacobstechtavern.com/i/182069552?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ASyg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!ASyg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!ASyg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!ASyg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82226f30-8964-4fad-a246-de6fe6e4c5e6_1680x1200.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><em>&#8220;Interview grind? Huh?</em>&#8221;, I hear you say from your screen, in the future, <em><a href="https://blog.jacobstechtavern.com/p/my-wife-gave-me-100-days">&#8220;I thought you were going independent?!&#8221;</a></em></p><p>Yeah, I thought so too. </p><p>Today&#8217;s post is one part life update, seven parts survival guide.</p><p>I&#8217;ll give a recap of where I got on my independence journey.</p><p>Next, I&#8217;ll share my experience working through 50 interviews in one month, and offer you practical advice for maximising your chances at passing each stage of the big tech interview process.</p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/my-going-indie-scorecard">My Going Indie Scorecard</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/my-job-application-journey">The job market</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/cv-optimisation">CV optimisation</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/recruiter-screening">Recruiter screening</a> </p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/first-technical-round">First technical round</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/take-home-test">Take-home test</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/the-panel-interview">The Panel Interview&#8482;</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/offer-and-onboarding">Offer &amp; Onboarding</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/182069552/last-orders">Last Orders</a></p></li></ul><div><hr></div><h2>My Going Indie Scorecard</h2><p>Before I tell you what&#8217;s new, let&#8217;s put together a scorecard of my 100 days as an independent creator:</p><p>My initial approach to shipping content: <strong>all bangers, all the time</strong>. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W0yJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W0yJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 424w, https://substackcdn.com/image/fetch/$s_!W0yJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 848w, https://substackcdn.com/image/fetch/$s_!W0yJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 1272w, https://substackcdn.com/image/fetch/$s_!W0yJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W0yJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif" width="480" height="270" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:270,&quot;width&quot;:480,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1889673,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/182069552?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!W0yJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 424w, https://substackcdn.com/image/fetch/$s_!W0yJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 848w, https://substackcdn.com/image/fetch/$s_!W0yJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 1272w, https://substackcdn.com/image/fetch/$s_!W0yJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e0a1df4-e863-4b4d-83be-aa2e8f53e167_480x270.gif 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><a href="https://blog.jacobstechtavern.com/p/swift-for-android-vs-kmp">My first month</a> of independence was <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">spent artisnally</a> crafting <a href="https://blog.jacobstechtavern.com/p/the-year-swiftui-died">each new article</a> over a full <a href="https://blog.jacobstechtavern.com/p/ios-system-design">5 working days</a>. Each one of these pieces of content was a killer, growing my paid subcount by over a dozen apiece. <strong>Content Score: A+</strong>.</p><p>Riding high, I deigned to actually do a budget. </p><p>And&#8230; f*ck.</p><p>You&#8217;d think a digital services business would have phenomenal margins, but costs like EU VAT, transaction fees, blog hosting fees, and income tax added up quickly.</p><p>Break even would be tough. Optimistically, maybe in 8 months, if my growth rate stayed at the maximum. Maybe I could do this before running out of money. But this is kind of a dumb risk when I have a wife, a mortgage, and 2 young kids. </p><p>War Stories landed me some great content, and was a brilliant excuse to connect to other prolific creators. You should definitely read my interviews if you haven&#8217;t had the chance! I will definitely continue to do more of these. </p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;5f7a594c-2a65-4bef-9f8e-e71aba0b2e30&quot;,&quot;caption&quot;:&quot;Welcome to my first edition of War Stories, where I partner with famous builders in the iOS space to share real-life stories from the frontlines as they scale their projects.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Great Connection Pool Meltdown&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100},{&quot;id&quot;:161471335,&quot;name&quot;:&quot;Pedro Pi&#241;era Buend&#237;a&quot;,&quot;bio&quot;:&quot;I'm a builder and an open source advocate. I'm the CEO of Tuist, a productivity platform for app developers.&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LyzR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf3ea601-3f55-43bf-a08f-066668e23640_3024x4032.jpeg&quot;,&quot;is_guest&quot;:true,&quot;bestseller_tier&quot;:null,&quot;primaryPublicationSubscribeUrl&quot;:&quot;https://thebuildersreturn.substack.com/subscribe?&quot;,&quot;primaryPublicationUrl&quot;:&quot;https://thebuildersreturn.substack.com&quot;,&quot;primaryPublicationName&quot;:&quot;The Builder's Return &quot;,&quot;primaryPublicationId&quot;:4469839}],&quot;post_date&quot;:&quot;2025-11-06T16:02:23.569Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!xR1f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/the-great-connection-pool-meltdown&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:176919776,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:16,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;b830428c-1a7d-4d1f-a7d1-c6b69fabf1b1&quot;,&quot;caption&quot;:&quot;Welcome to War Stories, where I partner with famous builders in the iOS space to share real-life stories from the frontlines. It&#8217;s part narrative, part interview, all swashbuckling fun.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;When To Kill A Project&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-11-20T16:01:51.474Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!GVEQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/when-to-kill-a-project&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:178878712,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:9,&quot;comment_count&quot;:3,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>My Creator Spotlights collab with <a href="https://weekly.fatbobman.com">fatbobman</a> also went ahead, and netted some nice cross-pollination with our mutual readership of iOS devs. </p><p>These collaborations produced some solid content, and allowed me to share some very fun war stories. My strategy, however, was about growing my free subscriber base significantly, and unfortunately I was not able to move the needle enough for this to bootstrap my independence. <strong>Collaboration Score: B-</strong>.</p><p>My experiment with paid acquisition was a big success in terms of scaling my readership, with my cost-per-acquisition down to (something like) $2 per inorganic free subscriber. These have translated into exactly zero paid subscribers (since I fixed my UTM tags last month). <strong>Paid Acquisition Score: C.</strong> </p><p>Tavern Tools&#8482;, my beautiful vision for a dev tools suite, was aborted before I began. I realised it was a giant distraction from growing my free base. My paid conversion rate was already sitting pretty at over 5%, so I didn&#8217;t need to create extra incentives here. <strong>DevTools Score: D for &#8220;dunno&#8221;, as I never showed up to the exam</strong>.</p><p>One bright spot in my scorecard was netting a sponsorship deal (perhaps more? Watch this space!) to advertise on my blog with my friends at <a href="https://www.revenuecat.com">RevenueCat</a>. However, it turns out that in the incredibly mature world of dev tools marketing, budgets can be tight for a new entrant. <strong>Sponsorship Score: B+</strong>.</p><p><strong>Overall Grade: B</strong>. Must try harder.</p><p>In the crushing wake of my budget, I realised what I had to do. I had to find my white whale. And what is an employer, if not just one <em>really big</em> paid subscriber? </p><div><hr></div><h2>My Job Application Journey </h2><p>Thus began my first foray into job applications since 2015.</p><p>My previous 3 job moves were through recruiters, and I&#8217;ve never had the luxury of treating the application process as a full-time job before.</p><p>The grind I underwent in December has given me insight into the state of the market, and finally given me the space to <em>properly</em> get ready for the tough interview loops that big tech companies apply to candidates.</p><p>Here&#8217;s my full stats: 26 applications. 2 offers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p4j3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p4j3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 424w, https://substackcdn.com/image/fetch/$s_!p4j3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 848w, https://substackcdn.com/image/fetch/$s_!p4j3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 1272w, https://substackcdn.com/image/fetch/$s_!p4j3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p4j3!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png" width="1200" height="431.04395604395603" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:523,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:110727,&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://blog.jacobstechtavern.com/i/182069552?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!p4j3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 424w, https://substackcdn.com/image/fetch/$s_!p4j3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 848w, https://substackcdn.com/image/fetch/$s_!p4j3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.png 1272w, https://substackcdn.com/image/fetch/$s_!p4j3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff4f4bfe1-5a7c-44a1-9e4c-14cede9dd640_1578x567.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">My job application stats in 2025</figcaption></figure></div><p>For my kings and queens who write native iOS for a living: the market isn&#8217;t as bad as the startup winter of 2022. <strong>It&#8217;s healthy</strong>. There are a ton of well-capitalised AI startups hiring native iOS engineers, despite <a href="https://newsletter.pragmaticengineer.com/p/native-vs-cross-platform">the narrative that cross-platform is eating our lunch</a>. There are a lot of established companies growing their teams too.</p><p>That said, unless you live in an American city, there are not many FAANG jobs to go around. In London, the only &#8220;big&#8221; big tech co&#8217;s hiring for iOS at the end of 2025 were Snap <em>(I got to the panel)</em> and Meta <em>(who ghosted me)</em>. </p><p>I&#8217;m kind of in a privileged position. I know the average engineer (who doesn&#8217;t run a popular blog) isn&#8217;t getting a &gt;50% hit rate on the CV screening. But I can share a lot of useful knowledge from my interview grind that can help you out with every step of the process.</p><blockquote><p><em>Upgrade to unlock this article, plus much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/interview-grind">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Xcode Organizer: Your Performance Cheat Sheet]]></title><description><![CDATA[Instruments, but crowdsourced]]></description><link>https://blog.jacobstechtavern.com/p/xcode-organiser</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/xcode-organiser</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 20 Jan 2026 16:01:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-l4i!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.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_!-l4i!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-l4i!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!-l4i!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!-l4i!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!-l4i!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-l4i!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:989047,&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://blog.jacobstechtavern.com/i/162635177?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-l4i!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!-l4i!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!-l4i!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!-l4i!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05a0641a-ea68-4042-a74b-ee9acf4374cf_1680x1200.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>I love working on app performance.</p><p>It just sounds cool. Performance. <em>Performance</em>. </p><p>While the bozos on feature teams are busy building stuff that actually brings in paying customers, platform engineers can feel smugly superior, typing away from our windowless basements, reducing launch time by 0.01 seconds. <em>For everyone!</em></p><p>Unfortunately, if you don&#8217;t have a full-time platform team, &#8220;performance work&#8221; is generally treated the same as &#8220;tech debt tickets&#8221;.</p><p>Despite what app release notes will have you believe, no one&#8217;s going to give us time to work on performance optimisations, because a lot of the time it&#8217;s invisible. Everyone agrees that <em>high performance</em> is desirable, but it&#8217;s virtually impossible to quantify the impact of marginal improvements.</p><p>So how does this ever get done? And how do we stay on top of it? </p><p>There is a way. And if you can master the technique, it&#8217;s also a pretty good way to get promoted. </p><p><strong>Be the dev that keeps a close eye on the Xcode Organizer. </strong></p><p>There&#8217;s nothing better for your promo packet <em>(and, for my indie readers, your own customers)</em> than identifying low-hanging fruit, recent regressions, or serious performance bottlenecks; crafting a proposal to solve them; and allotting engineering time to solve it.</p><p>This is not theoretical; this is pretty much my standard playbook. </p><p>I&#8217;ll keep a watchful eye on the Xcode Organizer. I&#8217;ll flag to Product or Engineering leadership whenever I spot an opportunity to improve something that users will actually notice: Launch time, scroll hitches, terminations, battery usage, storage usage. All these issues often have fairly trivial root causes, and offer an outsized user impact once you solve them.</p><p>Xcode Organizer is easily where 80% of my performance optimisation work originates. If you&#8217;re on top of it, you can usually pre-empt user complaints. </p><div><hr></div><blockquote><h5>Sponsored Link</h5><p><em>Substack, which powers my newsletter, is hiring iOS engineers!</em></p><p><em>The team is small, close-knit, and provides ample opportunities for mentorship, growth, ownership, and autonomy. You can apply for either the <a href="https://jobs.ashbyhq.com/substack/1b9b2f85-c54a-4cef-b5fc-e227bb30e3cc?utm_source=rMaLyl12Jp">growth team</a> or the <a href="https://jobs.ashbyhq.com/substack/695a7649-99a2-4b00-93e2-4078d2730a19?utm_source=rMaLyl12Jp">enterprise team</a>. Check out <a href="https://substack.com/jobs?utm_source=rMaLyl12Jp">their jobs page</a> for the full list of technical and non-technical openings.</em></p></blockquote><div><hr></div><h2>The Xcode Organizer</h2><p>We can find the Organizer in Xcode&#8217;s Window menu. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RpsC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RpsC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 424w, https://substackcdn.com/image/fetch/$s_!RpsC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 848w, https://substackcdn.com/image/fetch/$s_!RpsC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 1272w, https://substackcdn.com/image/fetch/$s_!RpsC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RpsC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png" width="1456" height="912" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:912,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2087131,&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://blog.jacobstechtavern.com/i/162635177?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.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_!RpsC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 424w, https://substackcdn.com/image/fetch/$s_!RpsC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 848w, https://substackcdn.com/image/fetch/$s_!RpsC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.png 1272w, https://substackcdn.com/image/fetch/$s_!RpsC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a38e040-43a7-438c-9b2e-dbc656f17f43_1856x1162.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>Even if you&#8217;ve never touched the performance charts, you&#8217;re likely already acquainted with the Organizer, since it&#8217;s where all your Archives live.</p><p>If you&#8217;ve been in the indie game for a while, you&#8217;ll also experience a nostalgia tour of everything you&#8217;ve ever submitted to the App Store.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gLOG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gLOG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 424w, https://substackcdn.com/image/fetch/$s_!gLOG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 848w, https://substackcdn.com/image/fetch/$s_!gLOG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 1272w, https://substackcdn.com/image/fetch/$s_!gLOG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gLOG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png" width="1456" height="961" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:961,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:843207,&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://blog.jacobstechtavern.com/i/162635177?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.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_!gLOG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 424w, https://substackcdn.com/image/fetch/$s_!gLOG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 848w, https://substackcdn.com/image/fetch/$s_!gLOG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.png 1272w, https://substackcdn.com/image/fetch/$s_!gLOG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76eecd4a-3d54-4eab-a4fa-296e18e435ab_2058x1358.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>Oh dear. </p><p>I just realised; none of my apps have enough users to actually display any data here. </p><p>Stand by. </p><blockquote><p><em>&#9742;&#65039; Thomas, help me out please! &#128225; </em></p></blockquote><p>Famous Twitter personality and iOS engineer <a href="https://x.com/Dimillian">Thomas Ricouard</a> generously took the time to share the performance stats of his indie app, <a href="https://apps.apple.com/gb/app/ice-cubes-for-mastodon/id6444915884 Ice Cubes for Mastodon">Ice Cubes for Mastodon</a>. Please show your appreciation by downloading it, either if you&#8217;re a Fediverse fanatic or even if you&#8217;re merely toot-curious.</p><blockquote><p><em>Thomas also posted a really good piece recently on <strong><a href="https://dimillian.medium.com/the-state-of-agentic-ios-engineering-in-2026-c5f0cbaa7b34">The State of Agentic iOS Engineering </a></strong><a href="https://dimillian.medium.com/the-state-of-agentic-ios-engineering-in-2026-c5f0cbaa7b34">in 2026</a>, which I massively recommend both if you&#8217;re new to agentic engineering or you&#8217;re already a Claudepilled Codex-cel</em>.</p></blockquote><div><hr></div><p>You can get very specific when you look through the organizer. You can slice most of the reports by time, by device, and by version.</p><p>There are usually tons of low-hanging performance optimisation fruit at the top level, but if you have enough users, you can often spot OS-version, device, or version corner cases by narrowing things down. </p><p>Many performance attributes in the Organizer have both metrics and reports to investigate. Metrics are aggregated numbers sliced across all your users and versions, and reports surface individual code-level issues. </p><p>I think of the Xcode Organizer like the top of the performance funnel. You get fully aggregated metrics across your whole user-base. When you spot a problem, you can often go deeper with Instruments. Once you identify the bottleneck, you can then solve it in code and verify the improvement.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!59vu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!59vu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 424w, https://substackcdn.com/image/fetch/$s_!59vu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 848w, https://substackcdn.com/image/fetch/$s_!59vu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 1272w, https://substackcdn.com/image/fetch/$s_!59vu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!59vu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png" width="1456" height="1089" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1089,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:236575,&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://blog.jacobstechtavern.com/i/162635177?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.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_!59vu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 424w, https://substackcdn.com/image/fetch/$s_!59vu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 848w, https://substackcdn.com/image/fetch/$s_!59vu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.png 1272w, https://substackcdn.com/image/fetch/$s_!59vu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49227ba4-8a5d-4c2b-9e82-2a08a8da88da_1570x1174.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>Now let&#8217;s look at how to apply each report in the Organizer to optimise your app&#8217;s performance today <em>(and make you look like a hero in the process!)</em>.</p><div><hr></div><blockquote><p><em>Upgrade to unlock this article, plus much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">full course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/xcode-organiser">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[How to design an SDK to handle $10bn in transactions]]></title><description><![CDATA[A deep-dive into SDK design (feat. RevenueCat)]]></description><link>https://blog.jacobstechtavern.com/p/revenuecat-sdk</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/revenuecat-sdk</guid><pubDate>Mon, 12 Jan 2026 16:01:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!L2oO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.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_!L2oO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!L2oO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!L2oO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!L2oO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!L2oO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!L2oO!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:3218311,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!L2oO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!L2oO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!L2oO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!L2oO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6eb1389-3b63-4020-bb6c-d4ac482cfe6c_1680x1200.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>RevenueCat has a neat business model: Take an enormously painful hassle (managing in-app subscriptions), abstract it into something bearable, and charge devs a cool 1% for the service. Classic painkiller. </p><p>This abstraction is where the value lies. </p><p>$10bn worth of value (so far!).</p><p>When tens of thousands of devs are relying on you to make money, the stakes can&#8217;t get much higher. Consequently, the <a href="https://github.com/RevenueCat/purchases-ios">RevenueCat iOS SDK</a> is one of the most battle-hardened open-source projects out there.</p><p>Therefore, <strong>we can learn a lot about SDK design principles by analysing it</strong>:</p><ul><li><p>Backwards compatibility as a top-level constraint</p></li><li><p>Fa&#231;ade-first design for public APIs</p></li><li><p>Sensible defaults and progressive disclosure of complexity</p></li><li><p>Careful layering of dependencies</p></li><li><p>Relentless logging, diagnostics, and profiling</p></li><li><p>Orchestration between services for complex flows </p></li><li><p>Offline-first correctness </p></li><li><p>&#8220;Invisible&#8221; performance characteristics </p></li><li><p>Friendly abstraction over janky third-party APIs</p></li><li><p>Keeping mindful of dev-ex (developer experience) every step of the way</p></li></ul><p>We&#8217;re taking a deep-dive into the payments flow: how the SDK abstracts away the complexity of making purchases and setting up in-app subscriptions.</p><div><hr></div><blockquote><h5><strong>Sponsored Link</strong> </h5><h4><strong><a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">RevenueCat Paywalls: Build &amp; iterate subscription flows faster</a></strong></h4><p>RevenueCat Paywalls just added a steady stream of new features: more templates, deeper customization, better previews, and new promo tools. <a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">Check the Paywalls changelog</a> and keep improving your subscription flows as new capabilities ship.</p></blockquote><p><em>(That&#8217;s right, I finally manifested <a href="https://blog.jacobstechtavern.com/i/138829948/the-observation-framework">my bit from 2023</a>)</em></p><div><hr></div><h2>Contents</h2><ul><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/high-level-system-design">High-Level System Design</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/how-to-make-a-purchase">How to make a Purchase</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/the-facade-layer">The Fa&#231;ade Layer</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/configuration-and-progressive-disclosure">Configuration and Progressive Disclosure</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/managing-the-dependency-graph">Managing the Dependency Graph</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/the-purchase-function-and-backwards-compatibility">The Purchase function and backwards compatibility</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/the-orchestration-layer">The Orchestration Layer</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/making-the-purchase-via-storekit">Making the Purchase via StoreKit</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/handling-the-transaction-and-delegating-to-services">Handling the transaction and delegating to services</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/handoff-to-the-services-layer">Handoff to the services layer</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/the-service-layer">The Service Layer</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/transactionposter-and-backend-validation">TransactionPoster and backend validation</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/customerinfomanager-and-offline-correctness">CustomerInfoManager and offline correctness</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/the-infrastructure-layer">The Infrastructure Layer</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/183560520/last-orders">Last Orders</a></p></li></ul><div><hr></div><h2><strong>High-Level System Design</strong> </h2><p>Consider the RevenueCat SDK at a basic level: how would you design such a thing? Don&#8217;t think about payments, subscriptions, entitlements, receipt validation, and paywalling yet.</p><p>It&#8217;s easier to start with a big box that abstracts away everything a user has to worry about. </p><p>Now consider: who are the big players involved?</p><p>There&#8217;s the client app, of course, who pays you money to use the SDK. Then, with a great big box, we can represent the SDK. The other major players are StoreKit, Apple&#8217;s own servers, and of course the RevenueCat backend itself, mostly all chatting to each other. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i918!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i918!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 424w, https://substackcdn.com/image/fetch/$s_!i918!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 848w, https://substackcdn.com/image/fetch/$s_!i918!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 1272w, https://substackcdn.com/image/fetch/$s_!i918!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i918!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png" width="1456" height="718" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:718,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:126235,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.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_!i918!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 424w, https://substackcdn.com/image/fetch/$s_!i918!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 848w, https://substackcdn.com/image/fetch/$s_!i918!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.png 1272w, https://substackcdn.com/image/fetch/$s_!i918!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ab38d4-1006-416f-b78d-1da2b9350598_1466x723.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">Mini system design drill I took during my big interview grind this December</figcaption></figure></div><p>The SDK needs to abstract all the complexity away of creating a customer, displaying products on a paywall, talking to StoreKit during a purchase, updating and handling user entitlements, and posting transaction info to a server so everything links up cross-platform.</p><p>Inside the SDK, the architecture is loosely set up in layers, with very heavy usage of constructor injection to manage dependencies across all the classes. These dependencies are all initialised on SDK init, with lower level services injected into high level managers and orchestrators where needed. </p><p>For payments, the conceptual layers look a little like:</p><ul><li><p>Fa&#231;ade layer containing <strong>Purchases</strong>, the public API surface </p></li><li><p>Orchestration layer where <strong>PurchasesOrchestrator</strong> coordinates everything</p></li><li><p>Managers layer containing business logic and services like <strong>OfferingsManager</strong>, <strong>CustomerInfoManager</strong>, and <strong>ProductsManager</strong>.</p></li><li><p>Infrastructure layer containing basic services like <strong>Backend</strong>, <strong>HTTPClient</strong>, and <strong>OperationDispatcher</strong>.</p></li></ul><p>Let&#8217;s dive down into these layers in detail to see how the SDK handles payments. </p><div><hr></div><p>There are a couple of useful keywords to clarify before we go too far into the guts of RevenueCat, because they come up a bunch:</p><ul><li><p><strong>Entitlements</strong> refers to the level of access and features the user has unlocked. For instance, whether they are on your free tier, your paid tier, or your founding members tier.</p></li><li><p><strong>Products</strong> are the different individual things a user might buy; for example a free trial, a monthly membership, or a discounted annual or lifetime membership. They list separately on the App Store, Google Play, and Stripe (for web!).</p></li><li><p><strong>Packages</strong> refers to equivalent products across platforms (basically this makes paywalling admin easier).</p></li></ul><h2>How to make a Purchase </h2><p>There are actually two ways to make purchases via the SDK:</p><ol><li><p>The default mode is using the built-in paywalls, which automatically display your offerings. Set up on the dashboard, and the SDK handles everything automatically.</p></li><li><p>You can also manually tell the SDK to execute a purchase like this. I&#8217;m going to follow this one, because we can follow through the full public API: </p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6dKV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6dKV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 424w, https://substackcdn.com/image/fetch/$s_!6dKV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 848w, https://substackcdn.com/image/fetch/$s_!6dKV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 1272w, https://substackcdn.com/image/fetch/$s_!6dKV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6dKV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png" width="1456" height="847" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:847,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:207810,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.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_!6dKV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 424w, https://substackcdn.com/image/fetch/$s_!6dKV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 848w, https://substackcdn.com/image/fetch/$s_!6dKV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.png 1272w, https://substackcdn.com/image/fetch/$s_!6dKV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa92ed9a-ea28-447b-880f-6725004ef237_1744x1014.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">Think of a Package the same as a Product displayed a paywall, but cross-platform</figcaption></figure></div><div><hr></div><h2>The Fa&#231;ade Layer</h2><p>Fa&#231;ade is a top-3 design pattern for me because I love the little accoutrements on the letter C there (apparently called a <em>cedilla</em>).</p><p><strong>Purchases</strong>, the main object devs use to init and use the SDK, is this fa&#231;ade, a minimal developer-friendly API that distills the tasks of complex StoreKit integration, receipt validation, and entitlement management into a few simple function calls.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qgQ8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qgQ8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 424w, https://substackcdn.com/image/fetch/$s_!qgQ8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 848w, https://substackcdn.com/image/fetch/$s_!qgQ8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 1272w, https://substackcdn.com/image/fetch/$s_!qgQ8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qgQ8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png" width="1456" height="1102" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1102,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1057010,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.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_!qgQ8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 424w, https://substackcdn.com/image/fetch/$s_!qgQ8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 848w, https://substackcdn.com/image/fetch/$s_!qgQ8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.png 1272w, https://substackcdn.com/image/fetch/$s_!qgQ8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F300659fa-d222-4e70-a3b9-9a8a8c398a42_2104x1592.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/3903cae7c99e6b1edf909ba259bd52e016a06c88/Sources/Purchasing/Purchases/Purchases.swift#L61">Purchases</a></figcaption></figure></div><p>Woah, Nelly, that&#8217;s a lot of dependencies. And I redacted <em>a lot</em>. But we can spot also a few interesting SDK design techniques already: </p><ul><li><p>If the SDK is not configured, it will <strong>fatalError()</strong> on access. This is a deliberate design choice: this makes it virtually impossible for the developer to mess up basic initialisation and misuse the SDK.</p></li><li><p>Note the <strong>@objc(RCPurchase) </strong>at the class declaration. This exposes the class to Objective-C, and provides a prefixed alternative name (because ObjC uses a global namespace). Objective-C compatibility is a must when you are working with thousands of iOS projects that might never migrate to Swift. </p></li><li><p>Purchases also serves as the root of the dependency graph, owning references to all the services, managers, and orchestrators used throughout the SDK. It applies manual constructor injection, which is preferable to introducing a third-party DI framework as a sub-dependency into <em>every app shipped by your customers</em>.</p></li></ul><h4>Configuration and Progressive Disclosure </h4><p>Initialising the SDK reveals another interesting tidbit around <a href="https://developer.apple.com/videos/play/wwdc2022/10059/">progressive disclosure in API design</a>, which is vital for your dev-ex.</p><p>Most devs will start by configuring their payments SDK with the API key only.</p><pre><code>@objc(configureWithAPIKey:)
@discardableResult static func configure(withAPIKey apiKey: String) -&gt; Purchases {
    Self.configure(withAPIKey: apiKey, appUserID: nil)
}</code></pre><p>As you grow towards more advanced use cases, you might end up using this alternative function that allows for configuration:</p><pre><code>@objc(configureWithConfigurationBuilder:)
@discardableResult static func configure(with builder: Configuration.Builder) -&gt; Purchases {
    return Self.configure(with: builder.build())
}</code></pre><p>This <strong>Configuration</strong> object offers more granular control over SDK behaviour: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!F2I5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!F2I5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 424w, https://substackcdn.com/image/fetch/$s_!F2I5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 848w, https://substackcdn.com/image/fetch/$s_!F2I5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!F2I5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!F2I5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png" width="1456" height="1099" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1099,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:690652,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.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_!F2I5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 424w, https://substackcdn.com/image/fetch/$s_!F2I5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 848w, https://substackcdn.com/image/fetch/$s_!F2I5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!F2I5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0919e057-30f2-4ec1-bf6d-25699fcd3cd9_1584x1196.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>This means we can keep APIs simple while enabling customised behaviour for power users. </p><p>Consider a developer introducing this advanced configuration for the SDK to enforce response verification, hardcode StoreKit 2, and configure timeouts:</p><pre><code>let config = Configuration.Builder(withAPIKey: apiKey)
    .with(observerMode: true)
    .with(storeKitVersion: .storeKit2)
    .with(responseVerificationMode: .enforced)
    .with(networkTimeout: 90)
    .with(storeKit1Timeout: 45)
    .with(preferredLocale: "fr_FR")
    .build()
Purchases.configure(with: config)</code></pre><p>Without being able to apply this configuration at init, we would have to make the API surface far more complex, for example the basic <strong>purchase()</strong> API would require far more parameters:</p><pre><code><code>try await Purchases.shared.purchase(
    product: product,
    observerMode: true,
    storeKitVersion: .storeKit2,
    responseVerificationMode: .enforced,
    networkTimeout: 90,
    storeKit1Timeout: 45,
    preferredLocale: "fr_FR"
)</code></code></pre><p>Because this all lives in the configuration at init, the API can remain simple:</p><pre><code>try await Purchases.shared.purchase(product: product)</code></pre><p>Configuration creep is also a problem, so you need to be thoughtful about how much should be configurable locally, vs how much can be set up on a dashboard somewhere. You need to carefully balance ease-of-use, flexibility, and actual customer needs.</p><h4>Managing the Dependency Graph</h4><p>The dependency graph is all wired up in the Purchases convenience initialiser: All the services, managers, and orchestrators get created here. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bb-Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 424w, https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 848w, https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 1272w, https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png" width="1456" height="2275" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2275,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2079816,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.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_!Bb-Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 424w, https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 848w, https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.png 1272w, https://substackcdn.com/image/fetch/$s_!Bb-Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5933bf6a-7c36-4d19-9075-09eb4c2c5bb1_2314x3616.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/3903cae7c99e6b1edf909ba259bd52e016a06c88/Sources/Purchasing/Purchases/Purchases.swift#L333">Purchases</a></figcaption></figure></div><blockquote><p><em>Because I&#8217;m not being paid by the letter, I redacted about 80% of the code.</em></p></blockquote><p>The layered architecture I referred to isn&#8217;t enforced <em>logically</em>, but is kept safe by the compiler: it&#8217;s impossible accidentally create a cycle when using vanilla constructor injection, because your code just won&#8217;t compile. </p><p>So I suppose it&#8217;s less like a dependency <em>graph</em>, and more like a <em>list</em> of dependencies that are instantiated, one after the other, in the order they appear in this initialiser.</p><p>This is not trivial, however: you still need to carefully design each dependency to avoid cycles, ensuring each service has only what it needs.</p><h4>The Purchase function and backwards compatibility </h4><p>It&#8217;s easy to get recursively sidetracked when analysing an interesting SDK like this. Where were we? We were searching out the <strong>purchase()</strong> function. </p><p>I found the protocol we were looking for. This is the true fa&#231;ade: the protocol with every developer-accessible function:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xxzG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xxzG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 424w, https://substackcdn.com/image/fetch/$s_!xxzG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 848w, https://substackcdn.com/image/fetch/$s_!xxzG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 1272w, https://substackcdn.com/image/fetch/$s_!xxzG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xxzG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png" width="1456" height="816" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:816,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:919975,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.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_!xxzG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 424w, https://substackcdn.com/image/fetch/$s_!xxzG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 848w, https://substackcdn.com/image/fetch/$s_!xxzG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.png 1272w, https://substackcdn.com/image/fetch/$s_!xxzG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8562e321-a5c6-4a26-bb40-e1016c312260_2292x1284.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/45a6db20034f2195227c34f0ab8b90e1f86bfa3b/Sources/Purchasing/Purchases/PurchasesType.swift#L325">PurchaseType</a></figcaption></figure></div><p>When creating an SDK used by tens of thousands of developers, backwards compatibility is perhaps the most important consideration of all. You aren&#8217;t Apple. You don&#8217;t really get to deprecate stuff, because devs probably don&#8217;t have a Stockholm-syndrome relationship with you.</p><p>It&#8217;s wonderful to offer shiny new async/await APIs, but you don&#8217;t get to force devs to migrate. You need to keep those &#8220;legacy&#8221; completion block forms working too. </p><p>This doesn&#8217;t mean you have to double your code: the async versions just wrap the original completion block versions using <strong>withUnsafeThrowingContinuation</strong>. </p><p>You also can&#8217;t just gate all your functionality behind the latest OS versions: as an SDK, your deployment target is constrained by <em>the customers of your customers</em>. A single gambling app supporting iOS 11 for their three surviving geriatric whales means you can&#8217;t just rip the floor out from under them. </p><blockquote><p><em>RevenueCat targets iOS 13 for <a href="https://github.com/RevenueCat/purchases-ios/tree/3903cae7c99e6b1edf909ba259bd52e016a06c88">their main SPM repo</a>, but <a href="https://cocoapods.org/pods/RevenueCat">still supports iOS 11 on Cocoapods</a>.</em></p></blockquote><p>For our <strong>purchase(package: completion:)</strong> function, the implementation is here, firing into the <strong>PurchasesOrchestrator</strong> class.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E2a0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E2a0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 424w, https://substackcdn.com/image/fetch/$s_!E2a0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 848w, https://substackcdn.com/image/fetch/$s_!E2a0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 1272w, https://substackcdn.com/image/fetch/$s_!E2a0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E2a0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png" width="1456" height="604" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:604,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:505447,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.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_!E2a0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 424w, https://substackcdn.com/image/fetch/$s_!E2a0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 848w, https://substackcdn.com/image/fetch/$s_!E2a0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.png 1272w, https://substackcdn.com/image/fetch/$s_!E2a0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6687939d-b9a1-4aff-b45c-5253fb9cf0fe_1928x800.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/45a6db20034f2195227c34f0ab8b90e1f86bfa3b/Sources/Purchasing/Purchases/Purchases.swift#L1110">Purchases</a></figcaption></figure></div><p><strong>PurchasesOrchestrator</strong> is the next layer in our conceptual stack of pancakes. Or lasagna. I actually need to get lunch. </p><div><hr></div><h2>The Orchestration Layer</h2><p>This is by far the most complicated functionality in the SDK, which is why it&#8217;s fun to write about. <strong>PurchasesOrchestrator</strong> coordinates all the services and dependencies required to make a purchase, including transacting with StoreKit, posting completed transactions data to the RevenueCat backend, and updating customer entitlements locally. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7LR6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7LR6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 424w, https://substackcdn.com/image/fetch/$s_!7LR6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 848w, https://substackcdn.com/image/fetch/$s_!7LR6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 1272w, https://substackcdn.com/image/fetch/$s_!7LR6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7LR6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png" width="1456" height="1091" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1091,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1082935,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.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_!7LR6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 424w, https://substackcdn.com/image/fetch/$s_!7LR6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 848w, https://substackcdn.com/image/fetch/$s_!7LR6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.png 1272w, https://substackcdn.com/image/fetch/$s_!7LR6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F611cecd1-44d4-4852-b51d-c9a01661db81_2008x1504.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/45a6db20034f2195227c34f0ab8b90e1f86bfa3b/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift#L31">PurchasesOrchestrator</a></figcaption></figure></div><p>This 2000-line behemoth is the main engine driving $10bn of transactions. </p><h4>Making the Purchase via StoreKit </h4><p>Let&#8217;s follow along to the <strong>purchase()</strong> function.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p0LX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p0LX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 424w, https://substackcdn.com/image/fetch/$s_!p0LX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 848w, https://substackcdn.com/image/fetch/$s_!p0LX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 1272w, https://substackcdn.com/image/fetch/$s_!p0LX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p0LX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png" width="1456" height="809" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:809,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1038741,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.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_!p0LX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 424w, https://substackcdn.com/image/fetch/$s_!p0LX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 848w, https://substackcdn.com/image/fetch/$s_!p0LX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.png 1272w, https://substackcdn.com/image/fetch/$s_!p0LX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdd0eccd-9aba-49f5-a9ab-09b9ca9cd107_2468x1372.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>There&#8217;s a few more interesting SDK design lessons to learn here:</p><ol><li><p>Log everything on the critical path to catch errors and hit that <a href="https://www.revenuecat.com/why-revenuecat/">99.99% SLA</a>. </p></li><li><p>We should also profile times and performance for our metrics.</p></li><li><p>Handle both <a href="https://www.revenuecat.com/blog/engineering/storekit-1-deprecation-wwdc-2024-recap/">legacy SK1</a> and SK2 transactions, while abstracting this choice away from the developer. </p></li><li><p>Wrap <strong>#available</strong> conditionals around APIs younger than the minimum deployment target to ensure backwards compatibility. </p></li><li><p>Enable users to test the flow without spending money using <strong>simulatedStoreProduct</strong>. </p></li></ol><p>Let&#8217;s follow the StoreKit 2 version. </p><p>After a brief time-skip as the SDK passes through more layers of logging, profiling, caching, and error handling, we land on the function that actually calls into Apple&#8217;s StoreKit API: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cRZy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cRZy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 424w, https://substackcdn.com/image/fetch/$s_!cRZy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 848w, https://substackcdn.com/image/fetch/$s_!cRZy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 1272w, https://substackcdn.com/image/fetch/$s_!cRZy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cRZy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png" width="1456" height="607" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:607,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:546732,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.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_!cRZy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 424w, https://substackcdn.com/image/fetch/$s_!cRZy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 848w, https://substackcdn.com/image/fetch/$s_!cRZy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.png 1272w, https://substackcdn.com/image/fetch/$s_!cRZy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1002be-757c-4edf-98fe-1e2d190912b7_2024x844.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>Notice that SDKs don&#8217;t get the luxury of ignoring new platforms like VisionOS: you need to ensure all your APIs work with all platforms by the time it&#8217;s out of Beta!</p><p>This presents the modal payment window for an in-app purchase or subscription. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2FUl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2FUl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 424w, https://substackcdn.com/image/fetch/$s_!2FUl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 848w, https://substackcdn.com/image/fetch/$s_!2FUl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 1272w, https://substackcdn.com/image/fetch/$s_!2FUl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2FUl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png" width="1304" height="1048" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1048,&quot;width&quot;:1304,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:462716,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.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_!2FUl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 424w, https://substackcdn.com/image/fetch/$s_!2FUl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 848w, https://substackcdn.com/image/fetch/$s_!2FUl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.png 1272w, https://substackcdn.com/image/fetch/$s_!2FUl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49409627-5a0b-4b22-b42f-f7f451f08fcd_1304x1048.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>The purchase is complete! But the orchestration journey is not over.</p><h4>Handling the transaction and delegating to services </h4><p>Apple has now processed the transaction. </p><p>But what happens when the user upgrades to a new device? What about if they move over to Android, or your web app? How do we know they aren&#8217;t fraudulently accessing your content via a jailbroken device?</p><p>These problems of <strong>entitlements</strong> and <strong>receipt validation</strong> are two of the major reasons that payments is a headache. </p><p>To kick off the second half, after calling <strong>purchase(sk2Product&#8230;)</strong>, the orchestrator manages the result of the StoreKit purchase action </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Xoj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Xoj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 424w, https://substackcdn.com/image/fetch/$s_!8Xoj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 848w, https://substackcdn.com/image/fetch/$s_!8Xoj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 1272w, https://substackcdn.com/image/fetch/$s_!8Xoj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Xoj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png" width="1456" height="999" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:999,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:978433,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.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_!8Xoj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 424w, https://substackcdn.com/image/fetch/$s_!8Xoj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 848w, https://substackcdn.com/image/fetch/$s_!8Xoj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.png 1272w, https://substackcdn.com/image/fetch/$s_!8Xoj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe832bc2d-8867-468a-b0ac-efd146337d5b_2256x1548.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>This does several critical things:</p><ol><li><p>Verifies this transaction using the StoreKit transaction listener, another friendly wrapper around StoreKit APIs.</p></li><li><p>If the transaction returns, it hands off the data to other SDK services. </p></li><li><p>Tracks and logs a lot more stuff.</p></li><li><p>Finally, returns the contents of the completion block (or throws an error).</p></li></ol><p>It&#8217;s used as a helper function here, but the StoreKit listener also runs in the background to catch transactions that happen outside this explicit <strong>purchase()</strong> call, such as family sharing, renewals, or restoring purchases.</p><h4>Handoff to the services layer</h4><p>As our time with the orchestrator comes to a close, <strong>handlePurchasedTransaction </strong>cleans up paywalls, tokens, and contexts, wraps up a <strong>PurchasedTransactionData</strong> object, and hands off to more services:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bGkG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bGkG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 424w, https://substackcdn.com/image/fetch/$s_!bGkG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 848w, https://substackcdn.com/image/fetch/$s_!bGkG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 1272w, https://substackcdn.com/image/fetch/$s_!bGkG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bGkG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png" width="1456" height="1132" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1132,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:975978,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.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_!bGkG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 424w, https://substackcdn.com/image/fetch/$s_!bGkG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 848w, https://substackcdn.com/image/fetch/$s_!bGkG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.png 1272w, https://substackcdn.com/image/fetch/$s_!bGkG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3b58b71-ac5e-4554-81f2-b7d792caabed_2160x1680.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>Let&#8217;s take a look at two of these critical services now. </p><div><hr></div><h2>The Service Layer</h2><p>There&#8217;s two important services used here to finalise a purchase: <strong>TransactionPoster</strong> and <strong>CustomerInfoManager</strong>.</p><h4>TransactionPoster and backend validation </h4><p>TransactionPoster itself, as a relatively high-level specialised service, further builds on top of several lower-level dependencies.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oi7c!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oi7c!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 424w, https://substackcdn.com/image/fetch/$s_!oi7c!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 848w, https://substackcdn.com/image/fetch/$s_!oi7c!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 1272w, https://substackcdn.com/image/fetch/$s_!oi7c!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oi7c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png" width="1456" height="776" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:776,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:493366,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.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_!oi7c!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 424w, https://substackcdn.com/image/fetch/$s_!oi7c!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 848w, https://substackcdn.com/image/fetch/$s_!oi7c!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.png 1272w, https://substackcdn.com/image/fetch/$s_!oi7c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff88b0cb7-0319-45da-b5d1-5c5d2ee52d9b_1584x844.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/45a6db20034f2195227c34f0ab8b90e1f86bfa3b/Sources/Purchasing/Purchases/TransactionPoster.swift#L58">TransactionPoster</a></figcaption></figure></div><p>After <strong>PurchasesOrchestrator</strong> finishes a transaction, it asks <strong>TransactionPoster</strong> to send StoreKit receipts to the RevenueCat backend, which then <a href="https://medium.com/revenuecat-blog/dissecting-an-app-store-receipt-b1e9c5136482">validates the receipt</a>, verifies the customer&#8217;s subscription, and returns confirmation to the SDK.  </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-1Fq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-1Fq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 424w, https://substackcdn.com/image/fetch/$s_!-1Fq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 848w, https://substackcdn.com/image/fetch/$s_!-1Fq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 1272w, https://substackcdn.com/image/fetch/$s_!-1Fq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-1Fq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png" width="1456" height="1142" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1142,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:990760,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.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_!-1Fq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 424w, https://substackcdn.com/image/fetch/$s_!-1Fq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 848w, https://substackcdn.com/image/fetch/$s_!-1Fq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.png 1272w, https://substackcdn.com/image/fetch/$s_!-1Fq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5230d82f-764c-47a0-a67d-b48ad1604c41_2142x1680.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>Pretty much every one of these functions calls into of the dependencies above: </p><ul><li><p><strong>product(with: productIdentifier)</strong> calls into <strong>productsManager</strong> to the available products.</p></li><li><p><strong>postReceipt()</strong> tells the <strong>backend</strong> to actually send the receipt to RevenueCat servers.</p></li><li><p><strong>handleReceiptPost()</strong> calls into <strong>operationDispatcher</strong> to jump to the main actor and performing the callback thread-safely.</p></li></ul><h4>CustomerInfoManager and offline correctness </h4><p><strong>CustomerInfoManager</strong> is where the entitlements of the user live. This is one of the most important services, because it dictates whether a user can access paywalled content in your app, or not. It&#8217;s really important to get this right. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G3sY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G3sY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 424w, https://substackcdn.com/image/fetch/$s_!G3sY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 848w, https://substackcdn.com/image/fetch/$s_!G3sY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!G3sY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G3sY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png" width="1456" height="731" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:731,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:780355,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.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_!G3sY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 424w, https://substackcdn.com/image/fetch/$s_!G3sY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 848w, https://substackcdn.com/image/fetch/$s_!G3sY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!G3sY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9784eed-a541-43b0-a3a9-e2463f4de6a4_2296x1152.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/45a6db20034f2195227c34f0ab8b90e1f86bfa3b/Sources/Identity/CustomerInfoManager.swift#L18">CustomerInfoManager</a></figcaption></figure></div><p>Once the <strong>PurchasesOrchestrator</strong> has posted the receipt, it updates the cache on <strong>CustomerInfoManager</strong> to ensure entitlements are readily available, both for speed of retrieval and to ensure it still works offline.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!17vm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!17vm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 424w, https://substackcdn.com/image/fetch/$s_!17vm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 848w, https://substackcdn.com/image/fetch/$s_!17vm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!17vm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!17vm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png" width="1456" height="783" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:783,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:708890,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.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_!17vm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 424w, https://substackcdn.com/image/fetch/$s_!17vm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 848w, https://substackcdn.com/image/fetch/$s_!17vm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!17vm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb31689-05c6-4144-b70b-40fe1b98d88a_2142x1152.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> In the end, this more or less lands in UserDefaults. Nothing is ever magic. </p><p>It&#8217;s really, really, really important that an SDK works in all sorts of conditions, such as poor network, low power mode, and offline. </p><p>One of the <strong>CustomerInfoManager</strong> dependencies, <strong>OfflineEntitlementsManager</strong>, acts as the fallback; computing customer info from locally-persisted SK2 purchase history and cached information on products and entitlements. </p><p>This is an instance where you can influence API design to improve developer experience: giving devs control over how they want to fetch customer info data, with a choice between speed and correctness.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nUqM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nUqM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 424w, https://substackcdn.com/image/fetch/$s_!nUqM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 848w, https://substackcdn.com/image/fetch/$s_!nUqM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!nUqM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nUqM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png" width="1456" height="949" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22371816-4451-4543-b187-a384b532c900_1834x1196.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:949,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:678651,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.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_!nUqM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 424w, https://substackcdn.com/image/fetch/$s_!nUqM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 848w, https://substackcdn.com/image/fetch/$s_!nUqM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!nUqM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22371816-4451-4543-b187-a384b532c900_1834x1196.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><div><hr></div><h2>The Infrastructure Layer </h2><p>With a layered architecture SDK like this, it&#8217;s very easy to spend 50,000 words recursively going into every nook and cranny, but I think this is a really good time to take a break here. </p><p>Ok, fine, I&#8217;ll talk about <strong>Backend</strong> really quickly because it appears <em>everywhere</em>. </p><p>When you want to call something on the backend, you call something like: <strong>backend.offerings.getOfferings()</strong> or <strong>backend.identity.logIn()</strong>. This is because Backend serves as a neatly name-spaced API gateway. A composition surface for all of the network requests you might need.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a2c4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a2c4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 424w, https://substackcdn.com/image/fetch/$s_!a2c4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 848w, https://substackcdn.com/image/fetch/$s_!a2c4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 1272w, https://substackcdn.com/image/fetch/$s_!a2c4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a2c4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png" width="1316" height="932" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:932,&quot;width&quot;:1316,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:471227,&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://blog.jacobstechtavern.com/i/183560520?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.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_!a2c4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 424w, https://substackcdn.com/image/fetch/$s_!a2c4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 848w, https://substackcdn.com/image/fetch/$s_!a2c4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.png 1272w, https://substackcdn.com/image/fetch/$s_!a2c4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff73bad46-ffff-44a6-acec-2def46e4cadb_1316x932.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"><a href="https://github.com/RevenueCat/purchases-ios/blob/45a6db20034f2195227c34f0ab8b90e1f86bfa3b/Sources/Networking/Backend.swift#L16">Backend</a></figcaption></figure></div><p>This low-level infra isn&#8217;t immune to containing various dependencies: a collection of all the different APIs and endpoints the SDK can talk to, as well as a BackendConfiguration object containing services like <strong>HTTPClient</strong>,<strong> </strong>which wraps <strong>URLSession</strong> and handles ETag caching, response verification, request signing, retrying, and serialisation with operation queues. </p><p>Naturally, the level of logging and profiling required on the network layer is more important than ever.</p><div><hr></div><h2>Last Orders </h2><p>The RevenueCat iOS SDK creates a reliable and easy-to-use way to handle a deeply complex field like payments, and has helped process $10bn in revenue (and counting!) for developers across the world. Following through the payment orchestration logic in this battle-tested project teaches us a great deal about SDK design. </p><ul><li><p>Backwards compatibility is a first-class consideration.</p></li><li><p>You need a really strong handle on error handling, logging, and profiling.</p></li><li><p>The APIs need to be dead simple, with  progressive disclosure of advanced use cases via confirmation.</p></li><li><p>Your dependency graph needs to be layered thoughtfully, with more complex services relying on low-level core infrastructure. </p></li><li><p>Your code has to work on a wide range of platforms and OS version.</p></li><li><p>You need to work in imperfect device conditions, including offline.</p></li></ul><p>I didn&#8217;t cover this anywhere in the low-level code, but one more critical design consideration when building an SDK is that <strong>it should be invisible</strong>: there when you need it, but otherwise negligible in terms of its impact on performance characteristics like app launch time, CPU load, disk and network I/O, and app size. </p><p>Finally, because an SDK is often a piece of critical infrastructure, you also need to <strong>treat tests with the same care as production code</strong>.</p><blockquote><h5><strong>Sponsored Link</strong> </h5><h4><strong><a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">RevenueCat Paywalls: Build &amp; iterate subscription flows faster</a></strong></h4><p>RevenueCat Paywalls just added a steady stream of new features: more templates, deeper customization, better previews, and new promo tools. <a href="https://www.revenuecat.com/blog/engineering/paywalls-changelog/?utm_medium=sponsored&amp;utm_source=JacobsTechTavern&amp;utm_campaign=general_sponsorship&amp;utm_content=paywalls">Check the Paywalls changelog</a> and keep improving your subscription flows as new capabilities ship.</p></blockquote><div><hr></div><blockquote><p><em>If you liked my post, subscribe free to join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week.</em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[10 techniques to pass 90% of algorithmic interviews ]]></title><description><![CDATA[Learnings from my long-overdue LeetCode grind]]></description><link>https://blog.jacobstechtavern.com/p/rage-against-the-leetcode</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/rage-against-the-leetcode</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 06 Jan 2026 16:01:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!V4B4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.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_!V4B4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V4B4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!V4B4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!V4B4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!V4B4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!V4B4!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:1991651,&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://blog.jacobstechtavern.com/i/181052142?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!V4B4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!V4B4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!V4B4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!V4B4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.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>In my 10ish years of experience (always round up), I&#8217;ve so far managed to deftly flit between startups with under-developed hiring processes. I&#8217;m a master of slipping through the cracks and convincing entrepreneurs that I&#8217;m hot sh*t at iOS.<br><br>What I&#8217;m trying to say is, I&#8217;ve managed to avoid actually learning how to answer algorithmic technical interview questions, a.k.a. <strong>LeetCode</strong>.</p><p>Many people consider LeetCode to be the <em>&#8220;<a href="https://news.ycombinator.com/item?id=36654947">highest ROI activity in tech</a>&#8221;</em>. This is because it unlocks the door to big American tech companies that typically pay way better than everyone else. </p><p>Why does this filter have zero bearing on day-to-day work in a tech job?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Q8a3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Q8a3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 424w, https://substackcdn.com/image/fetch/$s_!Q8a3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 848w, https://substackcdn.com/image/fetch/$s_!Q8a3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 1272w, https://substackcdn.com/image/fetch/$s_!Q8a3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Q8a3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png" width="1190" height="402" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:402,&quot;width&quot;:1190,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:67209,&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://blog.jacobstechtavern.com/i/181052142?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.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_!Q8a3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 424w, https://substackcdn.com/image/fetch/$s_!Q8a3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 848w, https://substackcdn.com/image/fetch/$s_!Q8a3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.png 1272w, https://substackcdn.com/image/fetch/$s_!Q8a3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2af65237-0791-44f4-93f0-5e50a341ef2c_1190x402.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><figcaption class="image-caption"><a href="https://x.com/iamdevloper/status/986193182936485888">I am devloper on Twitter</a></figcaption></figure></div><p>And why do these companies all support have the same hiring process? </p><ol><li><p><strong>LeetCode enforces a minimum competency bar.</strong><br>LeetCode interviews help avoid &#8220;false positives&#8221;. Big tech is optimising to avoid bad hires, <a href="https://x.com/mxcl/status/608682016205344768?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E608682016205344768%7Ctwgr%5Efa64f8c7c90f3d5563c82db1233388aef96f3f59%7Ctwcon%5Es1_&amp;ref_url=https%3A%2F%2Fwww.redditmedia.com%2Fmediaembed%2F39d0u1%2F%3Fresponsive%3Dtrueis_nightmode%3Dtrue">at the expense of rejecting some good candidates</a>. LeetCode provides a very standardised way to discover if a candidate can perform a moderately complex coding task under time pressure. </p></li><li><p><strong>LeetCode selects for people willing to endure an arbitrary grind.<br></strong><em><strong>(</strong>You aren&#8217;t meant to say this bit out loud).</em> <br>In economics, LeetCode is called &#8220;costly signalling&#8221;. People who grind LeetCode to land a job are probably conscientious, have a high tolerance for bureaucracy, and will happily sacrifice their free time for career advancement. </p></li></ol><p>As big tech hiring scaled up, and everyone wanted to cargo-cult Google, the mythical &#8220;algorithmic challenge&#8221; devolved into a cookie-cutter exercise, where candidates pretend to be a secret genius improvising a novel solution as they go*.</p><blockquote><p><em>*Top tip: don&#8217;t actually refer to this as &#8220;kayfabe&#8221; during your LeetCode interview&#8221;</em></p></blockquote><p>LeetCode was a moderately embarrassing weakness I&#8217;d failed to address, until now.</p><p>It wasn&#8217;t for lack of trying! </p><p>I halfheartedly started LeetCoding a few years ago, but after sinking in a few commutes into Two Sum and Valid Parenthesis, decided it&#8217;d be more interesting to focus on my blog. </p><p>In retrospect, <a href="https://blog.jacobstechtavern.com">perhaps that was a good decision</a>.</p><div><hr></div><p>I&#8217;m meandering. <em>&#8220;Can you get to the damn point?&#8221;</em>, I hear you ask from the future.</p><p>Big tech devs (mostly) aren&#8217;t geniuses. They&#8217;re pattern-recognition machines.</p><p>LeetCode is purely an exercise in pattern recognition.</p><p>The same ~10 patterns, over and over. In various configurations. </p><p>That&#8217;s why I can legitimately tell you that there&#8217;s 10 techniques that will carry you through the <em>vast</em> majority of LeetCode interviews. </p><p>You can take my word for this as well, because I&#8217;ve got a 100% pass rate on the 4-5 legit LeetCode interview loops I&#8217;ve actually done, and I will <em>not</em> be updating this if things go badly with Snap tomorrow.</p><p>Okay so <strong>what&#8217;s on the menu today?</strong> </p><ul><li><p>I&#8217;m going to demonstrate the 10 techniques that virtually every LeetCode question maps onto. </p></li><li><p>For each technique, I&#8217;ll show you a bona-fide LeetCode question that applies it, alongside my actual diary notes I wrote while trying them for the first time, so you don&#8217;t feel so alone when you do it. </p></li><li><p>Finally, I&#8217;ll give you my rough field-guide for staying sane in The Grind&#8482;. To be honest, I would recommend reading this first, because then you feel less bad during the rest of the article.  </p></li></ul><div><hr></div><h2>Contents</h2><ul><li><p><strong><a href="https://blog.jacobstechtavern.com/i/181052142/the-techniques">The 10 Techniques</a></strong></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/hashmaps">Hashmaps</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-ransom-note">LeetCode Diary: #383 Ransom Note</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/two-pointers">Two pointers</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-linked-list-cycle">LeetCode Diary: Linked List Cycle</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/sliding-windows">Sliding windows</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-longest-substring-without-repeating-characters">LeetCode Diary: #3 Longest Substring without Repeating Characters</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/stack-based-and-queue-based-parsing">Stack-based and queue-based parsing </a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-evaluate-reverse-polish-notation">LeetCode Diary: #150 Evaluate Reverse Polish Notation</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/binary-search">Binary search</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-binary-search">LeetCode Diary: #704 Binary Search</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/trees-recursion-and-dfs">Trees, Recursion and DFS</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-validate-binary-search-tree">LeetCode Diary: #98 Validate Binary Search Tree</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/graphs-traversal-and-bfs">Graphs, Traversal, and BFS</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-number-of-islands">LeetCode Diary: #200 Number of Islands</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/backtracking">Backtracking</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-permutations">LeetCode Diary: #46 Permutations</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/sort-and-sweep">Sort-and-sweep</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-insert-interval">LeetCode Diary: #57 Insert Interval</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/dynamic-programming">Dynamic Programming</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-coin-change">LeetCode Diary:</a><strong><a href="https://blog.jacobstechtavern.com/i/181052142/my-leetcode-diary-coin-change"> #322 Coin Change</a></strong></p></li></ul></li></ul></li><li><p><strong><a href="https://blog.jacobstechtavern.com/i/181052142/staying-sane-in-the-grind">Staying sane in The Grind&#8482;</a></strong></p></li><li><p><strong><a href="https://blog.jacobstechtavern.com/i/181052142/last-orders">Last Orders</a></strong></p></li></ul><blockquote><p><em>This post is super long, so your email client may cut it off. Read on my website here:</em> </p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/p/rage-against-the-leetcode&quot;,&quot;text&quot;:&quot;Read on my website&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.jacobstechtavern.com/p/rage-against-the-leetcode"><span>Read on my website</span></a></p><div><hr></div><h2>The 10 Techniques </h2><h3>Hashmaps </h3><p>Hashmaps (a.k.a. Dictionaries) are the basic cheat code for any algorithmic question, because they offer O(1) lookups (a.k.a. <a href="https://en.wikipedia.org/wiki/Time_complexity">constant time complexity</a>)*. </p><p>Virtually every time I&#8217;ve done a real-life LeetCode interview, I&#8217;ll write a solution that&#8217;s messy, inefficient, but works. After verifying my code, I&#8217;ll be asked &#8220;how efficient is that?&#8221; and check the time complexity, and be gently prompted to make it more efficient**. </p><p>This is usually code for &#8220;use a hash map&#8221;. </p><blockquote><p><em>*Sets also have constant time lookups, but you&#8217;ll use those less often.</em></p><p><em>**If you&#8217;re a better candidate than me, you can do this without being asked.</em></p></blockquote><p>Hashmap problems take many forms. You might build a dictionary to count the frequencies of each character in a paragraph. You might use a hashmap to cache values, and efficiently check if a value has already been computed or not. You might  do something clever with keys, by computing a value that you&#8217;ll need later, &#224;-la the O.G. <a href="https://leetcode.com/problems/two-sum/description/">Two Sum</a> problem. </p><p>The core pattern is making one pass through the input data to construct the hashmap, then another to query whatever you need. Sometimes, you can do both at the same time and exit early. </p><p>That was a lot of words. If you&#8217;re a LeetCode novice, I hope I haven&#8217;t scared you off. Here&#8217;s a nice LC Easy to cleanse the palette. </p><h4>My LeetCode Diary: #383 <a href="https://leetcode.com/problems/ransom-note/description/">Ransom Note</a> </h4><p>Surprisingly, I&#8217;m actually pretty good at traversing a collection and populating a dictionary. This might be the first LeetCode problem I found, dare I say, <em>fun</em>.</p><p>This is the classic hashmap approach, iterating through to count the characters, and traversing again to decrement and check you have enough characters for the target.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XTap!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XTap!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 424w, https://substackcdn.com/image/fetch/$s_!XTap!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 848w, https://substackcdn.com/image/fetch/$s_!XTap!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 1272w, https://substackcdn.com/image/fetch/$s_!XTap!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XTap!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png" width="1456" height="1112" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1112,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:250444,&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://blog.jacobstechtavern.com/i/181052142?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.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_!XTap!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 424w, https://substackcdn.com/image/fetch/$s_!XTap!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 848w, https://substackcdn.com/image/fetch/$s_!XTap!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.png 1272w, https://substackcdn.com/image/fetch/$s_!XTap!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5982fc-e44c-49ff-85d4-8ee08e4c1880_1624x1240.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 aren&#8217;t limited to integers and characters in your hashmap either. </p><p>You can store Linked List or Tree nodes in a dictionary. This is often the solution to  any &#8220;make a data structure with O(1) reads and writes&#8221; problem (see <a href="https://leetcode.com/problems/lru-cache/">LRU Cache</a>). </p><p>You can also place Graph edges into a dictionary for a topological sort (see <a href="https://leetcode.com/problems/course-schedule/description/">Course Schedule</a>), or just track &#8220;visited&#8221; nodes for a depth-first search (see <a href="https://leetcode.com/problems/clone-graph/description/">Clone Graph</a>).</p><div><hr></div><h3>Two pointers </h3><p>This is probably my favourite technique, because I feel dead smart every time I use it. </p><blockquote><p><em>Upgrade to unlock this article, plus much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/rage-against-the-leetcode">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[🎄 I just gifted you 14 days' membership ]]></title><description><![CDATA[Thanks for being a paid member &#127873;]]></description><link>https://blog.jacobstechtavern.com/p/i-just-gifted-you-14-days-membership</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/i-just-gifted-you-14-days-membership</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Fri, 19 Dec 2025 17:00:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!V4B4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8fd643d-5cad-4e62-b637-194fda723d47_1680x1200.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Seasons greetings,</p><p>I&#8217;ve been pretty flat out this month grinding interview loops, so haven&#8217;t had much time to write. Plus, the kids are off school &amp; nursery over the Christmas break, and I am told Christmas is a good time for family and stuff.</p><p>Hence, I&#8217;m taking a well-deserved 2-week break over Christmas.</p><p>To soften the blow, <strong>I gifted all my paid subscriber&#8230;</strong></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/i-just-gifted-you-14-days-membership">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Copy-on-write teaches you EVERYTHING about Swift Internals 🐮]]></title><description><![CDATA[isKnownUniquelyReferenced through the standard library, compiler, and runtime]]></description><link>https://blog.jacobstechtavern.com/p/copy-on-write-swift-internals</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/copy-on-write-swift-internals</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Mon, 15 Dec 2025 16:01:29 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!PKCV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.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_!PKCV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PKCV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!PKCV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!PKCV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!PKCV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PKCV!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4428875,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PKCV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!PKCV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!PKCV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!PKCV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7f613f8c-801d-45d0-a449-8de15596b5a4_1680x1200.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>There is a global function in Swift that, when you fully understand it, will teach you everything you need to know about Swift internals. </p><p>You&#8217;ll never guess what it is, because I guarantee you&#8217;ve used it less than 3 times in the real world, if you&#8217;ve even heard of it.</p><p><strong>isKnownUniquelyReferenced()</strong>. </p><p>If you know, you know: this function powers the <strong>copy-on-write</strong> optimisation (a.k.a. CoW, a.k.a.k.a. &#128046;). </p><p>It pretty much only ever comes up if a) you&#8217;re a library author, or b) you&#8217;re interviewing someone and want to rate their power level when it comes to Swift internals*</p><blockquote><p><em>*I never let interviews get to this point, because I <a href="https://blog.jacobstechtavern.com/p/swift-reference-counting">burn 45 minutes responding to their first question about weak references</a>.</em> </p></blockquote><p>I wanted to understand how this function worked, and little did I know that it would take me on an odyssey through every single layer and sublayer of the Swift source code. Seriously. Every layer. </p><p>As it happens, it&#8217;s pretty much the perfect candidate for doing this. <a href="https://blog.jacobstechtavern.com/p/swift-source-code">type(of:) comes close</a>, but doesn&#8217;t quite stick the landing in as satisfying a way. </p><p>Will learning all this make your hairline recede another inch? Yes. </p><p>Are you going to come on a fun journey to learn Swift Internals&#8482;? Also yes.</p><p>Let&#8217;s work through the various sublayers of the p&#822;l&#822;a&#822;n&#822;e&#822;t&#822; <a href="https://github.com/swiftlang/swift">Swift Source Code</a> and discover once and for all how isKnownUniquelyReferenced works. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EtLW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EtLW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!EtLW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!EtLW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!EtLW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EtLW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:135226,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EtLW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 424w, https://substackcdn.com/image/fetch/$s_!EtLW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 848w, https://substackcdn.com/image/fetch/$s_!EtLW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!EtLW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17defc1c-ee2d-4efc-ba76-a234bbd42ad5_1920x1080.jpeg 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">I kind of wanted to do a Donkey Kong Bananza bit with each section representing a different sublayer but I truly did not think enough people would get the reference. </figcaption></figure></div><h1>Journey to the centre of the &#128046; </h1><h4>(yes we&#8217;re really going through all these)</h4><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/what-is">What is &#128046;?</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/value-and-reference-semantics">Value and reference semantics</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/in-the-swift-standard-library">&#128046; In the Swift Standard Library</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/implementing">Implementing &#128046;</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/the-swift-standard-library">The Swift Standard Library</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/builtins">Builtins</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/interlude-the-swift-compiler">(Interlude) The Swift Compiler</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/our-isknownuniquelyreferenced-compass">Our isKnownUniquelyReferenced Compass</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/the-abstract-syntax-tree">The Abstract Syntax Tree</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/builtins-on-the-ast">Builtins on the AST</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/synthesising-a-builtin-function">Synthesising a Builtin Function</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/the-builtin-module">The Builtin Module</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/ast-recap">AST Recap</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/swift-intermediate-language">Swift Intermediate Language</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/llvm-intermediate-representation">LLVM Intermediate Representation</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/the-swift-runtime">The Swift Runtime</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/checking-the-docs">Checking the Docs</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/swift-object">SwiftObject</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/heapobject">HeapObject</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/swiftshims">SwiftShims</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/the-isknownuniquelyreferenced-meme">The </a><strong><a href="https://blog.jacobstechtavern.com/i/181220219/the-isknownuniquelyreferenced-meme">isKnownUniquelyReferenced</a></strong><a href="https://blog.jacobstechtavern.com/i/181220219/the-isknownuniquelyreferenced-meme"> Meme</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/181220219/last-orders">Last Orders</a></p></li></ul><div><hr></div><h1><strong>What is &#128046;?</strong></h1><p>For anyone who hasn&#8217;t brushed up on their interview prep recently: </p><p>&#128046; optimises the performance of a Swift struct to get the best of both worlds: </p><ul><li><p>easy-to-reason-about value semantics.</p></li><li><p>low memory overhead from reference semantics.</p></li></ul><p><em>&#8220;Uhh, I just said I <strong>wasn&#8217;t</strong> doing interviews, can you not drop terms like &#8220;reference semantics&#8221; as if I remember what they are?&#8221; </em>I hear you say from the future.</p><p>Right. Sorry. </p><div><hr></div><h2><strong>Value and reference semantics</strong></h2><p><strong>Value semantics</strong> = copies are independent entities </p><p><strong>Reference semantics</strong> = copies point to the same underlying memory on the heap</p><p>structs that utilise &#128046; store their data in a memory buffer on the heap.</p><p>When the struct is copied, all the properties are copied, including the 64-bit pointer to the backing data, referencing the memory address <strong>0x00000000d34db33f</strong>. </p><p>This is a <em>shallow copy</em>. Each copy of the reference still points to the same underling memory. This underlying memory is shared. <em>This</em> is reference semantics.</p><p>When the value of the data on a copy of a &#128046; struct changes, value semantics kick in.</p><p>The struct allocates a new buffer of memory on the heap, copies the updated data there, then points at the new buffer. A <em>deep copy</em>. It leaves the original memory block, and other instances of the struct pointing to it, unchanged.</p><div><hr></div><h2><strong>&#128046; In the Swift Standard Library</strong></h2><p>Many fundamental types in the Swift Standard Library utilise the &#128046; (copy-on-write) optimisation:</p><ul><li><p><a href="https://github.com/swiftlang/swift/blob/main/stdlib/public/core/Array.swift">Array</a></p></li><li><p><a href="https://github.com/swiftlang/swift/blob/main/stdlib/public/core/Set.swift">Set</a></p></li><li><p><a href="https://github.com/swiftlang/swift/blob/main/stdlib/public/core/Dictionary.swift">Dictionary</a></p></li><li><p><a href="https://github.com/swiftlang/swift/blob/main/stdlib/public/core/String.swift">String</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/p/data-deep-dive">Data</a> (actually an impostor from Foundation, but it&#8217;s one of the gang).</p></li></ul><p>When using these data structures in your code, or even types that contain them, you reap the benefits of the underlying &#128046; optimisation for free. </p><p>But it&#8217;s possible to implement &#128046; in your own types, too!</p><div><hr></div><h1><strong>Implementing &#128046;</strong></h1><p>Very senior iOS engineers will tell you how you can implement your own types that utilise &#128046;. Check out this sample robbed straight from Apple&#8217;s <a href="https://github.com/apple/swift/blob/main/docs/OptimizationTips.rst#advice-use-copy-on-write-semantics-for-large-values">Swift Optimisation Tips</a>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vVll!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vVll!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 424w, https://substackcdn.com/image/fetch/$s_!vVll!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 848w, https://substackcdn.com/image/fetch/$s_!vVll!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!vVll!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vVll!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png" width="1240" height="1196" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1196,&quot;width&quot;:1240,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:226666,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.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_!vVll!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 424w, https://substackcdn.com/image/fetch/$s_!vVll!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 848w, https://substackcdn.com/image/fetch/$s_!vVll!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!vVll!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbe53308-29d0-4f96-b41e-8ae323c3890b_1240x1196.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>In short, you place your struct, <strong>T</strong>, in <strong>Box</strong>. </p><p><strong>Box</strong> wraps <strong>T</strong> in a reference, <strong>Ref</strong>, placing the structure on the heap.</p><p>You can <em>read</em> the value inside <strong>Box</strong> trivially.</p><p>When you <em>write</em> the value, we check if the memory inside <strong>Ref</strong> is uniquely referenced, that is, if there is <strong>only one pointer</strong> to this instance. If it is unique, the value mutates in-place. Otherwise, the heap memory buffer under <strong>Ref</strong> is copied into a new address before mutation. The <strong>Ref</strong> pointer inside <strong>Box</strong> changes to point to this new address.</p><blockquote><p><em>This illustrative example shows how <strong>isKnownUniquelyReferenced</strong> can be used to implement &#128046;, but it&#8217;s kind</em> <em>of sh*tty for real life code: you&#8217;re polluting your type with slower reference access semantics to make copying a bit more efficient. </em></p><p><em>It&#8217;s only a good idea when copying is expected and there is enough memory that it makes sense to place it on the heap.</em></p></blockquote><p>A mysterious function, <strong>isKnownUniquelyReferenced</strong>, is the secret sauce that makes this optimisation possible.</p><blockquote><p><em>As it turns out, it&#8217;s fucking mysterious, because I originally spent about 3 weeks traversing megabytes of C++ (in 2023, before AI tooling could even touch this kind of task) to understand what the hell it was doing.</em> </p></blockquote><div><hr></div><h1><strong>The Swift Standard Library</strong></h1><p>First things first.</p><p>Let&#8217;s download <a href="https://github.com/apple/swift">the Swift source code</a>, search for isKnownUniquelyReferenced, and take a gander at the implementation.</p><p>Or, you can just CMD+Click that bad boy in Xcode.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8nt9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8nt9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 424w, https://substackcdn.com/image/fetch/$s_!8nt9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 848w, https://substackcdn.com/image/fetch/$s_!8nt9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 1272w, https://substackcdn.com/image/fetch/$s_!8nt9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8nt9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png" width="1456" height="948" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:948,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:773599,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.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_!8nt9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 424w, https://substackcdn.com/image/fetch/$s_!8nt9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 848w, https://substackcdn.com/image/fetch/$s_!8nt9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.png 1272w, https://substackcdn.com/image/fetch/$s_!8nt9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fe13ac1-c807-4a94-b6d8-f617350c2ae1_1968x1282.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>It&#8217;s holed up in <a href="https://github.com/swiftlang/swift/blob/main/stdlib/public/core/ManagedBuffer.swift">ManagedBuffer.swift</a>, underneath the definition of <strong>ManagedBufferPointer</strong>. I don&#8217;t love putting global functions in the same file as semi-related data structures, but who am I to question the wisdom of our Cupertinoverlords?</p><p>Here&#8217;s the implementation of <strong>isKnownUniquelyReferenced</strong> I&#8217;ve been searching for in all its glory:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hl0V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hl0V!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 424w, https://substackcdn.com/image/fetch/$s_!hl0V!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 848w, https://substackcdn.com/image/fetch/$s_!hl0V!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 1272w, https://substackcdn.com/image/fetch/$s_!hl0V!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hl0V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png" width="1456" height="394" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:394,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:156456,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.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_!hl0V!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 424w, https://substackcdn.com/image/fetch/$s_!hl0V!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 848w, https://substackcdn.com/image/fetch/$s_!hl0V!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.png 1272w, https://substackcdn.com/image/fetch/$s_!hl0V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1b7e0a38-853a-4387-b8a2-34107ba1d62a_1816x492.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>All in a day&#8217;s work. </p><p>I&#8217;ll head to the pub now for a well-deserved beverage. </p><div><hr></div><h1><strong>Builtins</strong></h1><p>I&#8217;ve got my beer!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!umY2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!umY2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 424w, https://substackcdn.com/image/fetch/$s_!umY2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 848w, https://substackcdn.com/image/fetch/$s_!umY2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 1272w, https://substackcdn.com/image/fetch/$s_!umY2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!umY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic" width="1456" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/118259db-8487-4d9e-a0e0-7baafc98246c.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2146953,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!umY2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 424w, https://substackcdn.com/image/fetch/$s_!umY2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 848w, https://substackcdn.com/image/fetch/$s_!umY2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 1272w, https://substackcdn.com/image/fetch/$s_!umY2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F118259db-8487-4d9e-a0e0-7baafc98246c.heic 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>Uh, I suppose I don&#8217;t have much else on.</p><p>Perhaps we can dive a little bit deeper and find out what <strong>_isUnique</strong> is doing.</p><p>Much deeper. Including <em>Builtins, The Swift Compiler, The Abstract Syntax Tree, Swift Intermediate Language, LLVM Intermediate Representation, The Swift Runtime, SwiftShims, </em>and <em>The <strong>isKnownUniquelyReferenced</strong> Meme.</em></p><div><hr></div><p>We find <strong>_isUnique</strong> defined pretty close by in Builtin.swift:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bynU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bynU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 424w, https://substackcdn.com/image/fetch/$s_!bynU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 848w, https://substackcdn.com/image/fetch/$s_!bynU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 1272w, https://substackcdn.com/image/fetch/$s_!bynU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bynU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png" width="1456" height="595" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:595,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:202957,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.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_!bynU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 424w, https://substackcdn.com/image/fetch/$s_!bynU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 848w, https://substackcdn.com/image/fetch/$s_!bynU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.png 1272w, https://substackcdn.com/image/fetch/$s_!bynU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80ee4e31-538d-41f3-afdc-97da113c2136_1528x624.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><blockquote><p><em>Loving the doc comments from Apple; let&#8217;s as an industry strive for more quantum physics references in our source code!</em></p></blockquote><p>We need to find out what this <strong>Builtin.isUnique(&amp;object)</strong> guy is trying to do.</p><p>This is where things get interesting.</p><p>We find this Builtin function defined somewhere totally different: <strong><a href="https://github.com/swiftlang/swift/blob/main/include/swift/AST/Builtins.def#L4">Builtins.def</a></strong>.</p><pre><code><code>BUILTIN_SIL_OPERATION(IsUnique, "isUnique", Special)</code></code></pre><p>Why is this located in <strong>include/AST</strong>? What is a SIL operation? Huh???</p><p>Before we can progress any further, we need to understand a bit of theory about the Swift Compiler and its dad, LLVM.</p><div><hr></div><h1><strong>(Interlude) The Swift Compiler</strong></h1><p><a href="https://www.swift.org/swift-compiler/">The Swift Compiler</a> processes Swift source code files into efficient machine code. It&#8217;s a pipeline with several Swift-specific optimisation stages.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!buND!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!buND!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 424w, https://substackcdn.com/image/fetch/$s_!buND!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 848w, https://substackcdn.com/image/fetch/$s_!buND!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 1272w, https://substackcdn.com/image/fetch/$s_!buND!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!buND!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png" width="1400" height="709" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:709,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!buND!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 424w, https://substackcdn.com/image/fetch/$s_!buND!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 848w, https://substackcdn.com/image/fetch/$s_!buND!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.png 1272w, https://substackcdn.com/image/fetch/$s_!buND!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a3f46d9-1601-47a7-b4fb-425bb8189e40_1400x709.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">Swift compilation process: Image from <a href="https://academy.realm.io/posts/tryswift-jesse-squires-contributing-open-source-swift/">Jesse Squires on Realm Academy</a></figcaption></figure></div><p>Let&#8217;s get our heads around each step in some detail:</p><ol><li><p><code>.swift</code> files are <a href="https://github.com/apple/swift/tree/main/lib/Parse">parsed</a> and turned into a data structure known as an Abstract Syntax Tree (<a href="https://github.com/apple/swift/tree/main/lib/AST">AST</a>), making it easy for algorithms to traverse.</p></li><li><p><a href="https://github.com/apple/swift/tree/main/lib/Sema">Semantic analysis</a> is performed on the AST, performing tasks such as type-checking, evaluating protocol conformance, and checking variable scopes.</p></li><li><p>Swift Intermediate Language (<a href="https://github.com/apple/swift/tree/main/lib/SIL">SIL</a>) is generated from the AST. This is a halfway point between raw Swift code and the low-level LLVM machine code.</p></li><li><p>This SIL is <a href="https://github.com/apple/swift/tree/main/lib/SILOptimizer">optimised</a> through various passes. ARC is optimised, generics are specialised, code is inlined, and devirtualization <a href="https://blog.jacobstechtavern.com/p/swift-method-dispatch">replaces dynamic dispatch</a>. </p></li><li><p>Optimised SIL is transformed into <a href="https://github.com/apple/swift/tree/main/lib/IRGen">LLVM IR</a> (Intermediate Representation). This is a high-level, language-independent kind of assembly language.</p></li><li><p>LLVM is a compiler toolchain: a frontend that processes any language into IR, and a backend that translates IR into machine instructions for any CPU. LLVM runs multiple <a href="https://github.com/apple/swift/tree/main/lib/LLVMPasses">optimisation passes</a> on IR, enhancing performance for the target CPU.</p></li><li><p>The LLVM backend transforms the LLVM IR into actual machine code and produces object <code>.o</code> files. <a href="https://blog.jacobstechtavern.com/p/reverse-engineer-private-frameworks">These contain these assembly instructions, metadata, strings, and debug information</a>.</p></li><li><p>In the final compilation step, the Linker combines various object files with libraries into a single executable, which the OS can load to run a Swift application.</p></li></ol><blockquote><p><em>I go into way more detail here:</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;dadc4471-95dd-4c64-8e96-a9d1bef18bd7&quot;,&quot;caption&quot;:&quot;The Swift language was created by Chris Lattner. Before he ran the Xcode and compiler teams at Apple, he built LLVM at age 23. That&#8217;s right. Chris is pretty much Impostor Syndrome: The Movie.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Swift Compiler &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2024-12-24T17:23:26.623Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7cbceb79-2853-49cc-8186-cb8c4528a6d5_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/the-swift-compiler&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:152589844,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:20,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><div><hr></div><h2>Our isKnownUniquelyReferenced Compass</h2><p>With that substantial segue completed, let&#8217;s return to our isKnownUniquelyReferenced deep-dive.</p><p>Now that we understand how the Swift Compiler works, we have a compass with which to orient ourselves while we dredge the depths of the Swift source code.</p><p>Instead of inspecting the 859 individual instances of isUnique we find when we CMF+F the Swift codebase, we can:</p><ol><li><p>Find out how the isUnique Builtin function is applied to the Abstract Syntax Tree.</p></li><li><p>Work out how isUnique looks when it is transformed into SIL (Swift Intermediate Language).</p></li><li><p>Determine how isUnique behaves when converted to LLVM Intermediate Representation.</p></li><li><p>Understand how these low-level instructions check whether an object is uniquely referenced.</p></li></ol><p><em>(I didn&#8217;t know this at the time, but this only took me halfway).</em></p><div><hr></div><h1><strong>The Abstract Syntax Tree</strong></h1><p>Last time we left off, we found the Builtin declaration for the isUnique method in the AST/ folder, Builtins.def:</p><pre><code><code>/// isUnique only returns true for non-null, native swift object
/// references with a strong reference count of one.
BUILTIN_SIL_OPERATION(IsUnique, "isUnique", Special)</code></code></pre><p>.def files contain exported C++ macro definitions. Think of them like header files. </p><p>The <strong>include/</strong> folder defines a public interface to the Swift Compiler, which is made available to <strong>stdlib/</strong>, the Swift Standard Library.</p><div><hr></div><h2><strong>Builtins on the AST</strong></h2><p>First, we need to work out how the Builtin isUnique function gets applied to the Abstract Syntax Tree.</p><p>We find the Builtin being synthesised here in <strong>Builtins.cpp</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lyGc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lyGc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 424w, https://substackcdn.com/image/fetch/$s_!lyGc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 848w, https://substackcdn.com/image/fetch/$s_!lyGc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 1272w, https://substackcdn.com/image/fetch/$s_!lyGc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lyGc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png" width="1456" height="828" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:828,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:296668,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.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_!lyGc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 424w, https://substackcdn.com/image/fetch/$s_!lyGc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 848w, https://substackcdn.com/image/fetch/$s_!lyGc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.png 1272w, https://substackcdn.com/image/fetch/$s_!lyGc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc510c6e1-4aab-4486-acc8-991eed2e0c7e_1716x976.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>Several methods show up here: <strong>IsUnique</strong>, <strong>IsUnique_native</strong> (with extra safety checks), and <strong>BeginCOWMutation</strong>, which the Swift Standard Library uses to internally implement &#128046; for Array, ArraySlice and ContiguousArray.</p><p>These variants all produce the same getIsUniqueOperation, hung like so many baubles onto the AST (abstract syntax tree). This itself calls <strong>getBuiltinFunction</strong> to return a pointer to a <strong>ValueDecl</strong>, which represents a function signature.</p><blockquote><p><em>You&#8217;ll notice the function signature returns Int1, a single-bit Integer. This is actually the underlying &#8220;Builtin&#8221; backing store used to implement the Swift Bool!</em></p></blockquote><div><hr></div><h2><strong>Synthesising a Builtin Function</strong></h2><p><strong>getBuiltinFunction</strong> is actually implemented in this same file:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uO9_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uO9_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 424w, https://substackcdn.com/image/fetch/$s_!uO9_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 848w, https://substackcdn.com/image/fetch/$s_!uO9_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 1272w, https://substackcdn.com/image/fetch/$s_!uO9_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uO9_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png" width="1456" height="1702" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f216f474-541c-4dba-8363-d78020239bc9_1738x2032.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1702,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:519731,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.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_!uO9_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 424w, https://substackcdn.com/image/fetch/$s_!uO9_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 848w, https://substackcdn.com/image/fetch/$s_!uO9_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.png 1272w, https://substackcdn.com/image/fetch/$s_!uO9_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff216f474-541c-4dba-8363-d78020239bc9_1738x2032.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><blockquote><p><em>With most code samples in this article, I&#8217;ve stripped out most of the code to make the key moving parts clearer, but feel free to <a href="https://github.com/apple/swift/blob/main/lib/AST/Builtins.cpp">look at the full source yourself</a>. There&#8217;s still a whole bunch of code, so I apologise for my crappy redaction. </em></p></blockquote><p>There are 3 critical steps to follow here:</p><ol><li><p>A reference to the <strong>Builtin</strong> module is retrieved from the <strong>ctx</strong>, the AST context, a repository of shared information the compiler uses to generate functions.</p></li><li><p>The generic inout parameter for <strong>isUnique</strong> and the result type, <strong>Int1</strong>, are defined here, to synthesise the signature of the <strong>FuncDecl</strong>.</p></li><li><p><strong>id</strong>, the Builtin function identifier, is used to synthesise the function declaration we want from the Builtin module, i.e. <strong>IsUnique</strong>.</p></li></ol><p>In summary, a FuncDecl, a function declaration, is synthesised. This implements the <strong>isUnique</strong> method on the Builtin module, and gets hung on the Abstract Syntax Tree.</p><p>All this processing allows Builtins to behave just like regular Swift functions.</p><div><hr></div><h2><code>T</code>he Builtin Module</h2><p>Swift&#8217;s Builtin module itself contains a set of low-level functions and operations that map to LLVM IR instructions, bypassing Swift&#8217;s ordinary type safety mechanisms.</p><p>As we have seen, Builtins are used extensively in the Standard Library for performance, but Apple doesn&#8217;t trust us mere mortals to utilise them ourselves.</p><p>To be honest, I&#8217;m 2 Hepcats deep at the pub, and I wouldn&#8217;t trust me either.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eWIz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eWIz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 424w, https://substackcdn.com/image/fetch/$s_!eWIz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 848w, https://substackcdn.com/image/fetch/$s_!eWIz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 1272w, https://substackcdn.com/image/fetch/$s_!eWIz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eWIz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic" width="1456" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f11ecbdd-d54e-4174-8243-c36871e39f55.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3002685,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eWIz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 424w, https://substackcdn.com/image/fetch/$s_!eWIz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 848w, https://substackcdn.com/image/fetch/$s_!eWIz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 1272w, https://substackcdn.com/image/fetch/$s_!eWIz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff11ecbdd-d54e-4174-8243-c36871e39f55.heic 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"><em><a href="https://gipsyhillbrew.com/product/hepcat-2">Gipsy Hill brewery</a>, pls sponsor my Substack, I&#8217;ll send you my media kit, you can pay me in beer.</em></figcaption></figure></div><div><hr></div><h2><strong>AST Recap</strong></h2><p>Let&#8217;s recap on our progress so far:</p><p><strong>isKnownUniquelyReferenced</strong> calls an internal <strong>isUnique</strong> method, which uses a <strong>Builtin</strong> method, a special low-level function implemented inside the compiler.</p><p>When Swift code compiles, <strong>Builtin.isUnique</strong> plops straight onto the AST. Indistinguishable from a run-of-the-mill Swift function. Later compilation stages treat it as such, but ultimately it maps to a dedicated instruction.</p><p>What happens to this Builtin function next? How does the resulting low-level instruction check the reference count?</p><p>To truly find out, <em>we need to go deeper</em>.</p><p>Let&#8217;s check our compass.</p><p>Next stop?</p><p>SIL.</p><div><hr></div><h1><strong>Swift Intermediate Language</strong></h1><p>After constructing an Abstract Syntax Tree and synthesising Builtin function declarations, the Swift Compiler converts your code into Swift Intermediate Language. SIL is the precursor to LLVM IR, which itself undergoes multiple very cool Swift-specific optimisation passes.</p><p>In our journey to find out how the <strong>isUnique</strong> Builtin is working, the obvious first port of call is the SIL Generation library, and specifically, <strong>SILGenBuiltin.cpp</strong>. It&#8217;s not easy to find the right function calls. Naming is a bit jank between compiler steps.</p><p>This function looks&#8230; about right:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wUoY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wUoY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 424w, https://substackcdn.com/image/fetch/$s_!wUoY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 848w, https://substackcdn.com/image/fetch/$s_!wUoY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 1272w, https://substackcdn.com/image/fetch/$s_!wUoY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wUoY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png" width="1456" height="686" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45625e60-87bc-492b-90da-525f2b562a68_1604x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213278,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.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_!wUoY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 424w, https://substackcdn.com/image/fetch/$s_!wUoY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 848w, https://substackcdn.com/image/fetch/$s_!wUoY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.png 1272w, https://substackcdn.com/image/fetch/$s_!wUoY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45625e60-87bc-492b-90da-525f2b562a68_1604x756.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><blockquote><p><em>Only 10 lines this time. I&#8217;m learning. As before, I&#8217;ve left out numerous lines of C++ assertions (mostly nullability checks) to make the code easier to follow.</em></p></blockquote><p>This <strong>emitBuiltinIsUnique</strong> method, naturally, emits the SIL instructions for the Builtin function <strong>isUnique</strong>. </p><p>Following <strong>createIsUnique</strong> further, we find it defined in <strong>include/</strong> inside <strong>SILBuilder.h</strong>, which acts as the public interface for SIL:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRhI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRhI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 424w, https://substackcdn.com/image/fetch/$s_!LRhI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 848w, https://substackcdn.com/image/fetch/$s_!LRhI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 1272w, https://substackcdn.com/image/fetch/$s_!LRhI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRhI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png" width="1456" height="470" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:470,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:184373,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.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_!LRhI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 424w, https://substackcdn.com/image/fetch/$s_!LRhI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 848w, https://substackcdn.com/image/fetch/$s_!LRhI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.png 1272w, https://substackcdn.com/image/fetch/$s_!LRhI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ef4f361-8f4c-4552-aee6-8813368e7455_1662x536.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>C++ header files often inline their methods. <strong>createIsUnique </strong>method, in arcane C++ syntax, instantiates an instance of the type <strong>IsUniqueInst</strong>. Inst, in this context, meaning <em>instruction</em>, not instance. </p><blockquote><p><em>Uh, perhaps I structured the above paragraph pretty badly.</em></p></blockquote><p>We locate the class declaration for <strong>IsUniqueInst</strong> at <strong>SILInstruction.h</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PTcd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PTcd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 424w, https://substackcdn.com/image/fetch/$s_!PTcd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 848w, https://substackcdn.com/image/fetch/$s_!PTcd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 1272w, https://substackcdn.com/image/fetch/$s_!PTcd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PTcd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png" width="1456" height="633" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:633,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:242366,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.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_!PTcd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 424w, https://substackcdn.com/image/fetch/$s_!PTcd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 848w, https://substackcdn.com/image/fetch/$s_!PTcd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.png 1272w, https://substackcdn.com/image/fetch/$s_!PTcd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8eba730e-1436-4225-992b-a4c0deb49bae_1738x756.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><strong>IsUniqueInst</strong> ultimately defines the Swift Intermediate Language instruction, which checks whether an object on the heap is uniquely referenced. This SIL instruction is now ready for optimisation passes and eventual conversion into LLVM IR.</p><blockquote><p><em>Desperate to learn more about Swift Intermediate Language? Check out my O.G. Elite Hack, my first every foray into paid content, where I go way deeper on what it does for Swift.</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;2d34f2ef-278f-4d06-a1bc-24465c61ef70&quot;,&quot;caption&quot;:&quot;The Swift Compiler is a mysterious multi-headed hydra. It takes your code through a many-step journey from hello world to machine code:&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Swift Intermediate Language&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2024-09-16T16:14:08.291Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!rWLs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94f331c7-b580-4c9b-947b-78da0d2dd84c_1024x1024.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/swift-intermediate-language&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:148933610,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:10,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><p>Let&#8217;s make this simple: we haven&#8217;t worked out how the uniqueness checks are happening yet. </p><p>The key to searching through the compiler is all about <strong>maintaining your bearings as you traverse each layer</strong>, down towards low-level instructions and runtime ABI calls. Usually, the runtime that has what we&#8217;re looking for. We&#8217;ll get to that, bear with me.</p><div><hr></div><h1><strong>LLVM Intermediate Representation</strong></h1><p>Chris Lattner, creator of LLVM and Swift, apocryphally called Swift <em>&#8220;syntactic sugar for LLVM.&#8221;</em></p><p>After parsing the Abstract Syntax Tree and Swift Intermediate Language generation, we arrive at the lowest level of the Swift frontend to LLVM: Synthesising instructions in LLVM Intermediate Representation. </p><p>LLVM IR is a language-independent, high-level assembly language around which LLVM itself is designed. The LLVM toolchain optimises this IR for any CPU instruction set architecture you want to run your code on.</p><p>After searching through <strong>lib/IRGen/</strong>, the library for generating LLVM IR, we spot a familiar-looking declaration in <strong>IRGenSIL.cpp</strong>: this time, taking in an SIL instruction as an argument and emitting LLVM IR for the <strong>isUnique</strong> Builtin function:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oWaO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oWaO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 424w, https://substackcdn.com/image/fetch/$s_!oWaO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 848w, https://substackcdn.com/image/fetch/$s_!oWaO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 1272w, https://substackcdn.com/image/fetch/$s_!oWaO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oWaO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png" width="1456" height="577" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:577,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:214954,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.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_!oWaO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 424w, https://substackcdn.com/image/fetch/$s_!oWaO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 848w, https://substackcdn.com/image/fetch/$s_!oWaO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.png 1272w, https://substackcdn.com/image/fetch/$s_!oWaO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a8759b5-64cb-4ae8-9d9c-a8dd9723dbd7_1796x712.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>This method loads in a &#8220;reference-counted pointer&#8221;, that is, a pointer to the object we&#8217;re checking the uniqueness of, in <strong>loadRefcountedPtr</strong>. Then it emits the <strong>isUnique</strong> function call as an LLVM IR instruction.</p><p>Following this <strong>emitIsUniqueCall</strong> function call along; we are led to <strong>GenHeap.cpp</strong> in the <strong>IRGen/</strong> library.</p><blockquote><p><em>The documentation at the top of the file reads:</em></p><p><em>&#8220;This file implements routines for arbitrary Swift-native heap objects, such as layout and reference-counting.&#8221;</em></p><p><em>Is that light I see at the end of the tunnel?</em></p></blockquote><p>Let&#8217;s read through the implementation of <strong>emitIsUniqueCall</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!R2kq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!R2kq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 424w, https://substackcdn.com/image/fetch/$s_!R2kq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 848w, https://substackcdn.com/image/fetch/$s_!R2kq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 1272w, https://substackcdn.com/image/fetch/$s_!R2kq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!R2kq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png" width="1456" height="736" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.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;:259747,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.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_!R2kq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 424w, https://substackcdn.com/image/fetch/$s_!R2kq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 848w, https://substackcdn.com/image/fetch/$s_!R2kq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.png 1272w, https://substackcdn.com/image/fetch/$s_!R2kq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe99af7a8-9dfb-4a2b-9de6-cc30a0b5ec18_2104x1064.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>I&#8217;ve omitted a ton of code here, mostly around switch cases for nullables and ObjC.</p><p>The <strong>getIsUniquelyReferenced_nonNull_nativeFunctionPointer() </strong>function call generates LLVM IR, which, when compiled and linked, calls into the Swift Runtime&#8482; upon execution.</p><p>It looks like our understanding of Builtins was a little incomplete. </p><p><strong>This is really important, probably the most important bit so far:</strong></p><p>Builtins usually represent low-level, memory-unsafe, hyper-efficient types like Builtin.Int1, Builtin.Int64, and Builtin.FPIEEE64 (a.k.a. &#8220;Double&#8221;). Stdlib structs like Bool and Int use these as internal backing storage.</p><p><strong>But Builtins can also function as direct Swift runtime calls</strong>. The functions compile directly down into instructions that call into the runtime library. </p><p>This is all possible due to the incestuously interlinked nature of Chris Lattner&#8217;s Targaryen harem: The Swift Standard Library, the Swift Compiler, and the Swift Runtime.</p><div><hr></div><h1><strong>The Swift Runtime</strong></h1><p>The Swift Runtime provides core functionality you need to execute a Swift program: Dynamic dispatch, error handling, types, <em>and memory management operations like reference counting</em>.</p><p>I think you can see where this is going, at last.</p><blockquote><p><em>If you like runtimes, but aren&#8217;t sure you&#8217;re ready to love runtimes, here&#8217;s an excellent primer:</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;cb697d4c-691f-4e6c-8236-3077c999b8b8&quot;,&quot;caption&quot;:&quot;The Swift Runtime, a.k.a libswiftCore, is a C++ library that runs alongside Swift programs to facilitates core language features. I set out to understand what we mean by &#8220;runs alongside&#8221; and &#8220;facilitates core language features&#8221;.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Swift Runtime: Your Silent Partner&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2024-12-16T17:15:51.319Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45b9e4bb-b0ba-497b-a28b-12aaf6cd0dd1_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/the-swift-runtime-your-silent-partner&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:152505616,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:18,&quot;comment_count&quot;:2,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><div><hr></div><h2><strong>Checking the docs</strong></h2><p>Let&#8217;s investigate where the LLVM IR instruction for <strong>IGM.getIsUniquelyReferenced_nonNull_nativeFunctionPointer</strong> actually ends up. </p><p>This is more art than science: naming is fabulously inconsistent between Swift layers.</p><p>Like all good engineers, we can save ourselves hours of flailing about with a few minutes of reading documentation.</p><p>The <a href="https://github.com/apple/swift/blob/main/docs/Runtime.md">Swift Runtime ABI</a> documentation defines the interface that compiled machine instructions may call into. Specifically, the memory offset for each function inside the compiled runtime binary. </p><blockquote><p><em>I&#8217;ll do an article on ABI stability once I&#8217;m convinced lots of people will pay for it, because I am <strong>not</strong> touching that sh*t for free.</em></p></blockquote><p>The definition we&#8217;re looking for is <strong>_swift_isUniquelyReferenced_nonNull_native</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a8m4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a8m4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 424w, https://substackcdn.com/image/fetch/$s_!a8m4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 848w, https://substackcdn.com/image/fetch/$s_!a8m4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 1272w, https://substackcdn.com/image/fetch/$s_!a8m4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a8m4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png" width="1456" height="846" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:846,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:379839,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.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_!a8m4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 424w, https://substackcdn.com/image/fetch/$s_!a8m4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 848w, https://substackcdn.com/image/fetch/$s_!a8m4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.png 1272w, https://substackcdn.com/image/fetch/$s_!a8m4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94e2c088-c89d-4c03-929c-01d6b9b08774_2362x1372.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"><a href="https://github.com/swiftlang/swift/blob/main/docs/Runtime.md">Runtime.md</a></figcaption></figure></div><p>Fortunately, we don&#8217;t need to search out <strong>000000000002aea0</strong> in some obscure binary.</p><p>Unfortunately, we do have quite a bit more C++ to sift through.</p><div><hr></div><h2><strong>Swift Object</strong></h2><p>I investigated the Swift Runtime source code in <strong>/stdlib/public/runtime</strong>. </p><p>Looking at <strong>SwiftObject.mm</strong> (an Objective C++ file!), we locate the function that was defined in the ABI:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bZzg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bZzg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 424w, https://substackcdn.com/image/fetch/$s_!bZzg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 848w, https://substackcdn.com/image/fetch/$s_!bZzg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 1272w, https://substackcdn.com/image/fetch/$s_!bZzg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bZzg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png" width="1456" height="426" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de678248-fe93-4925-b39f-46377401298b_1834x536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:426,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:188537,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.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_!bZzg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 424w, https://substackcdn.com/image/fetch/$s_!bZzg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 848w, https://substackcdn.com/image/fetch/$s_!bZzg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.png 1272w, https://substackcdn.com/image/fetch/$s_!bZzg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde678248-fe93-4925-b39f-46377401298b_1834x536.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>After some assertions to avoid undefined behaviour from null pointers (<a href="https://blog.jacobstechtavern.com/p/2-minute-tips-the-dark-secret-of">no type-safe nullability here!</a>), we are looking at the <strong>HeapObject</strong> argument, inspecting its <strong>refCount</strong> property, and asking if it&#8217;s uniquely referenced.</p><h4>HeapObject</h4><p>Every reference type in Swift stored in a block of memory on the heap. HeapObject represents the &#8220;header&#8221; metadata attached to each of these blocks of memory, stored contiguously in front of the memory itself, like so:</p><pre><code><code>+-----------------------+
| HeapObject            |  &lt;- header struct
| - metadata (isa) ptr  |     &lt;- type information
| - inlineRefCounts     |     &lt;- reference count bits
+-----------------------+
| Instance Data         |  &lt;- The actual data for your object 
| - field1              |
| - field2              |
| - ...                 |
+-----------------------+</code></code></pre><p>HeapObject is a simple C struct storing type metadata and reference counts. <strong>RefCounts</strong> is, itself, a struct that holds the strong, weak, and unowned reference counts of the object in memory.</p><blockquote><p><em>Uh, I also did a ridiculously in-depth deep-dive into reference counting here. Like, I literally look at the bit layout of the refCounts C struct. It&#8217;s good, clean fun. </em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;51fe7fab-b3ca-4c18-ab7f-b0a790a08c4d&quot;,&quot;caption&quot;:&quot;Every iOS dev has a soft spot, or perhaps a weak spot, for Swift reference counts. This stems from the fact that we've all survived countless interview questions about it:&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Bits &amp; Side Tables: How Reference Counting Works in Swift&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-08-25T15:02:22.684Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!UT9G!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f8cc733-84bf-4955-a1bb-da3b2ccb0508_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/swift-reference-counting&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170428435,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:29,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><p>Like SEAL Team 6, let&#8217;s target where <strong>isUniquelyReferenced()</strong> is implemented, on the <strong>refCount</strong> for a HeapObject. With extreme prejudice.</p><div><hr></div><h1><strong>SwiftShims</strong></h1><p>SwiftShims is a lightweight compatibility layer between the Standard Library, the Runtime, the Compiler, and the OS. This collection of C and C++ header files helps to bridge high-level code with underlying system libraries.</p><p>Critically, <strong>RefCount.h</strong> implements the method we&#8217;re tracking down:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-WCQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-WCQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 424w, https://substackcdn.com/image/fetch/$s_!-WCQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 848w, https://substackcdn.com/image/fetch/$s_!-WCQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 1272w, https://substackcdn.com/image/fetch/$s_!-WCQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-WCQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png" width="1374" height="668" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bbba576c-7485-4138-949d-24acafec66cd_1374x668.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:668,&quot;width&quot;:1374,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:188278,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.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_!-WCQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 424w, https://substackcdn.com/image/fetch/$s_!-WCQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 848w, https://substackcdn.com/image/fetch/$s_!-WCQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.png 1272w, https://substackcdn.com/image/fetch/$s_!-WCQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbba576c-7485-4138-949d-24acafec66cd_1374x668.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>This <strong>refCount</strong> struct has an <strong>isUniquelyReferenced()</strong> property. For this uniqueness check, we safely load the memory into the <strong>bits</strong> property and ask if it&#8217;s uniquely referenced.</p><p>If the object has any weak references (or the strong or unowned ref counts overflow), the refCounts live on a &#8220;side table&#8221;. That&#8217;s why the <strong>isUniquelyReferenced()</strong> check either loads directly from <strong>refCounts</strong> or checks the side table.</p><p>Next, we can see the underlying implementation of <strong>isUniquelyReferenced()</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LE28!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LE28!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 424w, https://substackcdn.com/image/fetch/$s_!LE28!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 848w, https://substackcdn.com/image/fetch/$s_!LE28!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 1272w, https://substackcdn.com/image/fetch/$s_!LE28!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LE28!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png" width="1456" height="497" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:497,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:156563,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.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_!LE28!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 424w, https://substackcdn.com/image/fetch/$s_!LE28!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 848w, https://substackcdn.com/image/fetch/$s_!LE28!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.png 1272w, https://substackcdn.com/image/fetch/$s_!LE28!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cf1d82-f0df-4d2a-b56f-d100345b22bc_1700x580.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><strong>getUseSlowRC</strong> checks whether there&#8217;s a side table storing overflowed pointer counts; and <strong>getIsDeiniting</strong> is fairly self-explanatory: deinitialisation only happens when a strong reference count is already zero.</p><p>The most important part here is <strong>getStrongExtraRefCount() == 0</strong>. Scrolling up to the documentation inline, we find:</p><blockquote><p><em>The strong RC is stored as an extra count: when the physical field is 0 the logical value is 1.</em></p></blockquote><p>If an object has exactly one strong reference (logical), the bits representing the strong reference count are 00000000 (physical). The <strong>getStrongExtraRefCount</strong> function finds us the strong reference count that we&#8217;re looking for, StrongExtraRefCount:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!l1eS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!l1eS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 424w, https://substackcdn.com/image/fetch/$s_!l1eS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 848w, https://substackcdn.com/image/fetch/$s_!l1eS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 1272w, https://substackcdn.com/image/fetch/$s_!l1eS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!l1eS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png" width="1220" height="536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:536,&quot;width&quot;:1220,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:153066,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.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_!l1eS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 424w, https://substackcdn.com/image/fetch/$s_!l1eS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 848w, https://substackcdn.com/image/fetch/$s_!l1eS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.png 1272w, https://substackcdn.com/image/fetch/$s_!l1eS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46da65c6-6102-489a-8ba1-c87bce17266e_1220x536.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>Here, we call into a C++ macro that returns the StrongExtraRefCount field stored in RefCount:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ag5B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ag5B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 424w, https://substackcdn.com/image/fetch/$s_!ag5B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 848w, https://substackcdn.com/image/fetch/$s_!ag5B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 1272w, https://substackcdn.com/image/fetch/$s_!ag5B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ag5B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png" width="1428" height="492" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:492,&quot;width&quot;:1428,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:147386,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.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_!ag5B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 424w, https://substackcdn.com/image/fetch/$s_!ag5B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 848w, https://substackcdn.com/image/fetch/$s_!ag5B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.png 1272w, https://substackcdn.com/image/fetch/$s_!ag5B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34cf2b01-debf-4dee-9f20-d1f7e3138bf0_1428x492.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>These macros operate directly on the bits stored by RefCount to return the integer value of StrongExtraRefCount. These bitwise operations can be dense, so let&#8217;s take this step-by-step:</p><ul><li><p>The logical number <strong>StrongExtraRefCount</strong> is stored in the bits in RefCount&#8216;s memory layout, bit-packed with other metadata (unowned count and flags) to save space.</p></li><li><p>Let&#8217;s say the memory layout for the RefCount looks like 00101010 (in reality, it&#8217;s 64 bits wide, I&#8217;ll actually show you in a minute).</p></li><li><p>The bit-mask has 1s for the locations of the bits that represent the <strong>StrongExtraRefCount</strong>, e.g., 00001100.</p></li><li><p>We can run a bitwise &amp; operation to isolate just those bits, 0-ing out the rest of the data: leaving us with 00001000.</p></li><li><p>The offset <strong>##Shift</strong> contains the number of &#8220;significant&#8221; digits which the <strong>StrongExtraRefCount</strong> lives at, which in this example is two bits from the end (in this one-byte example, we don&#8217;t need to fret about endian-ness).</p></li><li><p>The right bit-shift operator &gt;&gt; shifts our bit-masked data to the right, returning 00000010.</p></li><li><p>This, in full binary glory, is the strong extra reference count we&#8217;re looking for: 10, or &#8220;2&#8221; if you&#8217;re a decimal normie.</p></li></ul><p>Therefore, our object has three strong references, meaning it&#8217;s not uniquely referenced!</p><blockquote><p><em>I&#8217;ll encourage you to read &#8220;<a href="https://blog.jacobstechtavern.com/p/swift-reference-counting">Bits and Side Tables</a>&#8221; once again because I show you the actual physical bits inside RefCount:</em> </p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vM63!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vM63!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 424w, https://substackcdn.com/image/fetch/$s_!vM63!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 848w, https://substackcdn.com/image/fetch/$s_!vM63!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 1272w, https://substackcdn.com/image/fetch/$s_!vM63!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vM63!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png" width="1456" height="779" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:779,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:200344,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.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_!vM63!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 424w, https://substackcdn.com/image/fetch/$s_!vM63!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 848w, https://substackcdn.com/image/fetch/$s_!vM63!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.png 1272w, https://substackcdn.com/image/fetch/$s_!vM63!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcde50fe8-65a8-45a4-8b6c-0a3849cf3f69_1776x950.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><div><hr></div><h1><strong>The </strong>isKnownUniquelyReferenced Meme</h1><p>We&#8217;ve finally determined how <strong>isKnownUniquelyReferenced</strong> is working behind the scenes to power our &#128046; optimisations.</p><p>It&#8217;s all a bit obvious, really.</p><p>Each time a new pointer is created to reference an object stored on heap memory strongly, it increments the strong reference count of that object.</p><p>isKnownUniquelyReferenced simply slips through its backchannel into the runtime  to ask whether the object&#8217;s strong reference count is equal to 1.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-5fq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-5fq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-5fq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-5fq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-5fq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-5fq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg" width="500" height="1069" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1069,&quot;width&quot;:500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!-5fq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-5fq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-5fq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-5fq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07ba4675-7850-4a63-9598-7c258f153b66_500x1069.jpeg 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">7-tier expanding brain meme, created with <a href="https://imgflip.com/memegenerator/180509546/7-Tier-Expanding-Brain">Memegenerator</a></figcaption></figure></div><p><em><strong>(Accessible version of the meme)</strong></em></p><ul><li><p>isKnownUniquelyReferenced just checks the strong reference count = 1</p></li><li><p>isUnique in the Swift Standard Library calls a Builtin function</p></li><li><p>The Abstract Syntax Tree synthesises Builtin functions so they can be called like regular Swift functions</p></li><li><p>Swift Intermediary Language emits the IsUniqueInst instruction, which performs the uniqueness check</p></li><li><p>The LLVM IR instruction generates the emitIsUnique instruction, which calls into the Swift Runtime ABI</p></li><li><p>The Swift Runtime inspects the bits on a HeapObject which stores the strong reference count</p></li><li><p>isKnownUniquelyReferenced just checks the strong reference count = 1</p></li></ul><div><hr></div><h2><strong>Last Orders</strong></h2><p>When I first casually looked into <strong>isKnownUniquelyReferenced</strong> back in 2023, I had no idea what I was getting into. I assumed I&#8217;d poke around the Swift Standard Library, find some funny private API that tracked a sneaky reference count property somewhere, and call it a day.</p><p>Curiosity is a heavy burden.</p><p>Like Dante, I kept pressing forward.</p><p>Into the haunted woods of the Standard Library source code. Through the purgatorial hallways of Builtin definitions. Deeper and deeper, through the infernal circles of the Swift Compiler: the Abstract Syntax Tree, Swift Intermediary Language, and LLVM IR. Until finally, paradise was found in the Swift Runtime and SwiftShims.</p><p>Today, Swift Internals is a core pillar of Jacob&#8217;s Tech Tavern. </p><p>I hope you had fun, learned a lot, and, most importantly, I hope you get the chance to flex your unbeatable &#128046; knowledge the next time you get an iOS job interview.</p><blockquote><p><em><strong>If you liked my post, subscribe free to join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week.</strong></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><blockquote><p><em>This is a full re-write my most underrated post of all time. Nobody read it, because I only had 291 subscribers at the time. Really.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5mMY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5mMY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 424w, https://substackcdn.com/image/fetch/$s_!5mMY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 848w, https://substackcdn.com/image/fetch/$s_!5mMY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 1272w, https://substackcdn.com/image/fetch/$s_!5mMY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5mMY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png" width="1456" height="694" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:694,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:121216,&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://blog.jacobstechtavern.com/i/181220219?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.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_!5mMY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 424w, https://substackcdn.com/image/fetch/$s_!5mMY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 848w, https://substackcdn.com/image/fetch/$s_!5mMY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.png 1272w, https://substackcdn.com/image/fetch/$s_!5mMY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff14bd357-8ab8-4a95-a876-f8b289170083_1770x844.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><em>I hope I can bring the joy to a new generation of subscribers.</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;470a93dc-41c6-4bdb-b725-3856a2de89b5&quot;,&quot;caption&quot;:&quot;Subscribe to Jacob&#8217;s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, &amp; indie projects in your inbox every two weeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;COW2LLVM: The isKnownUniquelyReferenced Deep-Dive &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2023-11-06T17:20:18.179Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!lZbv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c5730fc-2271-4fe1-a850-1eb13eb66708_1400x930.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/cow2llvm-the-isknownuniquelyreferenced&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:138629860,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:13,&quot;comment_count&quot;:2,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p><em>And if you liked this post, you will <strong>love</strong> this:</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;e56a600f-4789-4391-a4e3-5365ae738b2f&quot;,&quot;caption&quot;:&quot;Today I&#8217;m selling shovels. A treasure map. The equipment you need to tunnel through the Swift source code and mine out the nuggets of arcane knowledge reserved for C++ and compiler geeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;How to Learn the Swift Source Code&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-07-22T15:02:11.838Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LGzj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ab95ff2-d803-458d-9b6e-cfe56f3226ee_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/swift-source-code&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:168148655,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:14,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote>]]></content:encoded></item><item><title><![CDATA[Ancient Secrets of the Objective-C Runtime]]></title><description><![CDATA[Applied ObjC for modern Swift apps]]></description><link>https://blog.jacobstechtavern.com/p/objc-runtime-internals</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/objc-runtime-internals</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 09 Dec 2025 16:02:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qqpr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.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_!qqpr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qqpr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!qqpr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!qqpr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!qqpr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qqpr!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4675433,&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://blog.jacobstechtavern.com/i/180131074?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qqpr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!qqpr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!qqpr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!qqpr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed155b74-49fa-4df2-9628-2ff5f51e1641_1680x1200.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 go anywhere! Seriously. </p><p>This is <strong>not</strong> some theoretical archaeological deep-delve.</p><p>I&#8217;m going to give you something you can use in your Swift apps <strong>today</strong>.</p><p>I&#8217;m <strong><a href="https://example.com">NOT</a></strong> talking about <strong>#selector</strong>, <strong>@objc</strong>-marked methods, or <strong>dynamic</strong> functions.</p><p>This post is about <strong>Objective-C runtime internals</strong>. How ObjC is built, the powerful features it offers, and how to apply these features to simplify your modern Swift codebase. </p><div><hr></div><p>I&#8217;ve been doing iOS for just under 10 years. I went into consulting in 2016, just after the Grand Renaming&#8482; of Swift 2.0 to Swift 3.0. </p><p>It was kind of an annoying time to begin tbh.</p><p>I spent month #1 of my first ever job working through the Big Nerd Ranch Swift textbook, but Deloitte didn&#8217;t want to shell out $21 for the Swift 3 edition, so I spent half my time Googling each line of syntax to find the renamed version.</p><p>I dipped my toe into a few hairy legacy ObjC codebases back in the day, but I&#8217;ve managed to spend about 98% of my career rolling Swift. Yay me.</p><p>Most iOS devs today are similar. Many of you have likely never touched Objective-C.</p><p>So why am I darkening your doorstep with a d&#821;&#840;&#858;&#776;&#769;&#769;&#785;e&#820;&#857;&#848;&#781;&#228;&#822;&#800;&#826;&#803;&#769;&#838;&#769;d&#824;&#819;&#864; &#821;&#816;&#841;&#830;&#787;l&#821;&#858;&#812;&#838;&#834;&#769;&#257;&#821;&#807;&#795;&#828;&#776;&#769;&#505;&#824;&#801;&#846;&#799;&#788;g&#822;&#803;&#796;&#779;&#778;&#771;u&#823;&#793;&#775;&#770;&#855;&#261;&#824;&#841;&#853;&#856;&#861;&#861;g&#822;&#802;&#798;&#776;&#768;e&#823;&#811;&#852;&#831;?</p><p>3 reasons:</p><ul><li><p>We can learn a lot from ObjC&#8217;s design and runtime internals. </p></li><li><p>There are useful practical applications that work in UIKit apps today.</p></li><li><p>It&#8217;s really bloody interesting.</p></li></ul><p>Sound good? Come along for the ride. </p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/a-very-brief-history-of-objective-c">A (very) brief history of Objective-C</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/what-makes-objective-c-special">What makes Objective-C special?</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/the-objc-runtime">The ObjC Runtime</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/objcmsgsend-and-message-dispatch">objc_msgSend and Message Dispatch</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/the-power-of-the-runtime">The power of the runtime</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/modern-practical-applications">Modern Practical Applications</a></p><ul><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/screen-tracking-and-swizzling">Screen tracking and Swizzling</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/tracking-dwell-time-with-associated-objects">Tracking dwell time with Associated Objects</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/active-screens-and-introspection">Active screens and introspection</a></p></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/interacting-with-collections-via-message-forwarding-and-nsproxy">Interacting with collections via Message Forwarding and NSProxy</a></p></li></ul></li><li><p><a href="https://blog.jacobstechtavern.com/i/180131074/last-orders">Last Orders</a></p></li></ul><blockquote><p><em>Upgrade to unlock this article, plus much more:</em></p><p><em>&#127775; Access <a href="https://blog.jacobstechtavern.com/t/elite-hacks">Elite Hacks</a>, my exclusive advanced content <br>&#128640; Read <a href="https://blog.jacobstechtavern.com/archive?sort=top">my free articles</a> a month before anyone else <br>&#129525; Master concurrency with my <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-course">course</a> and <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">advanced training</a></em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/objc-runtime-internals">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Method Dispatch in Swift: The Complete Guide ]]></title><description><![CDATA[How does Swift *really* execute function calls?]]></description><link>https://blog.jacobstechtavern.com/p/swift-method-dispatch</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/swift-method-dispatch</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Mon, 01 Dec 2025 16:02:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ozUp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.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_!ozUp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ozUp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!ozUp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!ozUp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!ozUp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ozUp!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:3209542,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ozUp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!ozUp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!ozUp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!ozUp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e79f49-9649-448b-9b5f-dcb405734abe_1680x1200.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>If you&#8217;re like me, you&#8217;ve worked with a grizzled staff engineer that generously doles out helpful nitpicks to improve the performance of your code.</p><p>Perhaps, like me, you&#8217;ve also been that grizzled engineer.</p><p>You know the sort. </p><p>Nitpicks like <em>&#8220;this method should be declared <strong>fileprivate</strong>&#8221;</em>, or <em>&#8220;keep your <strong>generics </strong>in the same file where they&#8217;re used&#8221;</em>, and the all-time classic <em>&#8220;mark this function as <strong>final</strong>&#8221;</em> to help out the compiler and speed up your code.</p><p>In modern Swift, you might as well spend your time writing <a href="https://www.linkedin.com/posts/jacobmartinbartlett_while-reading-the-swift-source-code-i-ran-activity-7363887779161776130-q5eZ/">branch prediction hints</a> for the compiler. That is, the <a href="https://blog.jacobstechtavern.com/p/the-swift-compiler">compiler</a> and <a href="https://blog.jacobstechtavern.com/p/the-swift-runtime-your-silent-partner">runtime</a> do a ton of optimisation under the hood that makes these tips redundant.</p><p>These optimisations are mostly around <strong>Method Dispatch</strong>.</p><p>That is, <strong>how Swift executes function calls</strong>. This knowledge is crucial for understanding the low-level performance characteristics of your code.</p><p>Today we&#8217;re going to learn: </p><ul><li><p>How (and why) Swift implements all 4 types of dispatch</p></li><li><p>What <a href="https://blog.jacobstechtavern.com/p/the-swift-compiler">the Swift compiler</a> does to your methods in secret </p></li><li><p>How <a href="https://blog.jacobstechtavern.com/p/the-swift-runtime-your-silent-partner">the Swift runtime</a> calls into your functions at runtime</p></li><li><p>How to make your code run <strong>faster</strong></p></li><li><p>How to build an intuition about method dispatch</p></li></ul><div><hr></div><blockquote><p><em>Subscribe free to join 100,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week.</em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h3>Method Dispatch</h3><p>In broad Computer Science terms, &#8220;method dispatch&#8221; is the process for telling the CPU where to find executable code in memory for a function call. </p><p>Method dispatch can be <strong>static</strong> or <strong>dynamic</strong>, but these break down into 4 sub-types. As you move down, method dispatch becomes more flexible, but slower: The types create a bidirectional hierarchy of speed &amp; flexibility.</p><p>This hierarchy is defined by <strong>indirection</strong>. That is, the number of times the CPU has to jump between pointers to find the machine code for a function.</p><ul><li><p><strong>Inlining</strong> (fastest, not flexible)<br>This optimisation unrolls a method&#8217;s contents directly onto the code path.</p></li><li><p><strong>Static </strong>dispatch (fast, not flexible)<br>The function&#8217;s memory address is known, so the CPU jumps straight to it.</p></li><li><p><strong>Table</strong> dispatch (slow, flexible)<br>The CPU jumps twice: once to a table of pointers (to potential implementations), then once to the correct implementation. </p></li><li><p><strong>Message</strong> dispatch (slowest, very flexible)<br>There might be multiple jumps as the runtime traverses class and superclass metadata to locate method implementations. This dynamic approach implements caching that can speed it up past table dispatch once it&#8217;s &#8216;warmed up&#8217;. </p></li></ul><p>Most languages pick just one or two approaches:</p><ul><li><p><strong>C</strong> only uses <strong>static dispatch</strong> since it is designed around predictable low-level performance. </p></li><li><p><strong>Java</strong> only implements <strong>table dispatch</strong> because of its focus on portability, meaning the JVM must always be able to load classes dynamically.</p></li><li><p><strong>Objective-C</strong> uses <strong>message dispatch</strong> because it is deliberately built for runtime dynamism, with language features like swizzling and method forwarding. </p></li></ul><p><strong>Swift implements all 4.</strong></p><p>This is due to the scope of the language. </p><ul><li><p>Swift is <em>(designed to be)</em> as performant as C when using value types like structs and enums, which use static dispatch.</p></li><li><p>Swift also supports classes, protocols and generics, which rely on the more flexible table dispatch to locate relevant implementations.</p></li><li><p>Message dispatch, honestly, is a legacy Objective-C holdover. Swift had to be fully compatible with Obj-C and UIKit in order to achieve adoption from the aforementioned grizzled staff engineers.</p></li></ul><p>This is a double-edged sword: Swift gives engineers fine-grained control over the performance characteristics of their code; but this scope also introduces many of the gotchas and misunderstandings that trip up less experienced Swifties* </p><blockquote><p><em>(I&#8217;m pretty sure this is what they call us).</em></p></blockquote><div><hr></div><h2>Inlining</h2><p>This is the fastest approach, and is actually not <em>dispatch </em>at all. Inlining is a compiler optimisation which replaces the call to a function with the actual code from inside that function.</p><p>We don&#8217;t usually control this*. The Swift compiler makes the call about inlining function calls during its SIL optimisation stages.</p><blockquote><p><em>*but you can influence it by selecting size vs speed compiler optimisations</em>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7c7O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7c7O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 424w, https://substackcdn.com/image/fetch/$s_!7c7O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 848w, https://substackcdn.com/image/fetch/$s_!7c7O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 1272w, https://substackcdn.com/image/fetch/$s_!7c7O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7c7O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png" width="1245" height="200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:200,&quot;width&quot;:1245,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52763,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.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_!7c7O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 424w, https://substackcdn.com/image/fetch/$s_!7c7O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 848w, https://substackcdn.com/image/fetch/$s_!7c7O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 1272w, https://substackcdn.com/image/fetch/$s_!7c7O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5faa6b45-796d-4f68-be01-2f70a1eba400_1245x200.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div></blockquote><p>Let&#8217;s say you had the following 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_!C-Qg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!C-Qg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 424w, https://substackcdn.com/image/fetch/$s_!C-Qg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 848w, https://substackcdn.com/image/fetch/$s_!C-Qg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 1272w, https://substackcdn.com/image/fetch/$s_!C-Qg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!C-Qg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png" width="456" height="312" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:312,&quot;width&quot;:456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55025,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.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_!C-Qg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 424w, https://substackcdn.com/image/fetch/$s_!C-Qg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 848w, https://substackcdn.com/image/fetch/$s_!C-Qg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.png 1272w, https://substackcdn.com/image/fetch/$s_!C-Qg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0ddbce-9464-41dd-a2a6-f8575af7a084_456x312.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>If the compiler decides to inline this, the compiled Swift might be equivalent to this: </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K7y9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K7y9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 424w, https://substackcdn.com/image/fetch/$s_!K7y9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 848w, https://substackcdn.com/image/fetch/$s_!K7y9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 1272w, https://substackcdn.com/image/fetch/$s_!K7y9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K7y9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png" width="380" height="224" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:224,&quot;width&quot;:380,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:35581,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.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_!K7y9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 424w, https://substackcdn.com/image/fetch/$s_!K7y9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 848w, https://substackcdn.com/image/fetch/$s_!K7y9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 1272w, https://substackcdn.com/image/fetch/$s_!K7y9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbb051ba-f5ba-4412-b27e-06fc89007cd4_380x224.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Here, the call to the <strong>addOne</strong> function is just replaced with the operation <code>num + 1</code>, where <code>num</code> is replaced with our argument, <code>2</code>.</p><h4>Pre-computing</h4><p>The compiler can go further. </p><p>Since these numbers are hardcoded, the compiler actually has all the information it needs to calculate this result at compile-time. It can, literally, <em>pre-compute</em> the result we need here, giving us a simple number.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GAi8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GAi8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 424w, https://substackcdn.com/image/fetch/$s_!GAi8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 848w, https://substackcdn.com/image/fetch/$s_!GAi8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 1272w, https://substackcdn.com/image/fetch/$s_!GAi8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GAi8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png" width="476" height="224" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:224,&quot;width&quot;:476,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36878,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.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_!GAi8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 424w, https://substackcdn.com/image/fetch/$s_!GAi8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 848w, https://substackcdn.com/image/fetch/$s_!GAi8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 1272w, https://substackcdn.com/image/fetch/$s_!GAi8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3253fdd8-e15e-4b9f-bc37-7368d134705c_476x224.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Inlining skips dispatch entirely, but pre-computing avoids runtime execution altogether. No work needs to happen in our (hopefully) millions of users&#8217; devices at runtime. </p><h4><strong>Swift Intermediate Language</strong></h4><p>Before compiling your code down to machine language, the Swift compiler converts it into <strong>Swift Intermediate Language</strong> (SIL), where it runs through many optimisation passes. </p><p>You can generate SIL yourself from Swift code like this:</p><div class="pullquote"><p><code>swiftc -emit-sil -O main.swift &gt; sil.txt</code></p></div><p><strong>-O</strong> tells the compiler to run optimisations for <strong>speed</strong>, which include inlining. <strong>-Osize</strong> in contrast optimises for smaller binary size, making the compiler less likely to inline. Copying a function into multiple places inline can grow binary size.</p><blockquote><p><em>Learn more about SIL in my mini-deep-dive:</em> </p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;8ea5944f-7513-4294-9ff5-6bd68d93145f&quot;,&quot;caption&quot;:&quot;The Swift Compiler is a mysterious multi-headed hydra. It takes your code through a many-step journey from hello world to machine code:&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Swift Intermediate Language&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2024-09-16T16:14:08.291Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!rWLs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94f331c7-b580-4c9b-947b-78da0d2dd84c_1024x1024.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/swift-intermediate-language&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:148933610,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:10,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><p> The resulting arcane hieroglyphs allow us to see the optimisations in person:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7AoE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7AoE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 424w, https://substackcdn.com/image/fetch/$s_!7AoE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 848w, https://substackcdn.com/image/fetch/$s_!7AoE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 1272w, https://substackcdn.com/image/fetch/$s_!7AoE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7AoE!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png" width="1200" height="524.1758241758242" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:636,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:489067,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7AoE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 424w, https://substackcdn.com/image/fetch/$s_!7AoE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 848w, https://substackcdn.com/image/fetch/$s_!7AoE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.png 1272w, https://substackcdn.com/image/fetch/$s_!7AoE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c706eef-63f4-47ad-802d-6fff6b272b73_2334x1020.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">caption...</figcaption></figure></div><p>I omitted most of the code for brevity (4 lines of Swift turns into 78 lines of SIL!), but we can see inlining in action:</p><ol><li><p>Memory is allocated for the <strong>twoPlusOne</strong> property.</p></li><li><p>The pointer address of our <strong>twoPlusOne</strong> property is assigned.</p></li><li><p><strong>An integer literal for 3 is precomputed and inlined.</strong></p></li><li><p>This value converted into an <strong>Int</strong> struct from the Standard Library.</p></li><li><p>This <strong>Int</strong> is stored at <strong>%3</strong>, the memory address of <strong>twoPlusOne</strong>.</p></li><li><p>You&#8217;ll usually see these lines at the end of a <strong>main()</strong> function. This is simply exiting the program with code 0 (i.e. without an error).</p></li></ol><blockquote><p><em><a href="https://swiftrocks.com/the-forbidden-inline-attribute-in-swift">SwiftRocks has a great article</a> if you want more of a deep-dive on inlining and the undocumented</em> <strong>@inline</strong> <em>attribute.</em></p></blockquote><h4>Why is inlining so fast?</h4><p>While SIL does not map 1:1 onto ARM assembly instructions (you need to run <strong>swift -c</strong> for that!), it is pretty intuitive that less SIL will execute faster than more SIL. </p><p>To truly peer behind the veil, we need to touch the metal: what is happening on the CPU when you call a function?</p><p>There is <strong>Overhead</strong> each time you invoke a function. The CPU caches the data on its registers, jumps the instruction pointer to a new memory address, and restores state after function execution.</p><p>An executing binary lives primarily in a chunky <code>TEXT</code> file stored in memory. Segments of executing code are copied to the <strong>CPU Caches</strong>, which are accessed 100x faster than RAM. A slow <em>cache miss </em>happens if a function has to be loaded from memory.</p><p>CPUs utilise <strong>Pipelining</strong> to handle multiple instructions simultaneously. When it needs to wait for a new function to be loaded in from RAM, the instruction pipeline may be disrupted, stalled, or even invalidated entirely.</p><p>The CPU applies <strong>Branch Prediction</strong> to estimate which code paths are likely to run next, allowing it to fill the pipeline with the most likely paths (and even look ahead with <em>predictive execution</em>). Jumps to function calls can easily disrupt a CPU&#8217;s ability to predict outcomes. </p><blockquote><p><em>Learn more about binaries and TEXT here:</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;052a492b-8b7f-487c-970c-930af79e9038&quot;,&quot;caption&quot;:&quot;I&#8217;m religious when it suits me.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;How do researchers reverse-engineer private frameworks?&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-10-28T16:02:55.431Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Uymn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54b79f9d-ca27-4350-8a74-41a677768088_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/reverse-engineer-private-frameworks&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:176832931,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:20,&quot;comment_count&quot;:2,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p><em>I&#8217;ve also written a lot about registers, CPU caches, and pipelining here:</em> </p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;881c6124-ae44-471f-a01a-a1dd65ed8b4d&quot;,&quot;caption&quot;:&quot;Subscribe to Jacob&#8217;s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, &amp; indie projects in your inbox every two weeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Through the Ages: Apple CPU Architecture &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2023-10-30T19:47:24.880Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!gdjQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef56b4d8-b9c0-4766-98f4-ffebb24d9458_700x620.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/through-the-ages-apple-cpu-architecture&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:138428815,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:55,&quot;comment_count&quot;:12,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><p>Due to all these factors, inlining and pre-computation are powerful tools in the Swift Compiler&#8217;s arsenal for optimising your code for pure speed.</p><div><hr></div><h2>Static Dispatch</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wUdg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wUdg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 424w, https://substackcdn.com/image/fetch/$s_!wUdg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 848w, https://substackcdn.com/image/fetch/$s_!wUdg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!wUdg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wUdg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg" width="720" height="332" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:332,&quot;width&quot;:720,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!wUdg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 424w, https://substackcdn.com/image/fetch/$s_!wUdg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 848w, https://substackcdn.com/image/fetch/$s_!wUdg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!wUdg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdbd108a-49f9-4b9b-887d-d65fb35d8fd8_720x332.jpeg 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">No, not this kind of static. Effect generated using <a href="https://blog.jacobstechtavern.com/p/metal-in-swiftui-how-to-write-shaders">Metal in SwiftUI: How to write Shaders</a></figcaption></figure></div><p>This is also known as <em>direct dispatch</em> or, occasionally, <em>compile-time dispatch</em>. These names all describe what&#8217;s going on: </p><ul><li><p><em>static</em> implies that the location of the function in memory is fixed&#8230;</p></li><li><p>&#8230;and knowable at <em>compile-time</em>. </p></li><li><p>Therefore, only one jump is required to find and execute the function, <em>direct</em>ly to the memory address of the function in the binary.</p></li></ul><p><strong>static</strong> functions in Swift, as well as functions on <strong>enums</strong> and <strong>structs</strong>, use static dispatch. The compiled machine code of these functions is stored at a known address in memory when a Swift program launches.</p><p>This deterministic nature of static dispatch enables the compiler to easily run optimisations such as inlining and pre-computation.</p><p>Let&#8217;s see this in action with a very basic struct, with another <strong>addOne</strong> function:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZqeB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZqeB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 424w, https://substackcdn.com/image/fetch/$s_!ZqeB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 848w, https://substackcdn.com/image/fetch/$s_!ZqeB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 1272w, https://substackcdn.com/image/fetch/$s_!ZqeB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZqeB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png" width="524" height="356" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff468194-abd5-4501-a45d-4355c2011f77_524x356.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:356,&quot;width&quot;:524,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:66665,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.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_!ZqeB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 424w, https://substackcdn.com/image/fetch/$s_!ZqeB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 848w, https://substackcdn.com/image/fetch/$s_!ZqeB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.png 1272w, https://substackcdn.com/image/fetch/$s_!ZqeB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff468194-abd5-4501-a45d-4355c2011f77_524x356.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>Let&#8217;s generate the Swift Intermediate Language for this code and see what&#8217;s going on under the hood of the compiler. </p><blockquote><p><em>Again, I&#8217;ll massively cut down the 97 lines of generated SIL for this 7-line </em><code>main.swift</code><em> file to avoid information overload.</em></p></blockquote><p>Let&#8217;s see what became of our <strong>main</strong> function: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kj1R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kj1R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 424w, https://substackcdn.com/image/fetch/$s_!kj1R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 848w, https://substackcdn.com/image/fetch/$s_!kj1R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!kj1R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kj1R!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png" width="1200" height="614.8351648351648" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:746,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:620838,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kj1R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 424w, https://substackcdn.com/image/fetch/$s_!kj1R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 848w, https://substackcdn.com/image/fetch/$s_!kj1R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.png 1272w, https://substackcdn.com/image/fetch/$s_!kj1R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2e21ba5-2fcb-4dbe-adb9-315fdcd8f17d_2334x1196.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><ol><li><p>Memory is allocated for the <strong>threePlusOne</strong> property. </p></li><li><p>The function call for the <strong>Adder</strong> struct&#8217;s init function is called. <br>You thought struct initialisers were implicit? They are, until the compiler generates it! <br><strong>apply</strong> is the SIL instruction for calling a function, taking <strong>%4 </strong>(the type) as an argument for <strong>%5</strong> (the function).</p></li><li><p>Next, the integer literal for our function argument&#8202;, &#8202;that is, the number <strong>3</strong>, is instantiated. First a <strong>Builtin</strong> Literal is called, then an <strong>Int</strong> is initialised.</p></li><li><p>Finally, our <strong>addOne</strong> function is called; creating a function pointer <strong>function_ref</strong>, and passing the arguments created before: the <strong>Int</strong> and the <strong>Adder</strong>.  </p></li></ol><p>The calling convention of SIL looks a lot like Python: <strong>self</strong>, the instance, is explicitly passed to the call site of its methods. </p><p>This is because the methods on a type are shared between all instances in memory. Therefore, a reference to the instance is required to access or mutate any properties.</p><p>The definition for our <strong>addOne</strong> function is found here as well:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vQhW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vQhW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 424w, https://substackcdn.com/image/fetch/$s_!vQhW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 848w, https://substackcdn.com/image/fetch/$s_!vQhW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!vQhW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vQhW!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png" width="1200" height="472.25274725274727" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:573,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:584961,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vQhW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 424w, https://substackcdn.com/image/fetch/$s_!vQhW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 848w, https://substackcdn.com/image/fetch/$s_!vQhW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!vQhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F719d90f8-6fe2-4312-b6dd-249154f9f6a9_2928x1152.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><ol><li><p>An <strong>integer_literal</strong> is declared using 1, and the integer value of the input argument is extracted.</p></li><li><p>This is where the magic happens: &#8202;the actual functionality of the <strong>Int.+</strong> function is inlined here using the <strong>Builtin</strong> implementation.</p></li><li><p>There is some nifty error-handling that detects arithmetic overflow (i.e. values over 2&#8310;&#179;-1); and the result <strong>Int</strong> is instantiated and returned.</p></li></ol><p>I won&#8217;t go into more detail here, but the <strong>Int.init(_builtinIntegerLiteral:)</strong> initialiser and the <strong>Int.+ infix(_:_:) </strong>functions are also both defined in SIL.</p><blockquote><p><em>Not sure what is meant by <strong>Builtin</strong>? Read this post if you want to become absolutely sick of seeing them.</em></p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;c5a676ba-d830-4b33-b7f7-bc38cdd58e5d&quot;,&quot;caption&quot;:&quot;Subscribe to Jacob&#8217;s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, &amp; indie projects in your inbox every two weeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;COW2LLVM: The isKnownUniquelyReferenced Deep-Dive &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2023-11-06T17:20:18.179Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!lZbv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c5730fc-2271-4fe1-a850-1eb13eb66708_1400x930.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/cow2llvm-the-isknownuniquelyreferenced&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:138629860,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:13,&quot;comment_count&quot;:2,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><p>When compiling this SIL with optimisations, the <code>addOne</code> function itself is inlined straight to the call site; and the <strong>Int.init()</strong> and <strong>Int.+</strong> functions disappear entirely. </p><p>The Swift compiler collapses entire chains of statically-dispatched function calls inline to extinguish many expensive function calls at once. Such is the power of direct dispatch. </p><div><hr></div><h2>Dynamic Dispatch</h2><p>This is also known as <em>table dispatch</em>, or sometimes <em>runtime dispatch</em> (some of these words are straightforward)&#8202;. Basically, the function we dispatch to is <em>dynamic</em>ally chosen. This means chosen <em>at runtime</em>. </p><p><em>Table dispatch</em> isn&#8217;t as obvious semantically, but divulges an implementation detail: a table of pointers. This table is critical for implementing polymorphism. The power for a single type to have multiple <em>formes</em>.</p><p>Before you shout at me, yes, Swift actually implements <strong>two flavours of table dispatch</strong>: <em>virtual tables</em> for class hierarchies, and <em>witness tables</em> for protocols.</p><h4>Virtual Table Dispatch</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7A80!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7A80!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 424w, https://substackcdn.com/image/fetch/$s_!7A80!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 848w, https://substackcdn.com/image/fetch/$s_!7A80!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 1272w, https://substackcdn.com/image/fetch/$s_!7A80!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7A80!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png" width="800" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!7A80!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 424w, https://substackcdn.com/image/fetch/$s_!7A80!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 848w, https://substackcdn.com/image/fetch/$s_!7A80!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.png 1272w, https://substackcdn.com/image/fetch/$s_!7A80!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7ce1120-7b38-4858-8295-ab9d2e1df47c_800x695.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">Photo of my 3 cats: Rosie, Cody, and Luna. It&#8217;ll make sense in approximately 6 seconds.</figcaption></figure></div><p>Consider a very basic class hierarchy involving the <strong>Felidae</strong> family (to use the most precise taxonomical term, look it up). </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zdm1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zdm1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 424w, https://substackcdn.com/image/fetch/$s_!zdm1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 848w, https://substackcdn.com/image/fetch/$s_!zdm1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 1272w, https://substackcdn.com/image/fetch/$s_!zdm1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zdm1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png" width="1456" height="1027" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1027,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:319344,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.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_!zdm1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 424w, https://substackcdn.com/image/fetch/$s_!zdm1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 848w, https://substackcdn.com/image/fetch/$s_!zdm1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.png 1272w, https://substackcdn.com/image/fetch/$s_!zdm1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe43e184f-0a97-4f84-9f9f-8b1fd06bdfeb_1508x1064.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>Here, the subclassing relationship implies that a <strong>Lion</strong> is &#8220;a kind of cat&#8221;. If this code was part of an open-source <strong>Animals</strong> package (and marked <strong>open</strong>, so subclassable in other modules), we could import it and subclass <strong>Cat</strong> ourselves, with a custom implementation of <strong>cry()</strong>.</p><p>Therefore, if you use a <strong>Cat</strong> subclass in your codebase, it might roar, since <strong>Lion</strong> is a possible subclass of <strong>Cat</strong>. Swift also needs to handle other possible implementations of <strong>cry()</strong> for any other subclass of feline*.</p><p>Since our <strong>.swift</strong> files are compiled independently**, the Swift compiler can&#8217;t be sure which implementation is going to be used where. This information is only available at runtime&#8202;. Until the object is actually created, we don&#8217;t know whether we&#8217;re dealing with a bog-standard kitty or the king of the jungle***. </p><blockquote><p><em>*Let me be clear, I mean &#8220;class&#8221; Swift-onomically. <a href="https://en.wikipedia.org/wiki/Taxonomy_(biology)">Taxonomically</a>, cats and lions are a Family, and they&#8217;re both from the class &#8220;Mammal&#8221;. A superclass if you will. Sh*t.</em></p><p><em>**<strong>.swift</strong> files compile independently when whole-module optimisation is not active. I&#8217;ll go into more detail in <strong>Making Your Code Go Faster</strong> in a moment.</em></p><p><em>***Shouldn&#8217;t it be &#8220;king of the savannah&#8221;?</em></p></blockquote><p>The virtual table isn&#8217;t magic at all.</p><p>It&#8217;s a list, built at compile-time for each subclass, mapping each function to its implementation in memory. </p><p>If <strong>Lion</strong> overrides <strong>cry()</strong>, then the table points at the instructions defined on <strong>Lion.cry()</strong>. </p><p>If it doesn&#8217;t override <strong>eat()</strong>, then the virtual table for <strong>Lion</strong> will point at the instructions defined in the <strong>Cat</strong> superclass.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6GWa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6GWa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 424w, https://substackcdn.com/image/fetch/$s_!6GWa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 848w, https://substackcdn.com/image/fetch/$s_!6GWa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 1272w, https://substackcdn.com/image/fetch/$s_!6GWa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6GWa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png" width="1124" height="844" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:844,&quot;width&quot;:1124,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:239196,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.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_!6GWa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 424w, https://substackcdn.com/image/fetch/$s_!6GWa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 848w, https://substackcdn.com/image/fetch/$s_!6GWa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.png 1272w, https://substackcdn.com/image/fetch/$s_!6GWa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F938c3710-43c7-469b-bc04-f1a4327b1961_1124x844.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>This is the <em>indirection</em> I was talking about before. </p><p>Table dispatch is slower than direct dispatch because at runtime, to dynamically dispatch to a function, the runtime first needs to:</p><ul><li><p>Jump the instruction pointer to the virtual table stored in the subclass type metadata in the binary.</p></li><li><p>Pick out the correct function pointer from this table.</p></li><li><p>Jump the instruction pointer, again, to the function&#8217;s memory address elsewhere in the binary.</p></li></ul><p>Cool. What about the other tables?</p><h4>Protocol Witness Tables</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!V6Ow!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V6Ow!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 424w, https://substackcdn.com/image/fetch/$s_!V6Ow!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 848w, https://substackcdn.com/image/fetch/$s_!V6Ow!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!V6Ow!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!V6Ow!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg" width="800" height="450" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:450,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!V6Ow!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 424w, https://substackcdn.com/image/fetch/$s_!V6Ow!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 848w, https://substackcdn.com/image/fetch/$s_!V6Ow!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!V6Ow!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff45d5ba8-dd61-4324-bf49-3f80ec2fa286_800x450.jpeg 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">&#8220;Witness me&#8221;&#8202; - Mad Max: Fury Road (2015)</figcaption></figure></div><p>Protocols allow developers to add polymorphism to types through <strong>composition</strong>, even to value types like structs or enums. Protocol methods are dispatched via <strong>Protocol Witness Tables</strong>.</p><p>The mechanism for these is the same as virtual tables: Protocol-conforming types contain metadata (stored in an <em>existential container*</em>), which includes a pointer to their witness table, which is itself a table of function pointers. </p><blockquote><p><em>*Existential containers are an underlying implementation detail of protocols. To understand these in more detail, check out the in-depth essential WWDC talk, <a href="https://developer.apple.com/videos/play/wwdc2016/416/">Understanding Swift Performance (2016)</a>.</em></p></blockquote><p>When executing a function on a protocol type, Swift inspects the existential container, looks up the witness table, then dispatches to the memory address of the function to execute. </p><p>It&#8217;s not necessarily all indirection and jumps though. </p><p>The witness table dispatch happens if the type you&#8217;re dispatching to is an <em><strong>abstract</strong></em><strong> </strong>protocol type. If you specify the <em><strong>concrete</strong></em> type of something conforming to the protocol, then the specific implementation of the code is known at compile-time, and can be dispatched statically. </p><p>(I&#8217;ll go into this in more detail in <strong>Building Up An Intuition</strong> soon)</p><h4>Then why use abstract types?</h4><p>Anything mockable, for instance. We often use abstract protocol declarations when performing <strong>dependency injection</strong>: we specify the protocol&#8202;; the interface our dependency conforms to&#8202;; without a concrete type, injecting an implementation at runtime. </p><p>Other times, we might have a <strong>Collection </strong>containing various protocol-conforming objects we want to iterate over. In these cases, method dispatch is via the witness table.</p><p>The term &#8220;witness table&#8221; is <a href="https://forums.swift.org/t/where-does-the-term-witness-table-come-from/54334/8">borrowed from constructive logic</a>, where proofs serve as<em> witnesses</em> for propositions. In my opinion, though, this kinda-sorta feels like a post-hoc justification&#8202;. &#8202;They already used the term &#8220;virtual tables&#8221; for dynamic dispatch with subclasses. I reckon our boy Lattner just needed a different phrase to distinguish the concept. </p><h4>Table Dispatch in Swift Intermediate Language</h4><p>As mentioned, there are two main ways to invoke dynamic dispatch in Swift.</p><p>First, let&#8217;s look at the vanilla virtual-table dispatch you might find in a language like Java or C++. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rfnU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rfnU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 424w, https://substackcdn.com/image/fetch/$s_!rfnU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 848w, https://substackcdn.com/image/fetch/$s_!rfnU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!rfnU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rfnU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png" width="1278" height="1152" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1152,&quot;width&quot;:1278,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:335631,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.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_!rfnU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 424w, https://substackcdn.com/image/fetch/$s_!rfnU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 848w, https://substackcdn.com/image/fetch/$s_!rfnU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!rfnU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6e08c2ed-42c2-4ac7-9ac4-12d0487b1d25_1278x1152.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>We can see the virtual tables (a.k.a. <strong>vtables</strong>, if you&#8217;re a cool kid) created in the SIL. <strong>DoubleIncrementer</strong> implements both methods, but only overrides one with a pointer to its own implementation:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CklH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CklH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 424w, https://substackcdn.com/image/fetch/$s_!CklH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 848w, https://substackcdn.com/image/fetch/$s_!CklH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 1272w, https://substackcdn.com/image/fetch/$s_!CklH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CklH!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png" width="1200" height="275.27472527472526" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:334,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:448319,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CklH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 424w, https://substackcdn.com/image/fetch/$s_!CklH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 848w, https://substackcdn.com/image/fetch/$s_!CklH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 1272w, https://substackcdn.com/image/fetch/$s_!CklH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb81798db-784d-49c1-8139-f3199ce3e7b0_3102x712.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Let&#8217;s see how it looks when we use a protocol: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!feT2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!feT2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 424w, https://substackcdn.com/image/fetch/$s_!feT2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 848w, https://substackcdn.com/image/fetch/$s_!feT2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 1272w, https://substackcdn.com/image/fetch/$s_!feT2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!feT2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png" width="1220" height="888" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:888,&quot;width&quot;:1220,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:253796,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.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_!feT2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 424w, https://substackcdn.com/image/fetch/$s_!feT2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 848w, https://substackcdn.com/image/fetch/$s_!feT2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.png 1272w, https://substackcdn.com/image/fetch/$s_!feT2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17ff1304-3f5b-493c-9411-77f7e63f28c4_1220x888.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>This time, we see a witness table (<strong>sil_witness_table</strong>) in the SIL we generate:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VrOq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VrOq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 424w, https://substackcdn.com/image/fetch/$s_!VrOq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 848w, https://substackcdn.com/image/fetch/$s_!VrOq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 1272w, https://substackcdn.com/image/fetch/$s_!VrOq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VrOq!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png" width="1200" height="332.967032967033" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:404,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:235313,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VrOq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 424w, https://substackcdn.com/image/fetch/$s_!VrOq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 848w, https://substackcdn.com/image/fetch/$s_!VrOq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.png 1272w, https://substackcdn.com/image/fetch/$s_!VrOq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F971cb4c2-b60f-4620-9676-e13c2e2fa12e_1930x536.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>In both of these very simple examples, the compiler actually ends up statically dispatching the <strong>main()</strong> function straight to the method implementation of <strong>increment()</strong>, bypassing the dispatch tables. Agh!</p><p>If you compile with optimisations, Swift drops the functions entirely and produces precomputed results at the call site. Dammit!</p><p>The compiler won&#8217;t give you what you want; it&#8217;ll give you what it thinks you need&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!B7Pt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B7Pt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 424w, https://substackcdn.com/image/fetch/$s_!B7Pt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 848w, https://substackcdn.com/image/fetch/$s_!B7Pt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 1272w, https://substackcdn.com/image/fetch/$s_!B7Pt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B7Pt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp" width="500" height="375" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:375,&quot;width&quot;:500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23778,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!B7Pt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 424w, https://substackcdn.com/image/fetch/$s_!B7Pt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 848w, https://substackcdn.com/image/fetch/$s_!B7Pt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 1272w, https://substackcdn.com/image/fetch/$s_!B7Pt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09b28195-4818-472b-8f4f-d03988ddf2fe_500x375.webp 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">Stupid, sexy, compiler!</figcaption></figure></div><div><hr></div><h2>Message Dispatch</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fuOO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fuOO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fuOO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fuOO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fuOO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fuOO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg" width="563" height="346" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:346,&quot;width&quot;:563,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!fuOO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fuOO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fuOO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fuOO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb159e71-209e-4fe3-92df-f38c9c3537c2_563x346.jpeg 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">It&#8217;s moderately more high-tech than this&#8202;. Image from <a href="https://www.pinterest.co.uk/pin/173810866844454868/">Pinterest</a></figcaption></figure></div><p>Message dispatch is the most dynamic tool in Swift&#8217;s repertoire of dispatch approaches. It&#8217;s so dynamic, the implementation of a method can be changed at runtime through <em>swizzling</em>. It&#8217;s so dynamic, it doesn&#8217;t actually even use Swift&#8202;. It lives in <a href="https://developer.apple.com/documentation/swift/using-objective-c-runtime-features-in-swift">the Objective-C runtime library</a>. Huh? </p><p>Message-dispatched function invocations are dispatched using the ObjC runtime&#8217;s <a href="https://stackoverflow.com/questions/982116/objective-c-message-dispatch-mechanism">objc_msgSend</a> function. Instances of Objective-C classes have an <strong>isa</strong> pointer which points to the &#8220;class object&#8221;&#8202;, &#8202;the implementation of the type in memory. </p><blockquote><p><em>What&#8217;s an isa pointer? Boy do I have an article for you!</em> </p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;bb797636-403e-475f-867d-0cd5d3be9d14&quot;,&quot;caption&quot;:&quot;Today I&#8217;m selling shovels. A treasure map. The equipment you need to tunnel through the Swift source code and mine out the nuggets of arcane knowledge reserved for C++ and compiler geeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;How to Learn the Swift Source Code&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-07-22T15:02:11.838Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LGzj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ab95ff2-d803-458d-9b6e-cfe56f3226ee_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/swift-source-code&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:168148655,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:14,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></blockquote><p><strong>objc_msgSend</strong> follows <strong>isa</strong> to the class, then inspects its table of method selectors. If the method is found, it&#8217;s executed. If not, then the runtime follows the <strong>super</strong> pointer to the superclass table. If the method is still is not found, the runtime iterates through the object hierarchy, until the method is found or it hits <strong>NSObject</strong>, the ObjC root object. </p><p>This table of method selectors is implemented as a <a href="https://buckleyisms.com/blog/the-case-for-message-passing-in-swift/">message passing dictionary</a>, which is mutable at runtime. This is how ObjC implements its famous <em>method swizzling</em>.</p><p>The ObjC runtime <a href="https://medium.com/@boredbanana/objective-c-runtime-notes-f7e36db4daf1">caches</a> memory addresses of methods as they&#8217;re used. Calling a cached method is about as fast as a regular table-dispatched function call, making message dispatch quite quick once the program has run for a while and &#8220;warmed up&#8221; the cache. </p><p>Look. </p><p>If you want my honest opinion, nobody implementing a language today would have even considered message dispatch&#8202;. It&#8217;s a legacy holdover from the fact that virtually all of Apple&#8217;s frameworks have been implemented in Objective-C since time immemorial, including Core Data, UIKit, and <a href="https://trinhngocthuyen.com/posts/tech/method-dispatch-in-swift/">Swift&#8217;s KVO</a>. </p><p>It&#8217;s pretty neat though. </p><h4>Message Dispatch in SIL</h4><p>To invoke message dispatch in Swift, you need two things: </p><ol><li><p>The <strong>@objc</strong> attribute, which tells the compiler to make a class, property, or method available to the Objective-C runtime.</p></li><li><p>The <strong>dynamic</strong> keyword, which tells the compiler to invoke the property or method via message dispatch. </p></li></ol><p>Let&#8217;s write our final <strong>main.swift</strong>: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KiGk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KiGk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 424w, https://substackcdn.com/image/fetch/$s_!KiGk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 848w, https://substackcdn.com/image/fetch/$s_!KiGk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 1272w, https://substackcdn.com/image/fetch/$s_!KiGk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KiGk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png" width="648" height="356" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:356,&quot;width&quot;:648,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:75605,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.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_!KiGk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 424w, https://substackcdn.com/image/fetch/$s_!KiGk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 848w, https://substackcdn.com/image/fetch/$s_!KiGk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.png 1272w, https://substackcdn.com/image/fetch/$s_!KiGk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46e3c141-b1ff-405c-a3c7-35353205887c_648x356.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>And now let&#8217;s take a look at the SIL output:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!masi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!masi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 424w, https://substackcdn.com/image/fetch/$s_!masi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 848w, https://substackcdn.com/image/fetch/$s_!masi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 1272w, https://substackcdn.com/image/fetch/$s_!masi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!masi!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png" width="1200" height="608.2417582417582" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:738,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:1177724,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!masi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 424w, https://substackcdn.com/image/fetch/$s_!masi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 848w, https://substackcdn.com/image/fetch/$s_!masi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.png 1272w, https://substackcdn.com/image/fetch/$s_!masi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0359788-ce9d-47e8-91d8-92194df08748_3486x1768.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><ol><li><p>Here, the <strong>objc_method</strong> on <strong>Incrementer</strong> is invoked in our <strong>main()</strong> function. <br>Note the <strong>#Incrementer.increment!foreign</strong> to denote that the method is using something outside of native Swift.</p></li><li><p>When you have an <strong>@objc</strong> method implemented with Swift, both a Swift flavour and an Objective-C flavour of the method are emitted in SIL. <br>This redacted SIL code is identical to the statically-dispatched logic we looked at earlier (since we will call into it!).</p></li><li><p>Here, in the <strong>@objc Incrementer.increment(_:)</strong>, <strong>[thunk]</strong> lets the Objective-C runtime statically dispatch to the Swift implementation of the method. <br>Using a separate ObjC function like this allows Swift-native code to call straight into the Swift version straight away (and eschew slower message dispatch).</p></li><li><p>Methods marked <strong>dynamic</strong> do not appear in the <strong>v_table</strong>, since regular table dispatch is not used to resolve the method call. </p></li></ol><h4>Message Dispatch. Huh. Yeah. What is it good for?</h4><p>Message dispatch is certainly not the hammer you want to smash into every programming nail, but it shines in the right use case. Take Realm for example <em>(&#8202;yes, I know it&#8217;s called </em>Atlas Device SDKs<em> now, but that&#8217;s also the lamest rebrand I&#8217;ve heard in my life)*</em>. </p><blockquote><p><em>*<a href="https://www.mongodb.com/docs/realm/sdk/">Atlas Device SDKs</a>, please sponsor my Substack.</em></p></blockquote><p>Using Realm on iOS, you need to mark the properties on your database objects <strong>@objc dynamic</strong>. This is to expose them to the Objective-C runtime. This enables message dispatch on the model properties, and hence powers key-value observation!</p><p>Under the hood, this KVO uses method swizzling to replace the getter and setter of a property with customised read/write methods. This in turn allows database objects to dynamically update whenever the underlying data is modified.</p><div><hr></div><h2>Making Your Code Go Faster</h2><p>This is all really nice theory. The whole article. Wow. Well done, Jacob. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G97U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G97U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 424w, https://substackcdn.com/image/fetch/$s_!G97U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 848w, https://substackcdn.com/image/fetch/$s_!G97U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!G97U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G97U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg" width="800" height="494" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/be2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:494,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!G97U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 424w, https://substackcdn.com/image/fetch/$s_!G97U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 848w, https://substackcdn.com/image/fetch/$s_!G97U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!G97U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe2f5f45-54fd-452b-92e5-f6318710ba92_800x494.jpeg 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 outside of impressing your wife with your stonking depth of comp-sci knowledge, theory isn&#8217;t useful unless you can apply it. </p><p>Let&#8217;s discuss how your knowledge of method dispatch can help your own code run faster and more efficiently. </p><h4>Reducing Dynamic Dispatch</h4><p>The compiler works hard to optimise your Swift code before anything runs.</p><p>From the Swift repo&#8217;s own explainer on SIL: </p><blockquote><p><em>If the static type of the class instance is known, or the method is known to be final, then the instruction is a candidate for <strong>devirtualization </strong>optimization. A devirtualization pass can consult the module&#8217;s </em><strong>VTables</strong><code> </code><em>to find the SIL function that implements the method and promote the instruction to a static </em><strong>function_ref</strong><em>.</em></p></blockquote><p>Outside the specific context of <em>trying to <strong>demonstrate bloody dispatch methods for a blog post*</strong></em>, this is optimisation is generally considered pretty useful. There are several things we can do as developers to help the compiler out, and speed up our Swift code.</p><blockquote><p><em>*I had to muck around with </em><code>swiftc -emit-sil</code><em> for a while to stop the compiler optimising away all my dynamic method calls in the SIL sample code.</em></p></blockquote><p>Since I am now one with the Swift compiler; I was unable to resist inlining this information here instead of <a href="https://github.com/apple/swift/blob/main/docs/OptimizationTips.rst#reducing-dynamic-dispatch">just linking you to the docs</a>. </p><p><strong>final</strong> and <strong>private</strong> keywords allow the compiler to optimise a class or method to use static dispatch, because it can infer there is no dynamic polymorphism on those methods. But this tip is largely redundant now that<strong> Whole Module Optimisation</strong> is on by default. The compiler processes a module&#8217;s files all together (rather than each <strong>.swift</strong> file individually, meaning <strong>internal</strong> classes and methods can be inferred as <strong>final</strong>.</p><p>Cross-module optimisation takes things a step further and enables optimisations like <strong>devirtualisation</strong> (dynamic to static) and <strong>inlining</strong> (static to inline) across module boundaries, even for public functions. </p><p>This is set at a conservative level by default, because these optimisations improve speed but can impact code size. </p><p>You can explicitly opt into more aggressive optimisations, using compiler flags in your module&#8217;s Package.swift:</p><pre><code>// Package.swift
targets: [
    .target(
        name: "MyAwesomeModule",
        swiftSettings: [
            .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
        ]
    )
]</code></pre><p>You can opt out using <strong>-disable-cmo</strong>.</p><h4>Performance Characteristics</h4><p>The actual performance impact of the dynamic dispatch is, usually, fairly small&#8202;: the additional layer of function call indirection is only a few extra CPU instructions, or clock cycles. </p><p>There are, however, two <strong>big</strong> ways in which dynamic dispatch has an impact on runtime performance: </p><ol><li><p>The compiler loses the ability to perform optimisations like <strong>inlining</strong> or <strong>precomputing</strong>.</p></li><li><p>Indirection can <strong>increase the likelihood of a cache miss. </strong>Since the location of a function isn&#8217;t known at runtime, instead of the CPU reading its instructions from the L1 cache (1ns), your program may need to fetch the function code from RAM (100ns).</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NMVM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NMVM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 424w, https://substackcdn.com/image/fetch/$s_!NMVM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 848w, https://substackcdn.com/image/fetch/$s_!NMVM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!NMVM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NMVM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg" width="700" height="397" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:397,&quot;width&quot;:700,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:35340,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NMVM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 424w, https://substackcdn.com/image/fetch/$s_!NMVM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 848w, https://substackcdn.com/image/fetch/$s_!NMVM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!NMVM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a384750-e0f7-4be6-9494-48c3b2919d77_700x397.jpeg 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">RAM is actually slow as balls.</figcaption></figure></div><h4><strong>Why can&#8217;t we just work out all the concrete types at compile-time?</strong></h4><p>I&#8217;m glad you asked.</p><p>The whole point of polymorphism is that concrete types aren&#8217;t fully known at compile-time, so runtime behaviour can vary. This allows us to write flexible code, where implementations aren&#8217;t instantly known the minute you type out your protocol. </p><p>But when we are bounded within a region of <em>known access control</em>, we <strong>can </strong>know the implementations at compile-time. </p><p>Consider the guidance the Swift team gives us about reducing dynamic dispatch&#8202;. <strong>final</strong>, <strong>private</strong>, and <strong>whole-module</strong> (or cross-module) optimisation.</p><p>This gives the compiler more <strong>information</strong>. </p><p>Therefore the compiler can work out whether a type is knowable at compile-time, and therefore whether it can be converted to static dispatch and all its consequent optimisations.</p><div><hr></div><h2>Building up an intuition</h2><p>Due to its support of <em>all the dispatch methods</em>, Swift has many unintuitive gotchas about how certain types of method are dispatched. </p><p>When you understand the underlying mechanisms of static and dynamic dispatch&#8202;, and the information available to the compiler, &#8202;we can actually work out how these quirks come about.</p><h4>The canonical example</h4><p>Protocols are commonly invoked to demonstrate this &#8220;odd quirk&#8221; (but not really) to your interns. With protocols, you can impact dispatch behaviour via the type declaration&#8202;. </p><p>See this example with a protocol, an implementation, and default methods on the protocol extension: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4qLI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4qLI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 424w, https://substackcdn.com/image/fetch/$s_!4qLI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 848w, https://substackcdn.com/image/fetch/$s_!4qLI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 1272w, https://substackcdn.com/image/fetch/$s_!4qLI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4qLI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png" width="1456" height="1284" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1284,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:417434,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.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_!4qLI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 424w, https://substackcdn.com/image/fetch/$s_!4qLI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 848w, https://substackcdn.com/image/fetch/$s_!4qLI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.png 1272w, https://substackcdn.com/image/fetch/$s_!4qLI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00f87d55-8bb9-433e-bf47-3e9fc879e7df_1506x1328.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>When you call into these functions, the type declaration you use when instantiating your class affects whether you get static or dynamic dispatch. </p><blockquote><p><em>Feel free to copy this code into a Swift playground and see for yourself!</em></p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Sm18!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Sm18!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 424w, https://substackcdn.com/image/fetch/$s_!Sm18!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 848w, https://substackcdn.com/image/fetch/$s_!Sm18!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 1272w, https://substackcdn.com/image/fetch/$s_!Sm18!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Sm18!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png" width="418" height="444" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:444,&quot;width&quot;:418,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:75654,&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://blog.jacobstechtavern.com/i/179912527?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.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_!Sm18!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 424w, https://substackcdn.com/image/fetch/$s_!Sm18!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 848w, https://substackcdn.com/image/fetch/$s_!Sm18!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.png 1272w, https://substackcdn.com/image/fetch/$s_!Sm18!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95f36767-b4cf-4462-bfe1-ee7ae225749c_418x444.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>Make sure to follow this, because it&#8217;s the most important for cementing your understanding: </p><ol><li><p>When we declare an object as an <strong>Animal</strong> type, the compiler knows to expect dynamic dispatch, since the type of the animal could be mutated or set elsewhere.</p></li><li><p><strong>cry()</strong>, which is a protocol requirement, gets dispatched via a witness table to the cat&#8217;s implementation. <br>Protocol requirement methods will dispatch via a <strong>sil_witness_table</strong> because the implementation isn&#8217;t necessarily definitive at compile-time*.</p></li><li><p>Calling <strong>sayHello()</strong> on the animal is statically dispatched to the protocol extension&#8217;s implementation, because non-requirement methods don&#8217;t use a witness table, and the type is known to be an <strong>Animal</strong>. </p></li><li><p>We can instantiate a <strong>Cat</strong> object, which conforms to the Animal protocol but has a definitive concrete type. <br>This gives the compiler a ton of information which will allow it to optimise things&#8202;: if the class was <strong>final</strong>, or whole-module optimisation was turned on, then the methods on <strong>Cat</strong> will be statically dispatched. <br>Otherwise, they will be dynamically dispatched via the <strong>Animal</strong> witness table.</p></li><li><p>When calling the <strong>cry()</strong> method on <strong>cat</strong>, the Swift Runtime doesn&#8217;t consult the protocol witness table at all, since the concrete type is known. <br>Therefore, it meows (either statically or dynamically, depending on how your project is set up). </p></li><li><p>Calling <strong>sayHello()</strong> is similarly executed by the runtime on the concrete cat type, either directly or through table dispatch. </p></li></ol><blockquote><p><em>*In this instance, the compiler can know the concrete type of Animal, however Swift does not necessarily optimise this away: optimisation from dynamic to static is great, but <strong>not</strong> when it actually changes the implementation of a method.</em></p></blockquote><h4>How to intuit dispatch</h4><p>At this point in the deep-dive, most contributors to Swift method dispatch discourse like to present a table with the types of entity (protocol, class, final class, extension, etc) and the type of dispatch it uses (conveniently ignoring the existence of whole-module optimisation). </p><p>In my opinion, though, it&#8217;s fundamentally unhelpful to attempt to memorise the various &#8220;gotchas&#8221;.. It&#8217;s exhausting, and more importantly, the compiler optimises away most of what you&#8217;re trying to memorise.</p><p>The trick? Just<strong> consider whether the memory location of the function is knowable at compile-time</strong>.<strong> </strong>If it&#8217;s possible, the compiler will do it.</p><ul><li><p><strong>struct</strong> methods? <br>Obviously static.</p></li><li><p>Methods on a <strong>class</strong>? <br>These can be made static, but only if the compiler can know the type at runtime.</p></li><li><p><strong>open class</strong> methods? <br>This probably has to use table dispatch to find classes in other modules.</p></li><li><p><strong>protocol</strong> requirement methods? <br>This always needs to use a witness table, even if the type is knowable, so that execution is consistent.</p></li><li><p><strong>protocol extension</strong> methods that aren&#8217;t protocol requirements? <br>These just live with the protocol in memory, so can be directly dispatched.</p></li></ul><p>Again, I&#8217;m trying *not* to give an exhaustive list, because now you have the power to work out most of these instances using dispatch theory.</p><div><hr></div><h2>Last Orders</h2><p>Look, I really wanted to show you a cool sample project that showed all these dispatch performances in detail: &#8202;setting up some <strong>structs</strong>, <strong>classes</strong>, and <strong>dynamic</strong> functions, then running some simple addition functions 1 million times each.</p><p>But the compiler kept inlining and precomputing everything! </p><p>After some time spent fighting these optimisations, attempting to get to grips with <strong>@inline(never)</strong>, and fighting my instincts to clean up the code, I admitted defeat. </p><p>Remember my plight the next time you run into a gotcha, some unexpected behaviour, with Swift, and just remember the compiler is trying its darnedest. </p><p>If you enjoyed this deep dive, and you&#8217;re hungry for more, consider another deep dive into the compiler:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;5d35439f-2d68-4643-af60-fdf3d89087cc&quot;,&quot;caption&quot;:&quot;Today I&#8217;m selling shovels. A treasure map. The equipment you need to tunnel through the Swift source code and mine out the nuggets of arcane knowledge reserved for C++ and compiler geeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;How to Learn the Swift Source Code&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-07-22T15:02:11.838Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LGzj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ab95ff2-d803-458d-9b6e-cfe56f3226ee_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/swift-source-code&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:168148655,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:14,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Just remember, folks: tip your compiler this Christmas.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><blockquote><p><em>This is a full re-write of one of my early, critically under-appreciated posts, back from when I had sub-1,000 subscribers. I&#8217;m hoping to upgrade some of my old classics from the vault to spread the joy to my new generation of fans. </em></p></blockquote><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;2d080621-2186-441a-9a92-4bef94f284bb&quot;,&quot;caption&quot;:&quot;Subscribe to Jacob&#8217;s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, &amp; indie projects in your inbox every two weeks.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;md&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;The Swift Method Dispatch Deep Dive&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2024-02-05T17:15:58.307Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bdf753b-e03d-461a-8485-b3b5c5156bf0_800x457.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/compiler-cocaine-the-swift-method&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:141071005,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:32,&quot;comment_count&quot;:1,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Inside Meta’s “iOS System Design” Interview]]></title><description><![CDATA[Double your salary on the inside track]]></description><link>https://blog.jacobstechtavern.com/p/ios-system-design</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/ios-system-design</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 25 Nov 2025 16:01:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!wWEK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.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_!wWEK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wWEK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!wWEK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!wWEK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!wWEK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wWEK!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:2984215,&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://blog.jacobstechtavern.com/i/179341231?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wWEK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!wWEK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!wWEK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!wWEK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a7d60be-a18a-4f1e-853b-ac700b921064_1680x1200.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>If you want to maximise your salary as an iOS developer, the second best thing you can do is work for Facebook.</p><blockquote><p><em>The best thing you can do, naturally, is read Jacob&#8217;s Tech Tavern.</em></p></blockquote><p>Salaries at big American tech companies are hard to believe if you don&#8217;t actually know anyone that works for them. Total comp packages for a Meta E5 (senior dev) in London range from &#163;199k to over &#163;400k.</p><p>This fact alone makes their interview process a worthwhile field of study.</p><p>Roles are competitive, but achievable, with intentional practice. I&#8217;ve seen multiple friends and colleagues bang their head against the interviews, year after year, until they finally landed. </p><p>Big tech interview loops contain 2 major technical components:</p><ul><li><p>Algorithmic interviews (a.k.a. &#8220;LeetCode&#8482;&#8221;)</p></li><li><p>The System Design Interview&#8482; </p></li></ul><p>You probably don&#8217;t need me to explain LeetCode, so I won&#8217;t. It&#8217;s a grind.</p><p>What&#8217;s more interesting is the system design component. For most Software Engineering roles, this typically means explaining how you would build the backend infrastructure for a service like Pastebin, Instagram, or Uber.</p><p>For iOS roles at Meta, however, they administer an <strong>&#8220;iOS-specific system design interview&#8221;</strong>. This is really very opaque and scary if you don&#8217;t have insider information, so I wrote this piece.</p><p>I personally went through Meta&#8217;s interview loop in 2024, and accidentally passed their first round <em>(but ended up dropping out of the process as I&#8217;d just landed a cool startup job)</em>.</p><p>Even better, I got an E5 Meta interviewer drunk. I got the inside-track for how this interview works, and how you are rated by Meta.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!q5Tl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!q5Tl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 424w, https://substackcdn.com/image/fetch/$s_!q5Tl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 848w, https://substackcdn.com/image/fetch/$s_!q5Tl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!q5Tl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!q5Tl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png" width="996" height="1152" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1152,&quot;width&quot;:996,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2368339,&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://blog.jacobstechtavern.com/i/179341231?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.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_!q5Tl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 424w, https://substackcdn.com/image/fetch/$s_!q5Tl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 848w, https://substackcdn.com/image/fetch/$s_!q5Tl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.png 1272w, https://substackcdn.com/image/fetch/$s_!q5Tl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1d5868-9717-40ae-8204-3e28ac626aad_996x1152.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">He shall remain nameless to protect the innocent</figcaption></figure></div><p>What&#8217;s really interesting is that Meta levels candidates entirely on the behavioural and system design interviews. That means the intern and the staff engineer get the same hiring bar on the LeetCode component. </p><p>Nailing the iOS System Design interview, therefore, makes all the difference.</p><div><hr></div><h2>iOS-Specific System Design</h2><p>This interview sounds very amorphous until you understand what it actually is. </p><p>My man on the inside summarised it in a single sentence that made me realise it was not so complicated after all:</p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/ios-system-design">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[When To Kill A Project]]></title><description><![CDATA[Dave Verwer's lessons from 30 years of failures (and some successes!)]]></description><link>https://blog.jacobstechtavern.com/p/when-to-kill-a-project</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/when-to-kill-a-project</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Thu, 20 Nov 2025 16:01:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GVEQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><em>Welcome to <strong>War Stories</strong>, where I partner with famous builders in the iOS space to share real-life stories from the frontlines. It&#8217;s part narrative, part interview, all swashbuckling fun. </em></p><p><em>Today I&#8217;m working with <a href="https://www.linkedin.com/in/daveverwer/">Dave Verwer</a>, the author of <a href="https://iosdevweekly.com">iOS Dev Weekly</a> and co-founder of the <a href="https://swiftpackageindex.com">Swift Package Index</a>, plus many other projects you might have heard of.</em></p><p><em>To catch all my War Stories, be sure to subscribe</em>:</p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><p>Without further ado, here&#8217;s <strong>When To Kill A Project:</strong></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GVEQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GVEQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!GVEQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!GVEQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!GVEQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GVEQ!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:1993008,&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://blog.jacobstechtavern.com/i/178878712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GVEQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!GVEQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!GVEQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!GVEQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa1e73d-ffa3-4b9b-90c1-725326ef838a_1680x1200.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><blockquote><p><em>&#8220;You have to really carefully cut the bits that aren&#8217;t working, and feed the bits that are working.&#8221; <br>&#8212; Dave Verwer</em></p></blockquote><p>You might know him from <a href="https://iosdevweekly.com">iOS Dev Weekly</a>, but<em> </em>Dave&#8217;s early career reminds me of <a href="https://www.linkedin.com/in/jenhsunhuang/details/experience/">another famous LinkedIn profile</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W1eo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W1eo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 424w, https://substackcdn.com/image/fetch/$s_!W1eo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 848w, https://substackcdn.com/image/fetch/$s_!W1eo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 1272w, https://substackcdn.com/image/fetch/$s_!W1eo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W1eo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png" width="822" height="240" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/efbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:240,&quot;width&quot;:822,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:26768,&quot;alt&quot;:&quot;&quot;,&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://blog.jacobstechtavern.com/i/178878712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.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_!W1eo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 424w, https://substackcdn.com/image/fetch/$s_!W1eo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 848w, https://substackcdn.com/image/fetch/$s_!W1eo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 1272w, https://substackcdn.com/image/fetch/$s_!W1eo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefbeb6fe-249e-4c50-a1ea-4784801477f3_822x240.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><p>When I asked for tips about how to become a CTO within 10 years, Dave explained it wasn&#8217;t quite how it looked. Instead, it was a combination of growing up with the company as it scaled, working way too hard early on, and being the person to take the business online. </p><p>Since 2006, Dave has mostly run his own software businesses. When running your own company, you can just <em>do things</em>, so day-to-day work (as well as work-life balance), varies massively based on current projects and commitments.</p><p>Dave very modestly refers to himself as <em>&#8220;not that good at coding&#8221;</em> (which was deeply validating to my impostor syndrome), and explained his strengths lie in being a generalist, who enjoys getting stuck into all the aspects of running a small business: design, coding, research, writing, even doing the accounts.</p><p>One more very critical skill is <strong>knowing when to kill a project</strong>.</p><p>We discussed several of these projects, both successes and failures, and hammered out what we can learn from each of them. </p><div><hr></div><h2>iOS Dev Survey </h2><blockquote><p><em>Focus on what&#8217;s working, kill whatever isn&#8217;t. <br>&#8212; Dave Verwer</em></p></blockquote><p>Dave wanted to do this for ages. Fortunately, since you can just do things, he did.</p><p>In 2020, he orchestrated the largest ever public Apple platform developer survey.</p><p>Dave&#8217;s decade spent cultivating a newsletter audience made him one of the only people in the world who could pull this off, and he managed it in a big way: 2,290 developers spent ~30 minutes each filling out a comprehensive survey with the promise that all the data people contributed will be made public in aggregate form. </p><p>Dave grinded for months to prepare the questionnaire, set up the website, land some sponsors, market the survey, process the data, and write commentary. It was virtually certain to be a hit.</p><p>And. </p><p>Crickets.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VkZo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VkZo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 424w, https://substackcdn.com/image/fetch/$s_!VkZo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 848w, https://substackcdn.com/image/fetch/$s_!VkZo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 1272w, https://substackcdn.com/image/fetch/$s_!VkZo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VkZo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png" width="859" height="552" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:552,&quot;width&quot;:859,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Screenshot 2025-11-03 at 15.41.21.png&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 2025-11-03 at 15.41.21.png" title="Screenshot 2025-11-03 at 15.41.21.png" srcset="https://substackcdn.com/image/fetch/$s_!VkZo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 424w, https://substackcdn.com/image/fetch/$s_!VkZo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 848w, https://substackcdn.com/image/fetch/$s_!VkZo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.png 1272w, https://substackcdn.com/image/fetch/$s_!VkZo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0f2ca11-1ab2-48ac-8b40-289d30750511_859x552.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"><a href="https://iosdevsurvey.netlify.app/2019/">The site is still live. I had a really good time going through the data and commentary</a></figcaption></figure></div><p>Despite the enthusiasm from respondents, excitement from sponsors, fascinating analysis, and huge time investment, hardly anyone actually read the survey results.</p><p>As soon as it was clear it wasn&#8217;t going to be successful, Dave proactively refunded the sponsors (many of whom he still partners with). Reputation is everything when your business is trust. </p><p>While the 2019 survey was a flop, a few community members asked whether they could keep it going, and tried again next year. Dave agreed to hand it over, support where needed, and help with publicity, but that added up to a lot of work. When the second survey (still completed by 1,229 devs!) still failed to garner interest, Dave killed it, as it still ate up a lot of his time. </p><p>The key lesson here is that you can never predict when something will or won&#8217;t work. But you win in the long-term by knowing when to quit, and doing right by everyone.</p><div><hr></div><h2>Tackle Fishing </h2><blockquote><p><em>Market research is essential. <br>&#8212; Dave Verwer</em></p></blockquote><p>Dave&#8217;s company was on a roll after a big success with the <a href="https://www.cultofmac.com/reviews/launch-balloons-from-your-iphone-to-the-world">Balloons app</a>, and was looking for their next hit. </p><p>One of his co-founders was friends with a minor local celebrity in the fishing world. While at the pub, they had the idea to put his fishing knowledge into an app: <em>Tackle Fishing</em>. The team went all-in on production value, even getting a full-time illustrator on staff to make beautiful artwork with parallax-effect animation. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!89B4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!89B4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 424w, https://substackcdn.com/image/fetch/$s_!89B4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 848w, https://substackcdn.com/image/fetch/$s_!89B4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 1272w, https://substackcdn.com/image/fetch/$s_!89B4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!89B4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png" width="1456" height="701" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:701,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1137715,&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://blog.jacobstechtavern.com/i/178878712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.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_!89B4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 424w, https://substackcdn.com/image/fetch/$s_!89B4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 848w, https://substackcdn.com/image/fetch/$s_!89B4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.png 1272w, https://substackcdn.com/image/fetch/$s_!89B4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F488df2ab-b6bb-4dc7-ab60-b39290e9fdb3_1912x920.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">Recovered 2x-size designs from Tackle Fishing. Unfortunately, the full artwork and animated parallax effect are lost to time. </figcaption></figure></div><p>The business model was simple: you pay to download the app <em>&#129401; (ah, better times).</em></p><p>But in their excitement to ship, the team forgot an important step: Market research.</p><p>If they spoke to users and focus-grouped some fisherfolk, they&#8217;d have noticed a big problem with the concept:</p><p>You go fishing to relax, become one with nature, and clear your mind. The <em>last</em> thing an angler wants to do is look at their phone.</p><p>The pretty clear lesson here is to <em>talk to your users</em>. Oh, and don&#8217;t make apps for your mates based on a conversation at a pub. But we can go deeper than that: when doing market research, <strong>never</strong> ask someone if they&#8217;d pay for something*.</p><p>Paying hypothetical money is free, so people will happily fluff up your imaginary future revenues. People pay to have their needs met. Ask about everything <em>around</em> the money, and identify the needs. </p><blockquote><p><em>*I made this exact mistake with <a href="https://blog.jacobstechtavern.com/p/my-terrible-startup-architecture">my first startup</a>, where our market research indicated that people would </em>totally<em> pay $10-100 a month to offset their carbon footprint. They did not.</em></p></blockquote><div><hr></div><h2>AppReviewTimes </h2><blockquote><p><em>Even successful projects have an expiration date. <br>&#8212; Dave Verwer</em></p></blockquote><p>If, like me, you began releasing apps around 2016, it might not be obvious why AppReviewTimes was a hit.</p><p>In the early App Store, review times were <em>bad</em>. Really bad. Like a-whole-month-of-waiting bad. A-month,-then-you-get-rejected,-then-you-have-to-resubmit-and-wait-several-more-weeks-for-another-review bad. It was bad, basically.</p><p>Identifying this common pain, Dave hacked together a simple Rails program to scrape the Twitter (RIP) API (also RIP) for <em>#iosreviewtime</em> and <em>#macreviewtime</em> hashtags, crowdsourcing data in real-time and parsing out averages. This job ran hourly and updated a static web page (the best kind of website).</p><p>Dave heard from a few people who would know that the numbers matched the reality of the queue size pretty well. The sample size of ~100 Tweets/day gave enough data to make the site accurate, and provided a solid alternative to refreshing the App Review status page every hour*.</p><blockquote><p><em>*If someone can do the same thing for the <a href="https://substack.com/leaderboard/technology/paid">Substack Tech leaderboard</a> please tell me</em></p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_27A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_27A!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 424w, https://substackcdn.com/image/fetch/$s_!_27A!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 848w, https://substackcdn.com/image/fetch/$s_!_27A!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 1272w, https://substackcdn.com/image/fetch/$s_!_27A!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_27A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png" width="1250" height="653" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:653,&quot;width&quot;:1250,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:126214,&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://blog.jacobstechtavern.com/i/178878712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.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_!_27A!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 424w, https://substackcdn.com/image/fetch/$s_!_27A!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 848w, https://substackcdn.com/image/fetch/$s_!_27A!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.png 1272w, https://substackcdn.com/image/fetch/$s_!_27A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faff1d5c6-e459-421f-9ee0-1c18fb38f4ac_1250x653.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"><a href="https://web.archive.org/web/20141101122019/http://appreviewtimes.com/">appreviewtimes.com at November 1, 2014</a></figcaption></figure></div><p>Nothing went wrong here. The project was a smash hit, with tens of thousands of iOS and macOS devs checking it to feel better about their career choices every day.</p><p>The project started to become obsolete when Phil Schiller took over the App Store. In his first 6 months, average review times nosedived to a few days. Job done. Time to shut it down.</p><p>People encouraged Dave to keep the site up, lest Apple get lax with times again and they backslide. But with faster review times, fewer people checked the site, and less people Tweeted review times. Without a sufficient sample size, data grew less accurate, meaning there was no longer any reason <em>or</em> ability to keep the site active.</p><p>There was no business model with the site. Dave briefly played with ads, but those only work if time-on-site averages more than a couple of seconds. The most money the site ever made was eventually selling the domain: a gaming company bought it as an SEO play, to create high-quality backlinks for themselves. Dave struggled a bit with the decision of whether to sell it for that purpose, but it had been a couple of years since the site had stopped functioning and traffic had almost completely ceased.</p><p>With some projects, you <em>want</em> to shut them down. AppReviewTimes is a perfect example. See also, libraries where Apple upgrades its API to include the functionality. Apple is taking over maintenance! That&#8217;s a huge win.</p><p>Dave deftly sidestepped credit for improving review times, pointing squarely at Phil Schiller for the improvements. The most I got out of him was that <em>maybe</em> AppReviewTimes helped put it on Phil&#8217;s radar.</p><div><hr></div><h2>Swift Package Index </h2><p>This project is <a href="https://swiftpackageindex.com">still going strong</a>, so doesn&#8217;t quite fit the <em>&#8220;how to kill a project&#8221;</em> theme, but I kept it anyway because I found it interesting.</p><p>Swift Package Index was a prime example of skating to where the puck was headed. While at WWDC, by the giant escalators at Moscone: he had a thought that it seemed likely Apple would extend SPM support to iOS the year after.</p><p>This opened an opportunity. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hYpD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hYpD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 424w, https://substackcdn.com/image/fetch/$s_!hYpD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 848w, https://substackcdn.com/image/fetch/$s_!hYpD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!hYpD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hYpD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg" width="550" height="412" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:412,&quot;width&quot;:550,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:57129,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/178878712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hYpD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 424w, https://substackcdn.com/image/fetch/$s_!hYpD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 848w, https://substackcdn.com/image/fetch/$s_!hYpD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!hYpD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e7b49e-6f5e-4882-bec5-617cfb4e1530_550x412.jpeg 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">Moscone West convention center, from <a href="https://media-cdn.tripadvisor.com/media/photo-s/13/87/28/be/escalators-to-get-from.jpg">tripadvisor</a>  </figcaption></figure></div><p>Dave built a prototype with a few key principles in mind: Separate the index from the delivery mechanism (unlike Cocoapods). No crawling; ensure intentionality by requesting devs <a href="https://github.com/SwiftPackageIndex/PackageList/blob/main/packages.json">make a PR into a large list of packages</a>. Read the JSON, download manifests, process the packages, and throw them into a database.</p><p><a href="https://github.com/finestructure">Sven</a> emailed Dave with a suggestion for the site: integrate his <a href="https://github.com/finestructure/Arena">Arena</a> project so that devs could instantly test packages in a playground. They chatted on a call and agreed that to be a success with the community, the site also needed to be open-source and written in Swift rather than Rails.</p><p>Work on the Swift Package Index began a few days later.</p><p>They launched <em>just</em> before the next year&#8217;s WWDC announcement of SPM support for iOS, positioning themselves to become the default choice for package discovery.</p><p>I&#8217;m eternally fascinated by <a href="https://blog.jacobstechtavern.com/p/the-great-connection-pool-meltdown">iOS devs building into cloud-hosted devtools</a>, so spent extra time picking Dave&#8217;s brain about the infra. I asked about the 25% number from the <a href="https://www.swift.org/blog/nightly-swift-sdk-for-android/">Swift for Android announcement</a>. Basically, it was fairly straightforward to <a href="https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/pull/3803">add WASM and Android to their compatibility matrix</a>, which builds <em>each package</em> against <em>each version</em> of the Swift toolchain, on <em>each platform</em>, <em>each time</em> a package update is pushed.</p><p>So 25% was the <a href="https://swiftpackageindex.com/blog/adding-wasm-and-android-compatibility-testing">proportion of Swift packages that successfully compiled</a> when run using the Swift for Android toolchain.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-Gjc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-Gjc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 424w, https://substackcdn.com/image/fetch/$s_!-Gjc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 848w, https://substackcdn.com/image/fetch/$s_!-Gjc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 1272w, https://substackcdn.com/image/fetch/$s_!-Gjc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-Gjc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png" width="615" height="250" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:250,&quot;width&quot;:615,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24079,&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://blog.jacobstechtavern.com/i/178878712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.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_!-Gjc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 424w, https://substackcdn.com/image/fetch/$s_!-Gjc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 848w, https://substackcdn.com/image/fetch/$s_!-Gjc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.png 1272w, https://substackcdn.com/image/fetch/$s_!-Gjc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F655d0830-b0b4-45b1-96a5-b93aa807d6bd_615x250.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"><a href="https://swiftpackageindex.com/Alamofire/Alamofire/builds">Compatibility matrix for Alamofire</a></figcaption></figure></div><p>The infra is neat: a combination of a big MacStadium cluster of eight M3 Ultra Macs running Apple platform builds 24/7, and an Azure cluster for Linux, WASM, and Android. Very generous contributions from Apple, MacStadium, Microsoft, and the community pay to host all this. Running a popular open source project means people will often happily help cover your costs.</p><div><hr></div><blockquote><p><em>Thanks again to <a href="https://www.linkedin.com/in/daveverwer/">Dave Verwer</a> for taking the time to share his War Stories with me! </em></p><p><em>If you aren&#8217;t already on them, subscribe to <a href="https://iosdevweekly.com">iOS Dev Weekly</a> and start using the <a href="https://swiftpackageindex.com">Swift Package Index</a> today!</em></p><p><em>If you have a story you&#8217;d like to share, <a href="https://www.linkedin.com/in/jacobmartinbartlett/">get in touch</a>! </em></p><p><em>If you aren&#8217;t a subscriber to Jacob&#8217;s Tech Tavern, get every War Story (and much more) by subscribing here:</em></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[2025: The Year SwiftUI Died ]]></title><description><![CDATA[Rediscovering my love for the Classic UIKit Stack&#8482;]]></description><link>https://blog.jacobstechtavern.com/p/the-year-swiftui-died</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/the-year-swiftui-died</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Mon, 17 Nov 2025 16:03:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Hb7o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.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_!Hb7o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Hb7o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!Hb7o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!Hb7o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!Hb7o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Hb7o!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:4566938,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Hb7o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!Hb7o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!Hb7o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!Hb7o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f634d6-203c-448e-973a-ac4c5f70beac_1680x1200.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><h2>2019: Early adoption</h2><p>SwiftUI released in 2019, to tremendous excitement across the community. Unfortunately, it <em>really</em> sucked for that first year. </p><p>I was building a <a href="https://blog.jacobstechtavern.com/p/the-side-hustle-from-hell">satanic side hustle</a> at the time, and figured I&#8217;d go all-in. I blindly cobbled together a global @EnvironmentObject to run the prototype. Push navigation was mostly broken, so I was forced to make <em>every</em> screen transition a modal. I fell in love with the flawed framework.</p><p>By the time I did <a href="https://blog.jacobstechtavern.com/p/my-terrible-startup-architecture">a real startup</a> the next year, I was confident enough to make a proper bet on SwiftUI. This second version, on iOS 14, was much more stable. SwiftUI let me ship faster than I dreamed possible with UIKit. By <a href="https://blog.jacobstechtavern.com/p/swiftui-apps-at-scale">my third startup</a>, I targeted iOS 15+ and churned out screens like a maniac.</p><div><hr></div><p></p><div><hr></div><p></p><div><hr></div><p><em><strong>Like all great writers, my story has a 6-year time skip.</strong></em></p><div><hr></div><p></p><div><hr></div><p></p><div><hr></div><h2>2025: The summer everything changed</h2><p>Two twin technological happenstances collided this summer, transforming the way I work day-to-day:</p><p>Firstly, UIKit <a href="https://developer.apple.com/videos/play/wwdc2025/243/">got some love</a> from Apple. All of a sudden, the iOS 17 <strong>@Observable</strong> macro was ported to UIKit, alongside <strong>updateProperties()</strong>, a new view delegate method. It was even back-deployed to work on iOS 18.</p><p>Perhaps the eternal MVVM debate between Combine, RxSwift, closures, and binding libraries can finally be put to rest. Or, maybe it will just <a href="https://xkcd.com/927/">make the argument worse</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wjf3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wjf3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 424w, https://substackcdn.com/image/fetch/$s_!Wjf3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 848w, https://substackcdn.com/image/fetch/$s_!Wjf3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 1272w, https://substackcdn.com/image/fetch/$s_!Wjf3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wjf3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png" width="937" height="604" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:604,&quot;width&quot;:937,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48725,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.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_!Wjf3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 424w, https://substackcdn.com/image/fetch/$s_!Wjf3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 848w, https://substackcdn.com/image/fetch/$s_!Wjf3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.png 1272w, https://substackcdn.com/image/fetch/$s_!Wjf3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b89ecd2-27b2-4f39-8536-c7a75812283e_937x604.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"><a href="https://quickbirdstudios.com/blog/combine-vs-rxswift/">Funny little 2019 comic from QuickBird</a></figcaption></figure></div><p>Secondly, agentic AI tools took off in a big way. Improvement in context windows, foundation models, and the tool calling innovation triggered an inflection point where CLI tools started <a href="https://blog.jacobstechtavern.com/p/claude-code-productivity">working really well</a>. Pasting code into ChatGPT now feels a bit &#8216;90s.</p><div><hr></div><h2>Why do people use iOS?</h2><p>There&#8217;s a reason Apple is easy-breezy* when it comes to open-sourcing <a href="https://github.com/swiftlang/swift">Swift</a>, <a href="https://github.com/apple-oss-distributions/xnu">xnu</a>, <a href="https://github.com/swiftlang/swift-corelibs-libdispatch">libdispatch</a>, and <a href="https://github.com/swiftlang/swift-foundation">Foundation</a>. There are myriad security, community goodwill, and cross-platform benefits from keeping these low-level frameworks in the open.</p><blockquote><p><em>*I&#8217;m sure there are several Apple engineers (that aged 20 years during open-sourcing negotiations with legal) who may disagree with the term &#8220;easy-breezy&#8221;.</em></p></blockquote><p>When it comes to SwiftUI, UIKit, Core Animation, and most system libraries, however, Apple is ruthlessly guarded. </p><p>The difference is clear: Apple is in the hardware business. Integrated system UX is a core competitive advantage, and so Apple does <em>not</em> want you to enjoy their UI frameworks on other people&#8217;s platforms.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_hLA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_hLA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_hLA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_hLA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_hLA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_hLA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg" width="504" height="426" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:426,&quot;width&quot;:504,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!_hLA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_hLA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_hLA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_hLA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff223c9c6-8dab-4b76-95b4-9fa96d2d686a_504x426.jpeg 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">Mac OS X (10.0) architecture. Aqua, the characteristic system design language, sits above everything</figcaption></figure></div><p>The secret sauce of iOS has, from day 1, been its characteristic look and feel, what Apple calls the <em>human interface</em>: Interaction. Responsiveness. Animation.</p><p>When you drill down into the limits of these 3 pillars, you will find the gap between UIKit and SwiftUI is starkest. </p><div><hr></div><h2>Is SwiftUI ready for production?</h2><p>For years, developers have asked <em><a href="https://blog.jacobstechtavern.com/p/swiftui-apps-at-scale">is SwiftUI production-ready</a>?</em> </p><p>For years, the answer has been <em>yes, but</em>.</p><p>SwiftUI gets better every year, but is eternally on the long road to parity with UIKit. Even today, <a href="https://x.com/jacobtechtavern/status/1916947571974525169">basic stuff like camera previews</a> need to come wrapped in a UIHostingController.</p><p>SwiftUI also suffers worse performance out-of-the-box due to overhead from diffing view states and dynamic layout computation. This is <a href="https://developer.apple.com/videos/play/wwdc2025/256/">being worked on</a>, but is fundamentally an architectural choice that may never quite be as fast as UIKit. <a href="https://blog.jacobstechtavern.com/p/swiftui-scroll-performance-the-120fps">Every magic system has a cost</a>.</p><p>Everybody forgave SwiftUI&#8217;s shortcomings because of the undeniable boost to development speed and the tidy ease-of-use the API offers.</p><p>But what happens when you&#8217;re no longer writing every line of code manually?</p><div><hr></div><h2>Is SwiftUI dead?</h2><p>This year, UIKit quietly became production-ready again, with Apple granting access to modern <strong>@Observable</strong> macros and introducing <strong>updateProperties()</strong>. </p><p>Simultaneously, agentic AI tooling has trivialised the overhead of writing imperative layout boilerplate. Two key disadvantages of UIKit, slow development and verbose APIs, have been negated. The models are also trained on <em>mountains </em>of UIKit code and docs. Good luck one-shooting fresh SwiftUI APIs like <a href="https://developer.apple.com/videos/play/wwdc2025/256/?time=1435">TextEditor</a>.</p><p>In 2025, the question is unavoidable: </p><p><em>Should you start migrating back to UIKit?</em></p><p>We need to understand whether SwiftUI can ever fully match UIKit in API capability and performance. Let&#8217;s look at the code that reveals the definitive answer.</p><p>I won&#8217;t tell you how to live your life, but if you want the optimal UX for your users, maximum animation performance, and total control over interactions, <strong>UIKit will remain the undisputed king</strong>.</p><div><hr></div><h2>Delegates don&#8217;t actually suck</h2><p>I almost cried last year when I touched <strong>UIScrollViewDelegate</strong> for the first time since 2019. </p><p>I was building a cute interaction that animated a line of emojis along a circular path, with their motion along the circle linked to your scroll offset. I could trivially access <strong>scrollView.contentOffset.y</strong> from the <strong>scrollViewDidScroll(_:)</strong> delegate method.</p><p><em><strong>Do you know <a href="https://www.swiftbysundell.com/articles/observing-swiftui-scrollview-content-offset/">how hard this is</a> with SwiftUI preference keys!?</strong></em></p><p>To be completely fair to SwiftUI, <strong><a href="https://developer.apple.com/documentation/swiftui/view/onscrollgeometrychange(for:of:action:)">onScrollGeometryChange</a> </strong>(iOS 18) can do this now. At the time, I was supporting iOS 17 and couldn&#8217;t touch it.</p><p>But there are <em>hundreds</em> of UIKit delegate methods that remain unsupported, like <strong>scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)</strong>.</p><p>Even if SwiftUI achieves parity with the full <strong>UIScrollViewDelegate</strong>, we are subjected to a combinatorial explosion of memorisation for new views, view modifiers, and their respective positions on the view hierarchy. </p><p>Don&#8217;t even get me <em>started</em> on namespacing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VNuc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VNuc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 424w, https://substackcdn.com/image/fetch/$s_!VNuc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 848w, https://substackcdn.com/image/fetch/$s_!VNuc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 1272w, https://substackcdn.com/image/fetch/$s_!VNuc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VNuc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png" width="693" height="251" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:251,&quot;width&quot;:693,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:40485,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.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_!VNuc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 424w, https://substackcdn.com/image/fetch/$s_!VNuc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 848w, https://substackcdn.com/image/fetch/$s_!VNuc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.png 1272w, https://substackcdn.com/image/fetch/$s_!VNuc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2eb4f985-0208-458a-952e-24e51afd22b2_693x251.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">You&#8217;re more or less allowed to apply every view modifier to every view in SwiftUI. </figcaption></figure></div><p>It almost feels like&#8230; <em>maybe delegates were actually quite a good pattern</em> for implementing the iceberg of nuance underneath the world&#8217;s most complex UI system.</p><p><em>That&#8217;s actually a pretty great metaphor&#8230;</em></p><div><hr></div><h2>The UIKit Iceberg </h2><p>This is the case for pretty much every SwiftUI API that exists. Porting everything from a nearly-20-year-old framework isn&#8217;t happening anytime soon.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zd2a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zd2a!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 424w, https://substackcdn.com/image/fetch/$s_!zd2a!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 848w, https://substackcdn.com/image/fetch/$s_!zd2a!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 1272w, https://substackcdn.com/image/fetch/$s_!zd2a!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zd2a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png" width="726" height="1105" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1105,&quot;width&quot;:726,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:819015,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.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_!zd2a!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 424w, https://substackcdn.com/image/fetch/$s_!zd2a!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 848w, https://substackcdn.com/image/fetch/$s_!zd2a!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.png 1272w, https://substackcdn.com/image/fetch/$s_!zd2a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c6aeaf3-43a6-4331-bb07-e406abf2b9a2_726x1105.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><div><hr></div><h2>My controversial opinion about architecture </h2><p>UIKit lends itself inevitably to &#8220;complex&#8221; architectures, such as MVC, MVVM, and VIPER. Often, you&#8217;ll split your view controller into files for every delegate applied, and every link in the chain of data-flow.</p><p>SwiftUI lends itself to simpler architectures, such as the very hot MV approach.</p><p><strong>But here&#8217;s my edgy opinion:</strong></p><p>The more complex your screen-level architecture is, the harder it is to <strong>write</strong> code. But the easier it is to <strong>read</strong>. If you keep strict standardisation, you&#8217;ll always know where the gesture interactions will live, and what route your data takes as it propagates from tap, to model, to animation. </p><p>The simpler your architecture is, the easier it is to write code. <a href="https://blog.jacobstechtavern.com/p/enums-and-design-systems">With a good design library</a>, you can smash out a SwiftUI screen in an hour. The more you can reduce services into property wrappers, the faster you can ship.</p><p>But God help the next engineer who touches it.</p><p>The default standardisation from MV is, essentially, <em>&#8220;put the stuff wherever&#8221;</em>. It just doesn&#8217;t lend itself to consistency. Gesture handling will sit on the view that feels the most convenient at the time. If you&#8217;re lucky, interaction code sit vertically near to your state, otherwise you&#8217;ll just have to search the file(s) to hunt down what touches the data and when.</p><p>VIPER is a pain in the arse to write, but frankly, I always knew where to find what I needed. </p><div><hr></div><h2>AI + The Classic UIKit Stack&#8482; = &#10084;&#65039;</h2><p>This summer, I&#8217;ve been making a lot of prototypes, and I&#8217;ve been loving the workflow.</p><p>I&#8217;m rediscovering what makes UIKit so great.</p><p>It&#8217;s lightweight. It&#8217;s performant. I am not hand-coding any constraint boilerplate.</p><p>Any interaction I can dream up was built a decade ago. I don&#8217;t have to recall or research whether it has been ported yet. It <em>just works</em>. </p><p>And a lot of the time, for a complex screen, the code is just easier to read. Which you <em>kind of</em> want when you aren&#8217;t typing everything, because effort shifts towards code review of the output.</p><p>I wanted to whip up a really simple prototype for you to demonstrate all the ways UIKit is now easier to work with, but accidentally ended up going way overboard and building a full application. It was super fun, I actually can&#8217;t stop myself.</p><p>It&#8217;s an app that lets you create and edit collages from your photos, apply Metal shaders to them for cool effects, and save them to a gallery. </p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;4b22eb1e-f673-4384-ae85-b5f8bb0fb10b&quot;,&quot;duration&quot;:null}"></div><p>Every property, transformation, shader ordering, and image file path is stored on SwiftData, meaning that you can save and edit each photo any time you come back to them. </p><p>Naturally, I open-sourced it just for this post (prompts n&#8217; all), to demonstrate how nice this workflow is.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/jacobsapps/ClassicUIKit&quot;,&quot;text&quot;:&quot;View my code&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/jacobsapps/ClassicUIKit"><span>View my code</span></a></p><p>I&#8217;m going to take you through my process of smashing the app out over a few hours, and give you a gentle reminder of all the beautiful things that UIKit makes really easy for you, as well as demo-ing the new UIKit <strong>@Observable</strong> pattern. </p><div><hr></div><h2><strong>Prompts and one-shotting</strong></h2><p>Obviously, when you&#8217;re working on a live, complex, production app, I&#8217;d recommend being <strong>way</strong> closer to the code, and making smaller changes. But this began almost as a throwaway example app for this article, and I got carried away. </p><p>If you actually care about quality, then one-shotting with AI is a myth. But you can get pretty damn close with a clear prompt and a good eye for code review.</p><p>The secret is actually not a secret at all. You just need to explicitly detail every requirement. If you&#8217;re doing it properly, this might take a good hour. You don&#8217;t want to skimp on any details or interactions. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uK84!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uK84!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 424w, https://substackcdn.com/image/fetch/$s_!uK84!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 848w, https://substackcdn.com/image/fetch/$s_!uK84!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 1272w, https://substackcdn.com/image/fetch/$s_!uK84!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uK84!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png" width="894" height="576" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:576,&quot;width&quot;:894,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:152309,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.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_!uK84!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 424w, https://substackcdn.com/image/fetch/$s_!uK84!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 848w, https://substackcdn.com/image/fetch/$s_!uK84!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.png 1272w, https://substackcdn.com/image/fetch/$s_!uK84!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1392ff3-f867-44ed-ad25-17acfbf40772_894x576.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"><a href="https://github.com/jacobsapps/ClassicUIKit/blob/main/PROMPT.md">My initial prompt</a></figcaption></figure></div><p>Before you do anything, you need to create the basic project template in Xcode, because the clanker will get the Info.plist and build settings very wrong.</p><div><hr></div><h2>Actually reading your code</h2><p>After your initial prompt, it&#8217;s really important to do a serious code review to catch anything you aren&#8217;t happy with. </p><p>Then you can let Codex rip autonomously for another 30 minutes. </p><blockquote><p><em>This is pretty heavy early-project vibe-coding-between-Mario-Kart-races territory. In a serious project, you want to make small, incremental changes. </em></p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lvFm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lvFm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 424w, https://substackcdn.com/image/fetch/$s_!lvFm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 848w, https://substackcdn.com/image/fetch/$s_!lvFm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 1272w, https://substackcdn.com/image/fetch/$s_!lvFm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lvFm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic" width="1456" height="855" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:855,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:266087,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lvFm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 424w, https://substackcdn.com/image/fetch/$s_!lvFm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 848w, https://substackcdn.com/image/fetch/$s_!lvFm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 1272w, https://substackcdn.com/image/fetch/$s_!lvFm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37a1cd17-cb15-4af1-8596-8a08165a93d8_1536x902.heic 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">33m and 36 seconds after getting my review, I had dinner ready and the code had improved itself </figcaption></figure></div><p>Any issues you catch can also go into an AGENTS.md file to help avoid the same mistake happening twice. I landed a <strong>lot</strong> of solutions to Swift 6.2 concurrency warning solutions in there.</p><p>I&#8217;m going to be very fair. It wasn&#8217;t all fun and games. I did run into teething issues with Core Image Metal kernels that I had to mostly solve manually. There were also a bunch of low-level styling issues like borders and symbol sizes that I wasn&#8217;t able to articulate clearly enough, and had to actually type out, like a 1337 Hacker in an 80s movie. But this is more a by-product of my perfectionism. </p><div><hr></div><h2>The big AI life-hack</h2><p>Something I conveniently have access to: <a href="https://github.com/jacobsapps?tab=repositories">an enormous back-catalog of side projects and demo apps</a>. This is the most significant timesaver when applying AI engineering, because you can simply point it at a folder and say &#8220;I want this feature, like it was done here, copy it&#8221;. Software engineering isn&#8217;t usually about remaking the wheel. It&#8217;s about plumbing together known solutions to create new utility.</p><p>Being able to reference existing work is, IMO, the main skill when using agentic AI to assist with engineering. It scales all the way up to big projects when you have a highly standardised codebase*.</p><blockquote><p><em>*This is actually a thing, called <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">Context Engineering</a>.</em></p></blockquote><p>I was able to utilise a bunch of reference code from previous projects I&#8217;ve worked on for the database, the shaders, and the Vision framework.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;1bc2113a-626c-4bc5-a5d7-f332d6045494&quot;,&quot;caption&quot;:&quot;A few weeks ago, I released a new app to the world. Unfortunately, nobody seemed to like it very much. Let&#8217;s chalk it up to a rare Jacob Bartlett miss.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;High Performance SwiftData Apps&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-07-14T15:02:48.303Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!RiBG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cc22b16-0be5-43de-81ca-72d510e94b53_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/high-performance-swiftdata&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:164465302,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:17,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;f72d67d2-1c5f-468f-9d14-919d90e97d44&quot;,&quot;caption&quot;:&quot;Subscribe to Jacob&#8217;s Tech Tavern for free to get ludicrously in-depth articles on iOS, Swift, tech, &amp; indie projects in your inbox every week.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Advanced Core Image&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2024-06-17T16:15:52.294Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f212598-161c-41e2-a53d-90ff5ce789ae_800x603.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/advanced-core-image&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:143036840,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:8,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;ec50ddca-88d2-499f-8aee-cfdd4be12b27&quot;,&quot;caption&quot;:&quot;This is my most elaborate article yet, covering my full journey building my new indie project, Summon Self, from conception to initial release.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;I trapped your soul in a trading card (with client-side AI)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:126930235,&quot;name&quot;:&quot;Jacob Bartlett&quot;,&quot;bio&quot;:&quot;Master iOS. Boost your salary. Join 60,000 senior Swift devs learning advanced concurrency, SwiftUI, and iOS performance for 10 minutes a week. Sign up free today!&quot;,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!s80e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feab1e065-dffc-4096-ad9e-826ddda8a6cd_1304x1304.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:100}],&quot;post_date&quot;:&quot;2025-06-02T15:02:23.930Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b42d9c84-c73f-4f5b-9d3b-136520c6430c_1680x1200.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.jacobstechtavern.com/p/i-turned-you-into-a-trading-card&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:163084900,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:9,&quot;comment_count&quot;:0,&quot;publication_id&quot;:1376173,&quot;publication_name&quot;:&quot;Jacob&#8217;s Tech Tavern&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!LJp-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee402e25-4e20-4683-ba5f-20ca86eb2b43_512x512.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h2>Falling back in love with UIKit</h2><h4>Hyper-responsive Gestures </h4><p>UIKit <strong>@Observable</strong> hooks allow the CollageViewController to listen for mutations in the view model&#8217;s <strong>canvasItems</strong> (containing each image, transformations, and shader modifications), and update subviews via <strong>updateProperties()</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6-KM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6-KM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 424w, https://substackcdn.com/image/fetch/$s_!6-KM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 848w, https://substackcdn.com/image/fetch/$s_!6-KM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 1272w, https://substackcdn.com/image/fetch/$s_!6-KM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6-KM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png" width="1456" height="771" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:771,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:233329,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.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_!6-KM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 424w, https://substackcdn.com/image/fetch/$s_!6-KM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 848w, https://substackcdn.com/image/fetch/$s_!6-KM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.png 1272w, https://substackcdn.com/image/fetch/$s_!6-KM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa980d694-3599-4a88-8acd-3395db9b09fc_1844x976.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"><a href="https://github.com/jacobsapps/ClassicUIKit/blob/main/ClassicUIKit/Features/Collage/CollageViewController.swift">CollageViewController.swift</a></figcaption></figure></div><p>CollageViewController follows the standard MVVM single-source-of-truth, but unlike SwiftUI, we can short-circuit to get better performance. </p><p>We&#8217;re adding various gestures to each image in our collage, imperatively.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H9q8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H9q8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 424w, https://substackcdn.com/image/fetch/$s_!H9q8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 848w, https://substackcdn.com/image/fetch/$s_!H9q8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 1272w, https://substackcdn.com/image/fetch/$s_!H9q8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H9q8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png" width="1456" height="521" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:521,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:248689,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.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_!H9q8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 424w, https://substackcdn.com/image/fetch/$s_!H9q8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 848w, https://substackcdn.com/image/fetch/$s_!H9q8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.png 1272w, https://substackcdn.com/image/fetch/$s_!H9q8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c75f5d2-bbdc-41ad-86fc-dca9e0a045fc_2112x756.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"><a href="https://github.com/jacobsapps/ClassicUIKit/blob/main/ClassicUIKit/Features/Collage/CollageViewController.swift">CollageViewController.swift</a></figcaption></figure></div><p>When we apply one of these pan, zoom, or rotation gestures to an image node, we should see the UIView transform in real-time.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;156fcee4-6b3d-4d36-a9d6-a027085c938e&quot;,&quot;duration&quot;:null}"></div><p>The gesture updates the <strong>@Observable</strong> view model to detail transformation parameters applied to each image node.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1-k7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1-k7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 424w, https://substackcdn.com/image/fetch/$s_!1-k7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 848w, https://substackcdn.com/image/fetch/$s_!1-k7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 1272w, https://substackcdn.com/image/fetch/$s_!1-k7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1-k7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png" width="1038" height="1240" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1240,&quot;width&quot;:1038,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:244120,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.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_!1-k7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 424w, https://substackcdn.com/image/fetch/$s_!1-k7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 848w, https://substackcdn.com/image/fetch/$s_!1-k7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.png 1272w, https://substackcdn.com/image/fetch/$s_!1-k7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69dd22c-f9fe-41e4-8373-5cb8bf02c7e8_1038x1240.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"><a href="https://github.com/jacobsapps/ClassicUIKit/blob/main/ClassicUIKit/Features/Collage/CollageViewModel.swift">CollageViewModel.swift</a></figcaption></figure></div><p>SwiftUI renders UI as a function of state, so each pinch, drag, or rotation on a <strong>@GestureState</strong> can trigger view invalidation, body diffing, layout computation, and a render pass. The UI waits for the state update pipeline to propagate back up to the pixels before it responds to the user. Frame by frame.</p><p>In UIKit, we could get the same beautiful, unidirectional flow by applying gestures to the relevant image transformation parameters on the <strong>@Observable</strong> view model. When this changes, <strong>updateProperties()</strong> will traverse each subviews and apply the transformations. CoreAnimation would only re-render each layer when its own properties change. </p><p>If we wanted to be extra efficient, we could even give each image node its own <strong>@Observable</strong> model, saving traversal across the subviews.</p><p>We can go even further and take a performance shortcut: directly apply gesture-based transformations to the UIViews in real-time, and withheld updates to the view model to the end of the gesture. This means we only hit <strong>updateProperties()</strong> on the view controller at the start and end of each gesture.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!A2Np!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!A2Np!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 424w, https://substackcdn.com/image/fetch/$s_!A2Np!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 848w, https://substackcdn.com/image/fetch/$s_!A2Np!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 1272w, https://substackcdn.com/image/fetch/$s_!A2Np!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!A2Np!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png" width="792" height="166" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:166,&quot;width&quot;:792,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36888,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.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_!A2Np!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 424w, https://substackcdn.com/image/fetch/$s_!A2Np!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 848w, https://substackcdn.com/image/fetch/$s_!A2Np!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 1272w, https://substackcdn.com/image/fetch/$s_!A2Np!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc181bdaa-3408-4fb9-b32a-d35c516267f3_792x166.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">You can check for yourself!</figcaption></figure></div><p>The ability to short-circuit like this is a big reason that UIKit is virtually always faster.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8b30!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8b30!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 424w, https://substackcdn.com/image/fetch/$s_!8b30!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 848w, https://substackcdn.com/image/fetch/$s_!8b30!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 1272w, https://substackcdn.com/image/fetch/$s_!8b30!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8b30!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png" width="1456" height="930" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:930,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:411988,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.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_!8b30!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 424w, https://substackcdn.com/image/fetch/$s_!8b30!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 848w, https://substackcdn.com/image/fetch/$s_!8b30!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.png 1272w, https://substackcdn.com/image/fetch/$s_!8b30!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7888e6b-4bf5-4124-b504-435acb9e6762_2286x1460.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"><a href="https://github.com/jacobsapps/ClassicUIKit/blob/main/ClassicUIKit/Features/Collage/CollageViewController.swift">CollageViewController.swift</a></figcaption></figure></div><h4>Ultra-controlled transitions  </h4><p>One final stop on our rediscovery tour is the hero animation, played when opening and closing a collage. It&#8217;s powered by <strong>UIViewControllerTransitioningDelegate</strong>. There&#8217;s a ton of imperative layout boilerplate here, which is extremely easy for an LLM to write. You simply provide the <em>taste</em> and tune the animation parameters. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RFpM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RFpM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 424w, https://substackcdn.com/image/fetch/$s_!RFpM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 848w, https://substackcdn.com/image/fetch/$s_!RFpM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 1272w, https://substackcdn.com/image/fetch/$s_!RFpM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RFpM!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png" width="1200" height="838.1868131868132" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1017,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:289094,&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://blog.jacobstechtavern.com/i/178585175?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RFpM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 424w, https://substackcdn.com/image/fetch/$s_!RFpM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 848w, https://substackcdn.com/image/fetch/$s_!RFpM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.png 1272w, https://substackcdn.com/image/fetch/$s_!RFpM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70f71e97-b2e4-426f-91e0-0edee04a500f_1738x1214.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"><a href="https://github.com/jacobsapps/ClassicUIKit/blob/main/ClassicUIKit/Views/HeroTransitioningDelegate.swift">HeroTransitioningDelegate.swift</a></figcaption></figure></div><p>SwiftUI <strong>has</strong> started to introduce hero transitions via <a href="https://developer.apple.com/documentation/swiftui/navigationtransition">NavigationTransition</a>. This is welcome, but extremely basic and inflexible. It&#8217;s missing <a href="https://developer.apple.com/documentation/uikit/uipercentdriveninteractivetransition">percentage-driven transitions</a>, <a href="https://developer.apple.com/documentation/uikit/uiviewcontrollerinteractivetransitioning">interactive transitions</a>, and lacks the precision of <a href="https://developer.apple.com/documentation/uikit/uiviewcontrolleranimatedtransitioning">custom animators for transitions</a>.</p><p>Again, we scrape the surface of the UIKit iceberg. </p><div><hr></div><h2>Last Orders</h2><p>I got beers with a friend recently, and we shared the same feeling. The Classic UIKit Stack&#8482; just feels <em>great</em> to rediscover.</p><p>UIKit. Combine. Delegates. DispatchQueue (though, frankly, you&#8217;ll have to pry Swift Concurrency out of my cold, dead hands). All the classics. The gang, back together again.</p><p>SwiftUI was shipped from a place of fear, in response to the twin reapers of Flutter and React Native sucking developers out of Apple&#8217;s walled garden. Everyone jumped on the bandwagon, because suddenly we could knock out a complex screen in hours, not days.</p><p>Today, less code is hand-typed. Tomorrow, it will be less still.</p><p>Reading code is, again, the primary bottleneck to productivity.</p><p>AI-assisted engineering tools bestow speed without compromising maintainability, performance, and the all-important characteristic UX of iOS we know and love. </p><p>SwiftUI is dead. Long live UIKit.</p><p>I&#8217;m able to build anything, again.</p>]]></content:encoded></item><item><title><![CDATA[Swift Concurrency Training Kata]]></title><description><![CDATA[Master concurrency with 12 real-world challenges]]></description><link>https://blog.jacobstechtavern.com/p/swift-concurrency-kata</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/swift-concurrency-kata</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Tue, 11 Nov 2025 16:00:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Jmbw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.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_!Jmbw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jmbw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!Jmbw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!Jmbw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!Jmbw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jmbw!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:2674336,&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://blog.jacobstechtavern.com/i/177646585?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jmbw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!Jmbw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!Jmbw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!Jmbw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0b55ea4-9076-4c38-9650-d21ff4768e11_1680x1200.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>I&#8217;ve been teaching concurrency for a long time. But you can only get so far by reading a blog, or watching a video course. Knowing the toolkit is only half the battle.</p><p>For years, I&#8217;ve been saying that the best way to learn Swift Concurrency is to <strong>immerse yourself in real-world challenges</strong>. Swift concurrency experts have worked on hard problems for years and earned an intuition.</p><p>The pros have a quiet voice that tells us to use a <em>taskGroup </em>instead of an <em>async let</em>. Like seeing the Matrix, we <em>just</em> <em>know</em> which actor a function will execute on. With a glance, we might diagnose the unresponsive <em>AsyncStream</em> that stumped our teammate.</p><p>Welcome to my most ambitious project ever:</p><h3><strong>I compressed my 4 years of Swift Concurrency experience into one day.</strong></h3><p>12 challenges that simulate real day-to-day work. </p><p>All solved by applying the Swift Concurrency toolkit.</p><p>I built you a fully-fledged app: a <strong>murder mystery</strong>. Take the place of a detective and gather suspects, track down the crime scene, and secure a confession. The murder mystery is divided into 3 sections: <strong>Suspects</strong>, <strong>Field Ops</strong>, and <strong>Forensic Lab</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Qfuu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Qfuu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 424w, https://substackcdn.com/image/fetch/$s_!Qfuu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 848w, https://substackcdn.com/image/fetch/$s_!Qfuu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 1272w, https://substackcdn.com/image/fetch/$s_!Qfuu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Qfuu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png" width="480" height="164" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:164,&quot;width&quot;:480,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:26854,&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://blog.jacobstechtavern.com/i/177646585?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.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_!Qfuu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 424w, https://substackcdn.com/image/fetch/$s_!Qfuu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 848w, https://substackcdn.com/image/fetch/$s_!Qfuu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 1272w, https://substackcdn.com/image/fetch/$s_!Qfuu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3125c42-4bb3-4f5d-af58-9325365902eb_480x164.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The UI, interactions, and models are all pre-built.</p><p>Your mission is to finish features, squash bugs, and wire up asynchronous plumbing with your Swift Concurrency know-how.</p><p><strong>Clear your calendar</strong>. I&#8217;m about to guide you through 12 brutal training Kata.</p><p>By the end, you&#8217;ll bootstrap years worth of real-world experience with Swift Concurrency and build up a black-belt intuition.</p>
      <p>
          <a href="https://blog.jacobstechtavern.com/p/swift-concurrency-kata">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The Great Connection Pool Meltdown]]></title><description><![CDATA[A war story from the frontlines at Tuist]]></description><link>https://blog.jacobstechtavern.com/p/the-great-connection-pool-meltdown</link><guid isPermaLink="false">https://blog.jacobstechtavern.com/p/the-great-connection-pool-meltdown</guid><dc:creator><![CDATA[Jacob Bartlett]]></dc:creator><pubDate>Thu, 06 Nov 2025 16:02:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!xR1f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><em>Welcome to my first edition of <strong>War Stories</strong>, where I partner with famous builders in the iOS space to share real-life stories from the frontlines as they scale their projects.</em></p><p><em>Today I&#8217;m working with <a href="https://www.linkedin.com/in/pedro-pi%C3%B1era-buendia-9765a9125/">Pedro Pi&#241;era Buendia</a>, the creator of <a href="https://tuist.dev">Tuist</a>, which is designed to fix the problems shared by iOS teams as they scale Xcode projects. I have <strong>not</strong> been paid to endorse Tuist, but I do really like it.</em></p><p><em>I&#8217;m still working out the format here, so please be patient whenever I accidentally switch between first and third person. It&#8217;s part narrative, part interview, all swashbuckling fun.</em></p><p><em>To catch all my War Stories, be sure to subscribe</em>:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p></blockquote><p>Without further ado, here&#8217;s <strong>The Great Connection Pool Meltdown</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xR1f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xR1f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!xR1f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!xR1f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!xR1f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xR1f!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png" width="1200" height="857.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:3125543,&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://blog.jacobstechtavern.com/i/176919776?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xR1f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 424w, https://substackcdn.com/image/fetch/$s_!xR1f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 848w, https://substackcdn.com/image/fetch/$s_!xR1f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!xR1f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F080253fc-4caf-4713-b81f-5f8b0a90670e_1680x1200.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><h3>Hard Things</h3><p>Like many readers of Jacob&#8217;s Tech Tavern, the Tuist guys are iOS developers turned founders. <em>Web infra at scale</em> abruptly switches from an interview buzzword to cold reality. This is one of those Hard Things&#8482; that we are often shielded from when painting JSON on the client-side. </p><p>One of Tuist&#8217;s core features is <a href="https://docs.tuist.dev/en/guides/features/cache">caching</a>. It builds xcframeworks from each module and caches them remotely, which dramatically cuts cold build time for Xcode projects, both locally and on CI (Tuist newly integrates with <a href="https://tuist.dev/blog/2025/10/22/xcode-cache">Xcode 26 Compilation Caching</a> to make it even faster).</p><p>To power a cache, you need a server. The Tuist caching server is <a href="https://tuist.dev/blog/2025/07/15/elixir">coded in Elixir</a>, which compiles down to Erlang bytecode and runs on the Erlang runtime. It&#8217;s famous for being great at building highly parallel, real-time services. </p><blockquote><p><em>Tuist&#8217;s code is actually <a href="https://github.com/tuist/tuist/tree/main/server">open-source</a> if you&#8217;re interested.</em></p></blockquote><p>The HTTP cache server processes traffic from organisations with hundreds of devs, with bursts of traffic every time a project is freshly generated. This can rack up ~100k requests per hour. Given an average xcframework module can be 5-10 MB, adds up to (approximately) a metric f*ckton of traffic. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!COQL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!COQL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 424w, https://substackcdn.com/image/fetch/$s_!COQL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 848w, https://substackcdn.com/image/fetch/$s_!COQL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 1272w, https://substackcdn.com/image/fetch/$s_!COQL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!COQL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png" width="1346" height="710" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:710,&quot;width&quot;:1346,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:170116,&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://blog.jacobstechtavern.com/i/176919776?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.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_!COQL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 424w, https://substackcdn.com/image/fetch/$s_!COQL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 848w, https://substackcdn.com/image/fetch/$s_!COQL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.png 1272w, https://substackcdn.com/image/fetch/$s_!COQL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7825ed31-0899-4f53-8da3-f7c04ea9cc6b_1346x710.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">Basic architecture of Tuist&#8217;s caching system, generated by <a href="https://www.eraser.io/ai/architecture-diagram-generator">eraser.io</a></figcaption></figure></div><p>This was all well and good, but strange errors began 6 months ago.</p><div><hr></div><h3>The iOS Dev&#8217;s Blind Spot</h3><p>We are coddled by the Apple ecosystem. URLSession does <strong>a lot</strong> under the hood like HTTP/2 multiplexing, interfacing with system daemons that manage the radio, and maintaining an internal TCP connection pool. </p><blockquote><p><em>This stuff will make a pretty good article actually, I&#8217;ll add it to my list.</em></p></blockquote><p>Building on the server means you must keep TCP connections warm using a connection pool, or your users will suffer cold starts, leading to slow response times.</p><p>A caching server is a high-throughput environment, but when you&#8217;re linked to CI builds, the access pattern is actually <em>very</em> spiky. Every organisation onboarded to Tuist adds thousands of sporadic requests to the server as devs sprint to generate projects and merge PRs.</p><p>This leads to unpredictable surges in traffic on the server. These could queue up thousands of operations waiting to be executed, from DB queries to Postgres (fetching cache metadata), to external GET requests to Amazon S3 storage (where the xcframeworks are stored).</p><p>Each millisecond of latency counts on a cache server. You can optimise your Elixir code as much as you like, but there&#8217;s no getting around &#8220;fixed costs&#8221; like disk I/O on the database or the network latency when fetching from external storage. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kgDj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kgDj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 424w, https://substackcdn.com/image/fetch/$s_!kgDj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 848w, https://substackcdn.com/image/fetch/$s_!kgDj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 1272w, https://substackcdn.com/image/fetch/$s_!kgDj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kgDj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png" width="1456" height="1358" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1358,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:898935,&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://blog.jacobstechtavern.com/i/176919776?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.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_!kgDj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 424w, https://substackcdn.com/image/fetch/$s_!kgDj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 848w, https://substackcdn.com/image/fetch/$s_!kgDj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.png 1272w, https://substackcdn.com/image/fetch/$s_!kgDj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c6afdad-a2e0-400c-a813-fc009b542e8e_3680x3432.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"><a href="https://github.com/tuist/tuist/blob/main/server/lib/tuist/storage.ex">Snippet of server code to get presigned URLs from S3 to download xcframeworks</a></figcaption></figure></div><p>If you can serve these requests in time, great. </p><p>If not, bad things can happen. </p><div><hr></div><h3>The sh*t hits the fan</h3><p>The early warning signs were subtle at first. </p><p>Daily connection drop warnings were flagged from the server, because they sat in the queue too long. Users weren&#8217;t complaining, since the client would just retry failed connections, but it was annoying to begin every workday like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!01YL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!01YL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 424w, https://substackcdn.com/image/fetch/$s_!01YL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 848w, https://substackcdn.com/image/fetch/$s_!01YL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 1272w, https://substackcdn.com/image/fetch/$s_!01YL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!01YL!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png" width="1200" height="395.6043956043956" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:480,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:null,&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;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!01YL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 424w, https://substackcdn.com/image/fetch/$s_!01YL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 848w, https://substackcdn.com/image/fetch/$s_!01YL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.png 1272w, https://substackcdn.com/image/fetch/$s_!01YL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38888760-3e3b-4cfd-bdc1-37166c7f877d_1600x528.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>The team began to talk to their cloud provider (a popular wrapper who will remain nameless) about potential network issues in their caching server instance, but they would mostly push back and blame Pedro&#8217;s config.</p><blockquote><p><em>The cloud provider doth protest too much, methinks.</em></p></blockquote><p>One day, things got real bad. Contagion. The network issue spread out across the database provider <em>and </em>their S3 storage, proving it had nothing to do with app configuration. </p><p>All of a sudden, the server crashed.</p><p>It was a particularly high-traffic spike that toppled the service. The Tuist guys spun up the server again. It went down again. </p><p>The cloud provider&#8217;s network issue was failing to process many of the S3 requests that fetched cached xcframeworks. The failing requests sat around in the queue, waiting to retry. This hogged connection pool slots, wasted CPU cycles, and rapidly filled up application memory until the server crashed again.</p><p>The CLI client kept retrying with exponential backoff, so the server immediately got hit with thousands of requests each time it recovered.</p><p>At best, users didn&#8217;t notice much, because the Tuist client fell back to locally-cached modules. At worst, this incident manifested as time-outs on cache fetches, with the client <a href="https://github.com/tuist/tuist/blob/af43746687ccf9f40de6c710d27bf73871ffe542/cli/Sources/TuistServer/Network/URLSession%2BServer.swift#L4">URLSessionConfiguration</a> set up to kill sessions after 5 minutes. This blocked CI builds and newly-onboarding developers who needed to fetch from the cache.</p><blockquote><p><em>For what it&#8217;s worth, I&#8217;ve used Tuist at work and their team responds (and usually unblocks us) very fast on Slack anytime there&#8217;s a problem.</em></p></blockquote><p>Firefighting mode.</p><p>Well, mostly.</p><p>Pedro was in a taxi to the hospital for surgery* as this all went down, but the 3-strong engineering team coordinated the response over Slack.</p><blockquote><p><em>*Sick days are one of the casualties of becoming a founder &#129394;</em></p></blockquote><p>The team bought themselves time by upgrading their server instance to a chunkier one with more memory. </p><p>With a minute to breathe, they found a straightforward change to the queue configuration that let it fail fast instead of re-queueing infinitely and clogging up memory. Basically: <em>&#8220;if network issues happen again, cascade them down to the client instead of re-queueing on the server&#8221;.</em> </p><p>Here&#8217;s what the Postgres DB config looked like in production with this fix; check out the pool_size and queue_target parameters.</p><pre><code>[
  ssl: [
    server_name_indication: ~c"db.tuist.dev",
    verify: :verify_none
  ],
  pool_size: 40,
  queue_target: 200,
  queue_interval: 2000,
  database: "cache_db",
  username: "pedro",
  password: "123456", # *
  hostname: "db.tuist.dev",
  port: 5432,
  socket_options: [keepalive: true],
  parameters: [
    tcp_keepalives_idle: "60",
    tcp_keepalives_interval: "30",
    tcp_keepalives_count: "3"
  ]
]</code></pre><blockquote><p><em>*I am about 80% sure this isn&#8217;t the real password.</em> </p></blockquote><p>But WTF was going on?! </p><div><hr></div><h3>The Route of all Evil</h3><p>The first warning signs started bleeding through in early 2025, but the sh*t truly hit the fan in October. Fortunately, there was a months-long breadcrumb trail of logs and errors spanning the entire cache server that led to the ultimate conclusion: </p><p>Lo and behold, it was <em>absolutely</em> the cloud provider&#8217;s fault. </p><p>Tuist spun up a new machine on <a href="https://render.com">Render.com</a>, routed some traffic over, and the problem was gone. The new server was faster and seemed more reliable. Switching was a no-brainer.</p><blockquote><p><em>Pedro has not been paid to endorse Render.com, but he does really like it.</em></p></blockquote><p>The memory and queue configuration bought the team some time. Updates were shipped to the client CLI in the meantime that made the service issues less disruptive, for example, skipping some binary cache fetches when requests were slow.</p><p>This ultimately gave them breathing space to plan out a migration, moving their entire caching infra to the new-<br>-Wait, I&#8217;m told they got it shifted in just under a day. Nice.</p><p>The team used Cloudflare to gradually route caching traffic to the new service to gain confidence, and once things were up and running with no issues, the original service was shut down. </p><p>Memory and CPU were stable, responses were faster, and there were no more connection drops from timeouts. </p><p>Today, the caching server efficiently handles tens of thousands of requests per hour without breaking a sweat, using relatively minimal resources. All thanks to reliable underlying infra. </p><p>The original cloud provider, after months of ignoring complaints, finally declared an incident.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UPbx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UPbx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 424w, https://substackcdn.com/image/fetch/$s_!UPbx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 848w, https://substackcdn.com/image/fetch/$s_!UPbx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 1272w, https://substackcdn.com/image/fetch/$s_!UPbx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UPbx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png" width="1456" height="421" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:421,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:155889,&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://blog.jacobstechtavern.com/i/176919776?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.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_!UPbx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 424w, https://substackcdn.com/image/fetch/$s_!UPbx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 848w, https://substackcdn.com/image/fetch/$s_!UPbx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.png 1272w, https://substackcdn.com/image/fetch/$s_!UPbx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a806fc-c920-4275-be97-004d6de9eacd_1744x504.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>Too little, too late.</p><div><hr></div><h3>Lessons Learned</h3><p>As iOS-developers-turned-founders, creating web infra at scale didn&#8217;t come naturally. Learning to do Hard Things the Hard Way leaves you with scars that make you a better engineer. </p><p>There&#8217;s a lot we can take away from this story. </p><h4>Measure, measure, measure</h4><p>Without data, you can&#8217;t set up alerts. Without alerts, you don&#8217;t know whether your system is working. Without those annoying daily connection drop warnings, the Tuist team would have been blind when the server finally fell over.</p><p>It&#8217;s tough to improve this when you&#8217;re building a devtool, because devs are particularly strict with their data, and reluctant to share. But it&#8217;s kind of the only way to improve a setup.</p><p>It&#8217;s especially important to keep an eye on the state of the network and the latency of requests, and doubly-so if an endpoint has high throughput. Every customer onboarded to Tuist introduced new spiky bursts of thousands of requests.</p><blockquote><p><em>I also learned this the hard way, often finding out via a recruiter, or Twitter, that my Sign-in-with-Apple was busted during <a href="https://blog.jacobstechtavern.com/p/my-terrible-startup-architecture">my first foray into startups</a>.</em></p></blockquote><h4>Trust your gut</h4><p>The team&#8217;s initial assumption was a problem with the cloud provider. With the patterns they found in the logs, it really appeared to be the only culprit.</p><p>The cloud provider successfully gaslit the Tuist team into thinking that maybe something <em>was </em>wrong with their network configuration.</p><p>It took a serious incident to discard their diagnosis and revisit the initial assumption. </p><h4>Elixir &amp; Erlang are a beast</h4><p>When debugging CPU and memory, the Tuist team could open a shell terminal on the prod server. The Erlang runtime has a &#8220;fair scheduler&#8221; that allows critical traffic like SSH in to inspect what&#8217;s happening, even if the CPU is at capacity. </p><p>In a prod incident, this is functionally open-heart surgery. Other runtimes might block any kind of telemetry leaving the server and make debugging 10x harder, reinforcing the choice of Elixir. </p><blockquote><p><em>Having recently <a href="https://x.com/jacobtechtavern/status/1986125077008597214">melted my own VPS</a> while building a Vapor app, this sounds like a dream. When my CPU hit capacity, I was locked out and forced to shut it off. </em></p></blockquote><h4>Design for failure </h4><p>This is Erlang&#8217;s mantra. </p><p>The CLI wasn&#8217;t designed to recover from cache failures. Therefore, the incident was felt by some customers during the incident.</p><p>The Tuist team intends to embrace this mantra across all their tooling and server apps from now on: Things will break, so the system needs to be resilient to it. Design systems that can recover from failures. </p><blockquote><p><em>The <a href="https://x.com/GergelyOrosz/status/1982571625204810227">winners and losers from the October AWS outage</a> only make this lesson more concrete.</em></p></blockquote><div><hr></div><p>Thanks again to <a href="https://www.linkedin.com/in/pedro-pi%C3%B1era-buendia-9765a9125/">Pedro Pi&#241;era Buendia</a> for taking the time to share his War Story with me! You can try out Tuist yourself at <a href="https://tuist.dev">https://tuist.dev</a> </p><p>I&#8217;m hoping to make this a regular column on Jacob&#8217;s Tech Tavern. If you have a story you&#8217;d like to share, <a href="https://www.linkedin.com/in/jacobmartinbartlett/">get in touch</a>!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.jacobstechtavern.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://blog.jacobstechtavern.com/subscribe?"><span>Subscribe now</span></a></p><p></p>]]></content:encoded></item></channel></rss>