<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Swift - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Swift - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 18 Oct 2026 15:32:43 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/swift/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The iOS NFC Handbook: How to Read, Write and Lock NFC Tags with React Native ]]>
                </title>
                <description>
                    <![CDATA[ Hold an iPhone near a sticker and something happens. A business card lands in your contacts, a focus session ends, or a door opens. The chip costs about twenty pence and holds roughly a hundred and th ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-ios-nfc-handbook-how-to-read-write-and-lock-nfc-tags-with-react-native/</link>
                <guid isPermaLink="false">6aaec3412b999a8f7cf63f8f</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mobile Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Farouq Seriki ]]>
                </dc:creator>
                <pubDate>Sat, 19 Sep 2026 17:15:45 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/6e58f5f5-1bf1-4030-b3d2-f9b1617637c1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hold an iPhone near a sticker and something happens. A business card lands in your contacts, a focus session ends, or a door opens. The chip costs about twenty pence and holds roughly a hundred and thirty bytes.</p>
<p>Reading one takes two function calls. Earning the right to make those two calls takes considerably longer. And then CoreNFC asks you to earn it a second time.</p>
<p>The first gauntlet is Apple's. A paid developer account, an App ID registered in a web portal, a capability ticked on it, and a provisioning profile regenerated. Get any of it wrong and the build fails with a code-signing error that never says the word "NFC".</p>
<p>The second is CoreNFC's own, and it's the one nobody warns you about. It's a session-based API with delegate callbacks, four nested asynchronous steps, and a set of rules that punish you quietly.</p>
<p>Hold the session in the wrong variable and the system sheet vanishes with no error at all. Let a successful read settle your promise twice and your result is replaced by a failure. Ask for one polling option too many and the whole session refuses to start, without naming the option.</p>
<p>In this handbook, you'll get through both. You'll write an NDEF decoder by hand, which sounds like overkill until you read what the popular library's one actually does to an emoji. You'll write to a tag and discover your business card doesn't fit. You'll build a focus timer you can't stop without walking to another room. You'll delete the NFC dependency entirely and replace it with a native module in Swift. And you'll permanently lock a tag, which is the one thing here that can't be undone.</p>
<p>Two of the things I concluded during this build turned out to be wrong, and both are still in the repository under "superseded" banners. They're in here too, because how I got them wrong is more useful than the what replaced them.</p>
<p>This is an iOS handbook. Everything in the main sections was built, run, and verified on a real iPhone. Android gets its own handbook, and if you can't wait for it there's a preview at the end: the Kotlin counterpart to everything here, with the architectural differences that make the two platforms worth comparing.</p>
<p>Everything below comes from one project, TapCard, which is on GitHub with tagged checkpoints so you can check out the app at any stage and run it.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-what-nfc-tags-actually-are">What NFC Tags Actually Are</a></p>
</li>
<li><p><a href="#heading-where-you-have-already-seen-this">Where You Have Already Seen This</a></p>
</li>
<li><p><a href="#heading-why-there-is-no-simulator-path">Why There Is No Simulator Path</a></p>
</li>
<li><p><a href="#heading-how-the-ios-contract-works">How the iOS Contract Works</a></p>
</li>
<li><p><a href="#heading-how-to-read-your-first-tag">How to Read Your First Tag</a></p>
</li>
<li><p><a href="#heading-what-an-ndef-record-actually-is">What an NDEF Record Actually Is</a></p>
</li>
<li><p><a href="#heading-why-i-wrote-my-own-decoder">Why I Wrote My Own Decoder</a></p>
</li>
<li><p><a href="#heading-how-to-write-a-tag">How to Write a Tag</a></p>
</li>
<li><p><a href="#heading-will-it-fit-137-not-144">Will It Fit? 137, Not 144</a></p>
</li>
<li><p><a href="#heading-a-focus-session-you-cant-end-without-the-tag">A Focus Session You Can't End Without the Tag</a></p>
</li>
<li><p><a href="#heading-why-your-nfc-lock-isnt-secure">Why Your NFC Lock Isn't Secure</a></p>
</li>
<li><p><a href="#heading-four-gotchas-that-cost-me-an-evening-each">Four Gotchas That Cost Me an Evening Each</a></p>
</li>
<li><p><a href="#heading-why-you-cant-build-tap-to-pay">Why You Can't Build Tap to Pay</a></p>
</li>
<li><p><a href="#heading-why-you-might-write-your-own-native-module">Why You Might Write Your Own Native Module</a></p>
</li>
<li><p><a href="#heading-how-to-prove-parity-before-you-switch">How to Prove Parity Before You Switch</a></p>
</li>
<li><p><a href="#heading-what-a-config-plugin-was-doing-for-you">What a Config Plugin Was Doing For You</a></p>
</li>
<li><p><a href="#heading-how-to-lock-a-tag-forever">How to Lock a Tag Forever</a></p>
</li>
<li><p><a href="#heading-how-would-you-actually-ship-this">How Would You Actually Ship This?</a></p>
</li>
<li><p><a href="#heading-a-sneak-peek-at-the-android-side">A Sneak Peek at the Android Side</a></p>
</li>
<li><p><a href="#heading-the-demo-repository">The Demo Repository</a></p>
</li>
<li><p><a href="#heading-what-to-know-before-you-start">What to Know Before You Start</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a href="#heading-sources-and-further-reading">Sources and Further Reading</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along you'll need:</p>
<ul>
<li><p><strong>A physical iPhone</strong>, 7 or newer. Core NFC is iPhone-only. Apple's documentation lists iPhone 7 and later, and an Apple engineer on the developer forums puts it directly: "At this time, CoreNFC functionality is only available on iPhones with NFC capability." No iPad supports it.</p>
</li>
<li><p><strong>A paid Apple Developer account.</strong> NFC isn't available on a free provisioning profile. This isn't a soft requirement, and there's no way around it.</p>
</li>
<li><p><strong>NTAG213 stickers.</strong> Twenty of them cost a few pounds. Buy them before you write any code.</p>
</li>
<li><p><strong>Node 20+ and Xcode.</strong> Working knowledge of TypeScript throughout, and of Swift for the last third.</p>
</li>
<li><p><em>Optional</em>, for the Android preview only: Android Studio and the API 36 SDK.</p>
</li>
</ul>
<p>The versions I used:</p>
<table>
<thead>
<tr>
<th>Package or tool</th>
<th>Version</th>
</tr>
</thead>
<tbody><tr>
<td>Expo SDK</td>
<td>57.0.20</td>
</tr>
<tr>
<td>React Native</td>
<td>0.86.3</td>
</tr>
<tr>
<td>React</td>
<td>19.2.3</td>
</tr>
<tr>
<td>TypeScript</td>
<td>6.0.3</td>
</tr>
<tr>
<td><code>react-native-nfc-manager</code></td>
<td>3.17.2 (removed by the end)</td>
</tr>
<tr>
<td>Xcode</td>
<td>26.6</td>
</tr>
<tr>
<td>JDK</td>
<td>17 (Zulu), Android preview only</td>
</tr>
</tbody></table>
<p>One line in that table is load-bearing and I'll come back to it: the NFC library is listed <em>because it gets deleted</em>. The finished app has <strong>no third-party NFC dependency at all</strong>.</p>
<h2 id="heading-what-nfc-tags-actually-are">What NFC Tags Actually Are</h2>
<p>An NFC tag is a chip with a tiny antenna and no battery. Your phone powers it over the air, and in return it hands back a few dozen bytes. That's the whole device.</p>
<p>Those bytes are almost always formatted as <strong>NDEF</strong>, or NFC Data Exchange Format, which is the thing that makes a tag written by one app readable by every other. An NDEF message is a list of <strong>records</strong>, and each record has a type and a payload.</p>
<p>The tags in this handbook are <strong>NTAG213</strong>, the ones you'll get if you buy stickers online. They hold 144 bytes of user memory. That's <em>not</em> the number you can actually use, and it turns out to matter enormously.</p>
<p>Two things a tag is not:</p>
<ol>
<li><p><strong>It's not a beacon.</strong> It has no power of its own and does nothing until a phone is within a couple cm.</p>
</li>
<li><p><strong>It's not secure by default.</strong> Its identifier is world-readable and copyable with cheap hardware. There's a section on this later, because the obvious use of a tag, as a key, is the one most likely to be built wrong.</p>
</li>
</ol>
<h2 id="heading-where-you-have-already-seen-this">Where You Have Already Seen This</h2>
<p>NFC is in your pocket already, and it's worth separating what you can build from what you can't, because they look identical to a user.</p>
<p>Here are five uses cases you can go and check, each one documented by the company that ships it:</p>
<table>
<thead>
<tr>
<th>Where you have seen it</th>
<th>What happens</th>
<th>Source</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Shortcuts, on your own phone</strong></td>
<td>Scan a tag to fire a personal automation</td>
<td><a href="https://support.apple.com/guide/shortcuts/setting-triggers-apde31e9638b/ios">Setting triggers in Shortcuts</a></td>
</tr>
<tr>
<td><strong>A lost AirTag</strong></td>
<td>Anyone taps it with an NFC phone and a page opens with the owner's details</td>
<td><a href="https://support.apple.com/guide/iphone/mark-an-item-as-lost-iph1b451b75f/ios">Mark an item as lost in Find My</a></td>
</tr>
<tr>
<td><strong>Nintendo amiibo</strong></td>
<td>A figure is tapped to a controller. Some games read it, some write your character back onto it</td>
<td><a href="https://en-americas-support.nintendo.com/app/answers/detail/a_id/13260/">amiibo FAQ</a></td>
</tr>
<tr>
<td><strong>A UK visa application</strong></td>
<td>The "UK Immigration: ID Check" app reads the chip inside your passport</td>
<td><a href="https://www.gov.uk/guidance/using-the-uk-immigration-id-check-app">Using the app</a></td>
</tr>
<tr>
<td><strong>Tap to Pay on iPhone</strong></td>
<td>A shop takes a contactless card payment with no terminal at all</td>
<td><a href="https://www.apple.com/business/tap-to-pay-on-iphone/">Tap to Pay on iPhone</a></td>
</tr>
</tbody></table>
<p>The first three are the thing this handbook builds. A chip holds a few bytes, a reader reads them, and software acts. amiibo is the most complete example of the lot, because some games <strong>write</strong> to the figure as well, which is the second half of what you're about to build.</p>
<p>One detail on that first row is worth pausing on, because it comes back later. Apple's own NFC automation, the one built into every iPhone, says this about the tag you scan:</p>
<blockquote>
<p>"Other than the unique identifier, the contents of the NFC tag are ignored."</p>
</blockquote>
<p>Apple's feature ignores everything this handbook teaches you to write, and keys on the serial number alone. There's <a href="#heading-why-your-nfc-lock-is-not-secure">a section later</a> on what that does and doesn't buy you.</p>
<p>Let's go over two caveats about that table. The passport row is NFC but it's <em>not</em> NDEF: a biometric chip speaks ISO 7816 over the same radio, through <code>NFCISO7816Tag</code> and a different entitlement again, with its own cryptography on top. Same antenna, different world, and out of scope here. And the last row is the half you can't build, which is the rest of this section.</p>
<p>Beyond those five use cases, the pattern repeats everywhere a physical thing needs to say one short sentence to a phone, like museum labels that open an exhibit page, conference badges, product-authentication seals on a bottle, transit posters, restaurant table markers, and the little stickers people put on a desk to start a routine.</p>
<p>What you can't build on iOS is the other half: your phone <em>pretending to be</em> a card. Apple Pay, your bank card in Google Wallet, or a hotel key in your Apple Wallet. Those run on the <strong>Secure Element</strong>, a separate tamper-resistant chip that stores card credentials and answers terminals on its own. On iOS there's no third-party API for it at all. Not restricted: absent. There's a section later on exactly how closed that is.</p>
<p>So when someone says "NFC", they may mean either. This handbook is about the half you can actually write code for, and it'll explain precisely why the other half is closed.</p>
<h2 id="heading-why-there-is-no-simulator-path">Why There Is No Simulator Path</h2>
<p>Don't skip this section, because it changes how you work.</p>
<p><strong>NFC doesn't exist on the iOS Simulator or the Android emulator.</strong> It's not partially supported, nor is it behind a flag. The hardware isn't there and the APIs report it as unavailable. Every single thing you build is tested by holding a physical chip against a physical phone.</p>
<p>The consequences go beyond inconvenience. You can't write a test that proves a tag was read. You can't demo it in CI. If your phone is in another room, you're blocked. When my chips went missing in the post, the project stopped for two weeks.</p>
<p>The app says so permanently, because the question kept coming up:</p>
<pre><code class="language-ts">import * as Device from 'expo-device';

// NFC hardware does not exist on the iOS Simulator or the Android emulator,
// and isSupported() is not reliable there. Bail out early and explicitly.
if (!Device.isDevice) return false;
</code></pre>
<p>So split your code in two.</p>
<p>One part talks to the NFC hardware. Start a session, read the tag, write to it, and close the session. The only way to test that part is to hold a chip against a phone.</p>
<p>Everything else is just data handling: turning the bytes off a tag into a URL, turning a contact into the bytes you write back, checking whether a message fits, turning a native error code into a sentence a user can read, or deciding whether a tap should start a focus session or end one.</p>
<p>None of that needs NFC. Most of it doesn't even need React Native. It's plain functions: values go in, values come out.</p>
<p>Write it that way and you can test it on your laptop, with no phone in the room. In this project, that came to about 2,240 lines of TypeScript and <strong>293 tests that finish in about a second</strong>. The code that actually calls CoreNFC stays as small as I could make it.</p>
<p>This project stalled on hardware three times, including those two weeks waiting on the post. Each time there was still plenty left to build, because most of it never needed a tag. That's the best decision in the codebase, and I didn't make it deliberately. The constraint made it for me.</p>
<blockquote>
<p><strong>Checkpoint:</strong> <code>git checkout step-0-scaffold</code>. The app boots on both platforms and does nothing else.</p>
</blockquote>
<h2 id="heading-how-the-ios-contract-works">How the iOS Contract Works</h2>
<p>Three Apple terms do all the work here, and they're worth pinning down before the steps, because the error messages assume you already know them.</p>
<p>An <strong>App ID</strong> is the identity your app is registered under on Apple's servers, matching the <code>bundleIdentifier</code> in your config. An <strong>entitlement</strong> is a line in your app saying "I intend to use this capability", and NFC is one. A <strong>provisioning profile</strong> is the signed document tying the two together with your developer account, and Xcode embeds it in every build. All three have to agree, or nothing runs on a device.</p>
<p>With that, here's the actual sequence, and every step is important:</p>
<ol>
<li><p>A <strong>paid</strong> Apple Developer account.</p>
</li>
<li><p>An <strong>explicit App ID</strong> registered at developer.apple.com, not a wildcard.</p>
</li>
<li><p><strong>NFC Tag Reading</strong> ticked on that App ID.</p>
</li>
<li><p>A provisioning profile regenerated to include the capability.</p>
</li>
</ol>
<p>Then, in <code>app.json</code>:</p>
<pre><code class="language-json">{
  "expo": {
    "ios": {
      "bundleIdentifier": "com.yourname.tapcard",
      "infoPlist": {
        "NFCReaderUsageDescription": "TapCard uses NFC to read and write your card to a tag."
      },
      "entitlements": {
        "com.apple.developer.nfc.readersession.formats": ["NDEF", "TAG"]
      }
    }
  }
}
</code></pre>
<p>Miss step 2 or 3 and the build fails with this:</p>
<pre><code class="language-text">Provisioning Profile "iOS Team Provisioning Profile: *" does not support
the NFC Tag Reading capability.
</code></pre>
<p><strong>That error points at the wrong machine.</strong> Apple forbids special capabilities on a <em>wildcard</em> App ID, and Xcode silently falls back to one when there's no explicit match.</p>
<p>The message blames your local provisioning profile, but the missing half is on Apple's servers, in a web form you haven't filled in. Nothing in it suggests opening a browser.</p>
<p>A second-order trap while you're there: <strong>App IDs are globally unique across all Apple accounts</strong>, not per-team**.** My first choice was taken by a stranger, and my second was too. I renamed the app's identifier twice.</p>
<p>Those renames were painless, and that's worth a word on how this project is set up. Expo's <strong>Continuous Native Generation</strong> means the <code>ios/</code> and <code>android/</code> folders aren't kept in the repo at all. They're regenerated from <code>app.json</code> by <code>expo prebuild</code> whenever you need them, the way <code>node_modules</code> is regenerated from <code>package.json</code>. So renaming the app was two lines of JSON and one <code>prebuild --clean</code>, which rebuilt the iOS project, the Android package and the entire Kotlin source tree. No Xcode surgery.</p>
<p>For scale, the equivalent on Android is one line in a manifest, with no account, no portal, and no cost:</p>
<pre><code class="language-xml">&lt;uses-permission android:name="android.permission.NFC" /&gt;
</code></pre>
<p>That contrast isn't a complaint. It's worth internalising early, because it tells you where your time will go on this platform: not in the code, which is short, but in the paperwork around it.</p>
<table>
<thead>
<tr>
<th></th>
<th>Android</th>
<th>iOS</th>
</tr>
</thead>
<tbody><tr>
<td>To read one tag</td>
<td>One manifest line</td>
<td>App ID + capability + paid account + profile</td>
</tr>
<tr>
<td>Cost</td>
<td>Free</td>
<td>$99/yr, or local equivalent</td>
</tr>
<tr>
<td>Failure mode</td>
<td>Permission missing</td>
<td><strong>A code-signing error that never says "NFC"</strong></td>
</tr>
</tbody></table>
<h2 id="heading-how-to-read-your-first-tag">How to Read Your First Tag</h2>
<p>The reading code is short. This is all of it:</p>
<pre><code class="language-ts">import NfcManager, { NfcTech, type TagEvent } from 'react-native-nfc-manager';

export async function readTagOnce(): Promise&lt;TagEvent | null&gt; {
  await NfcManager.requestTechnology(NfcTech.Ndef, {
    alertMessage: 'Hold your iPhone near the NFC tag.',
  });

  try {
    return await NfcManager.getTag();
  } finally {
    // throwOnError: false because we are already unwinding. A failure to
    // close the session must not mask the original error.
    await NfcManager.cancelTechnologyRequest({ throwOnError: false });
  }
}
</code></pre>
<p>There are two calls, and they're identical on both platforms. <strong>And what the user sees couldn't be more different.</strong></p>
<p>On <strong>iOS</strong>, <code>requestTechnology</code> hands control to CoreNFC, which draws a system modal sheet. You can't restyle it. Your app isn't on screen.</p>
<p>On <strong>Android</strong>, nothing is drawn at all. Dispatch is silent. If your app doesn't tell the user to tap a tag, nobody does.</p>
<p>So the scanning UI is conditional, and this pattern recurs through the whole project:</p>
<pre><code class="language-tsx">{
  scanning &amp;&amp; (
    &lt;View style={styles.scanCard}&gt;
      &lt;ActivityIndicator /&gt;
      &lt;Text&gt;
        {Platform.OS === 'android'
          ? 'Hold a tag against the back of the phone.'
          : 'Waiting for the system NFC sheet…'}
      &lt;/Text&gt;
      {/* Android draws no system UI, so the app must offer its own way out. */}
      {Platform.OS === 'android' &amp;&amp; &lt;Button title="Cancel" onPress={handleCancel} /&gt;}
    &lt;/View&gt;
  );
}
</code></pre>
<p>That Cancel button exists only on Android, because on iOS the system sheet already has one.</p>
<h3 id="heading-three-things-that-will-catch-you">Three Things That Will Catch You</h3>
<h4 id="heading-1-the-antenna-is-in-different-places">1. The antenna is in different places.</h4>
<p>On iPhone: the <strong>top edge</strong>, near the camera. On Android: the <strong>middle of the back</strong>. "Hold the tag near the phone" isn't actionable, and someone using the wrong end concludes your app is broken. I ended up drawing a small phone outline with the dot in the right place per platform.</p>
<h4 id="heading-2-the-sheet-doesnt-show-the-string-you-think-it-does">2. The sheet doesn't show the string you think it does.</h4>
<p>I assumed it displayed <code>NFCReaderUsageDescription</code> from <code>app.json</code>. It doesn't. It shows the <code>alertMessage</code> passed to each <code>requestTechnology()</code> call. The usage description is a privacy-manifest string: it's mandatory, no session starts without it, and it's never shown to a user.</p>
<p>Both strings were configured correctly and spelled properly, and my assumption about which one appeared was still wrong. I found out by holding a phone. It also means the copy <strong>can differ per scan</strong>. "Hold your iPhone near the tag to write" beats reusing the read copy.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/c4c1ea67-0ab8-42dc-a810-4aaa6551ee2c.png" alt="The iOS system NFC sheet on an iPhone 13 Pro, reading &quot;Ready to Scan&quot; above the line &quot;Hold your iPhone near the NFC tag.&quot;, with a Cancel button. Behind the sheet the app reports real hardware and a green &quot;NFC ready&quot; banner." style="display: block;" width="600" height="400" loading="lazy">

<p>That second line is the <code>alertMessage</code> from the <code>requestTechnology</code> call above, word for word. The usage description from <code>app.json</code> is nowhere on screen.</p>
<h4 id="heading-3-a-blank-tag-reads-as-an-error-on-ios">3. A blank tag reads as an error on iOS.</h4>
<p>A factory-fresh NTAG213 is NDEF-formatted but empty, and <code>readNDEF</code> reports that as a <em>failure</em> rather than an empty message. The distinction has to come from the tag's NDEF <strong>status</strong>, not the read error. Since every tag you buy starts this way, it's the first thing you'll hit.</p>
<h3 id="heading-what-comes-back">What Comes Back</h3>
<p>Here's the real output from an NTAG213 on an iPhone 13 Pro:</p>
<pre><code class="language-json">{
  "id": "04C4FC91DF2A81",
  "tech": "mifare"
}
</code></pre>
<p>Two fields. That's everything iOS gives you from a read. No size, no technology list, and no NDEF type. Android returns all of them from the same chip.</p>
<p><strong>I drew the wrong conclusion from this</strong>: wrote it into three documents, and planned a whole phase of work around it. <a href="#heading-the-bigger-mistake">That comes later</a>, because the mistake is more useful than the fact. Skip ahead if you'd rather have the correction now.</p>
<p>That <code>id</code> is the tag's <strong>UID</strong>, a unique serial number burned into the chip at the factory and readable by anything that asks. The <code>04</code> prefix is NXP's manufacturer code, and a 7-byte UID is the NTAG21x signature, so the tag is what it claimed to be.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/1e3a1e0c-82c8-47f3-b985-1b65ceacc957.png" alt="The app's Read tab after a first scan on an iPhone 13 Pro. The Tag card lists ID 04C4FC91DF2A81, Type (none), Tech types (none), Max size (unknown) and NDEF records 0, above a RAW block containing only the id and tech fields." style="display: block;" width="600" height="400" loading="lazy">

<p>The <code>Max size</code> row is the one to look at. <code>(unknown)</code> is what I built the wrong conclusion on, and it is <a href="#heading-the-bigger-mistake">not what the platform can actually tell you</a>.</p>
<blockquote>
<p><strong>Checkpoint:</strong> <code>git checkout step-1-first-read</code>. Entitlements configured, a raw NDEF dump on screen.</p>
</blockquote>
<h2 id="heading-what-an-ndef-record-actually-is">What an NDEF Record Actually Is</h2>
<p>A tag doesn't store a URL. It stores bytes, and bytes are what your app gets handed. This whole section is about turning those bytes into <code>https://example.com</code> and back, and it's a much smaller job than its reputation suggests.</p>
<p>The unit you work with is a <strong>record</strong>, and a record is three things:</p>
<ul>
<li><p>a <strong>payload</strong>: the raw bytes of the content</p>
</li>
<li><p>a <strong>type</strong>: what that payload is, such as a URI or some text</p>
</li>
<li><p>a <strong>TNF</strong>, or Type Name Format: three bits saying how to read the type field itself</p>
</li>
</ul>
<p>That third one is the one people trip on. Think of the type as a label and the TNF as the rule for reading the label. A type byte of <code>U</code> means "URI", but only because the TNF said "this is a well-known NFC Forum type". The same byte under a different TNF would be the start of a MIME string instead.</p>
<p>Two record layouts carry almost all real traffic, and both are tiny.</p>
<h3 id="heading-a-uri-record">A URI Record</h3>
<pre><code class="language-text">04 65 78 61 6d 70 6c 65 2e 63 6f 6d
│  └──────── "example.com" ────────┘
└─ prefix index → "https://"

→ https://example.com
</code></pre>
<p>The annotations underneath say which byte does what. Everything after the first byte is ordinary text: <code>example.com</code>. The first byte, <code>04</code>, is an index into a 36-entry table in the NFC Forum spec, and entry 4 is <code>https://</code>.</p>
<p>So <strong>the scheme costs one byte instead of eight.</strong> On a tag with 137 usable bytes that isn't a micro-optimisation, it's 5% of your budget.</p>
<h3 id="heading-a-text-record">A Text Record</h3>
<p>Text needs two things a URI doesn't: which language it's in, and how it's encoded. Both get squeezed into the first byte.</p>
<pre><code class="language-text">02 65 6e 48 69
│  └─┬─┘ └─┬─┘
│   "en"  "Hi"
└─ status byte
</code></pre>
<p><strong>Read that first byte as a number.</strong> Here it's 2, and that's how long the language code is. So the next two bytes are the language: <code>65 6e</code>, "en". Everything after that is the text: <code>48 69</code>, "Hi".</p>
<p>The encoding hides in the same byte. If its value is 128 or more, the text is UTF-16 instead of UTF-8. That's all a "status byte" means.</p>
<p>That's the whole format. If you're writing the decoder yourself, mask off the low six bits for the length and test the top bit for the encoding.</p>
<h2 id="heading-why-i-wrote-my-own-decoder">Why I Wrote My Own Decoder</h2>
<p>You reach past a library for one of two reasons. Either it doesn't give you everything you need, or you work somewhere that builds this kind of thing in-house first and takes dependencies second.</p>
<p>The second is more common than the open-source default makes it sound, and for NDEF it has a short answer: yes, you can write this yourself. It's a few hundred lines of pure functions with no platform calls in them, and the format you just read is the whole specification you need.</p>
<p>The first reason is what actually happened here. The library bundles decoders, I read them before using them, and twenty minutes changed the architecture of the app.</p>
<p><strong>It throws away the language code.</strong> In <code>ndef-lib/ndef-text.js</code>:</p>
<pre><code class="language-js">var languageCodeLength = data[0] &amp; 0x3f; // 6 LSBs
// languageCode = data.slice(1, 1 + languageCodeLength),
// utf16 = (data[0] &amp; 0x80) !== 0; // assuming UTF-16BE

// TODO need to deal with UTF in the future
</code></pre>
<p>It measures the language code's length, uses it to skip past the code, and the line that would <em>keep</em> it is commented out. <code>decodePayload</code> returns a bare string, so a caller can't recover the language at all. "Which language is this in?" is precisely the question a record with a language field exists to answer.</p>
<p><strong>That</strong> <code>TODO</code> <strong>is load-bearing.</strong> UTF-16 text records are decoded as UTF-8 regardless, producing interleaved NUL characters.</p>
<p><strong>And the shared byte-to-string helper truncates.</strong> In <code>ndef-lib/util.js</code>:</p>
<pre><code class="language-js">str += String.fromCharCode(ch);
</code></pre>
<p><code>String.fromCharCode</code> only keeps the low 16 bits, and an emoji doesn't fit in 16 bits. So I fed it one:</p>
<pre><code class="language-text">bytes    : 68 69 20 f0 9f 98 80
expected : hi 😀
library  : "hi " codepoints: 68 69 20 f600     ← U+F600, Private Use Area
</code></pre>
<p>U+1F600 became U+F600, an invisible character. Three-byte sequences, such as Arabic and CJK, are fine, so the bug hides until someone uses an emoji.</p>
<p><strong>Its URI decoder, meanwhile, is eight lines and completely correct.</strong> That asymmetry is the interesting part. This isn't a bad library. It's a library with two stale corners. The only way to know which is which was to read it.</p>
<p>So I wrote the decoder and kept the library for the part that actually talks to the hardware. About 530 lines, all of it plain TypeScript with no React Native imports, which means it runs in Node and tests in milliseconds.</p>
<p>Its job is to turn a record into one of a few known shapes, and that's what this type describes:</p>
<pre><code class="language-ts">export type NdefView =
  | { kind: 'empty' }
  | { kind: 'uri'; uri: string }
  | { kind: 'text'; text: string; lang: string; encoding: TextEncodingName }
  | { kind: 'mime'; mime: string; text?: string; bytes: number[] }
  | { kind: 'aar'; packageName: string }
  | { kind: 'unknown'; tnf: number; type: string; payload: number[] };
</code></pre>
<p><strong>Why a union of shapes, rather than one object with lots of optional fields?</strong> Because with optional fields, every screen has to guess which ones are filled in. Here you check <code>kind</code> once and TypeScript knows the rest. On a record where <code>kind</code> is <code>'text'</code>, <code>.uri</code> doesn't exist. So a screen that tries to read it fails to compile instead of rendering <code>undefined</code> to somebody holding a phone.</p>
<p>The <code>unknown</code> case still carries the raw <code>tnf</code>, <code>type</code>, and <code>payload</code>, so a record nothing recognises can at least be shown as a hex dump. A reader that silently drops what it doesn't understand is worse than one that says "I don't know what this is, here are the bytes".</p>
<p>One platform difference is buried inside the decoder itself. A record's <code>type</code> field arrives as raw bytes on Android, and sometimes as an already-decoded string on iOS. So the same URI record turns up as <code>[85]</code> on one platform and <code>'U'</code> on the other, 85 being the byte for the letter U.</p>
<p>That matters because <code>[85] === 'U'</code> is just false. There's no error and no warning: your comparison quietly fails to match, and a perfectly good URI record falls through to "unknown record". Convert the type to a string before you compare it, on both platforms.</p>
<h3 id="heading-test-against-the-thing-you-replaced">Test Against the Thing You Replaced</h3>
<p>This is the technique I'd most like people to steal. The tests come in three groups.</p>
<p><strong>Correctness</strong>: the decoder against hand-built payloads.</p>
<p><strong>Agreement</strong>: where the library is <em>right</em>, prove we match it exactly. Twelve real URIs encoded by the library and decoded by us, plus all 36 prefix indices. That's the cheap way to be confident about a lookup table you typed out by hand.</p>
<p><strong>Divergence</strong> is the strange one. Where the library is wrong, write a test that locks in exactly how it's wrong:</p>
<pre><code class="language-text">✓ the library discards the language code; we keep it
✓ the library truncates 4-byte UTF-8; we do not
✓ both handle 3-byte sequences, so only characters above U+FFFF break
✓ the library ignores the UTF-16 flag; we honour it
</code></pre>
<p>That looks backwards. You're writing tests that pass <strong>because</strong> a dependency is broken, and normally that's a smell.</p>
<p>Two things earn them their place. Each one is a written record of why your own code exists, sitting next to the code instead of in a commit message nobody reads. And because they assert the library's current behaviour, <strong>they start failing the day somebody upstream fixes it.</strong></p>
<p>That failure is the whole point. It isn't a broken test, it's a notification: the reason you wrote your own decoder may have just gone away, and you can go and check. A comment saying "the library is buggy" rots quietly while the library changes around it. A test saying so can't.</p>
<p>One detail decides whether these tests are useful or useless. The emoji test asserts the <strong>exact</strong> wrong answer, the code point <code>0xf600</code>, rather than just "the library disagrees with us".</p>
<p>If it only checked for disagreement, a future version with a <em>different</em> bug would still pass, and you would never notice the behaviour had changed. Pinning the specific wrong value means any change at all shows up, whether upstream fixed the bug or replaced it with a new one.</p>
<blockquote>
<p><strong>Checkpoint:</strong> <code>git checkout step-2-decode</code>. Own decoder, a Tag Info screen showing every field and the raw bytes.</p>
</blockquote>
<h2 id="heading-how-to-write-a-tag">How to Write a Tag</h2>
<p>Now the other direction. Two options, and they're opposite trades rather than variations.</p>
<p><strong>A URL record</strong> is tiny, and every phone opens it with no app installed. It's what most commercial NFC business cards do. It also needs something at the other end: a domain that stays renewed, a server that stays up, or a network connection at the moment someone taps.</p>
<p><strong>A vCard</strong> is the whole card. <code>text/vcard</code> as a MIME record, no server, works on a plane. It's also much bigger.</p>
<p>I built both and let the user choose, because the numbers make the argument better than copy could.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/0f0eb78e-e265-4239-ab2c-4e8b0a9aa155.png" alt="The app's Write tab. Two buttons side by side, URL showing 17 bytes and vCard showing 184 bytes, under the heading &quot;Write to a tag&quot; and the line &quot;Writing replaces whatever the tag holds. It does not lock it.&quot;" style="display: block;" width="600" height="400" loading="lazy">

<p>Seventeen bytes against 184, for the same person's contact details. That gap is the entire trade, and it's why the choice sits in front of the user instead of being made for them.</p>
<h3 id="heading-how-to-encode-a-vcard">How to Encode a vCard</h3>
<p>A vCard is just text. This is what the app actually writes onto the tag:</p>
<pre><code class="language-text">BEGIN:VCARD
VERSION:3.0
N:Doe;Jane;;;
FN:Jane Doe
ORG:Example Ltd
TITLE:Full-stack engineer
TEL;TYPE=CELL:+15550100
EMAIL;TYPE=INTERNET:jane@example.com
URL:https://example.com
END:VCARD
</code></pre>
<p>One field per line: a name, a colon, a value, and a carriage return plus newline at the end of every one. Build that string and you have a working card.</p>
<p>The format is from the 1990s and it shows, though, and three of its rules are easy to get wrong. Your encoder has to handle all three.</p>
<h4 id="heading-1-fold-long-lines-by-octets-not-characters">1. Fold long lines by octets, not characters.</h4>
<p>Any line longer than 75 bytes has to be broken and continued on the next one, starting with a space. The obvious way to do that is <code>line.slice(0, 75)</code>, which counts characters rather than bytes, so it can cut a two-byte character in half and leave invalid UTF-8 on the tag. Walk the string by code point instead, tracking the byte cost as you go.</p>
<h4 id="heading-2-emit-n-and-be-up-front-that-youre-guessing">2. Emit <code>N</code>, and be up front that you're guessing.</h4>
<p>Look at that <code>N:</code> line. vCard 3.0 wants the name split into <code>Family;Given;Additional;Prefix;Suffix</code>, so emitting <code>FN</code> on its own isn't enough. Splitting a display name into those parts is guesswork, and the guess is wrong for Chinese and Hungarian names, for Spanish names with two surnames, and for anyone who goes by a single name. I take the last token, document that it's a guess, and let <code>FN</code>, which is what importers actually display, carry the name exactly as typed.</p>
<h4 id="heading-3-escape-every-semicolon-inside-a-value">3. Escape every semicolon inside a value.</h4>
<p>The semicolons on that <code>N:</code> line are structural. If someone's job title were "Engineer; Lagos", writing it straight through would turn one field into two and an importer would read the rest as part of the name instead. It has to reach the tag as <code>Engineer\; Lagos</code>.</p>
<p>Get those three right and the whole encoder is about 170 lines of pure string handling, testable without a tag anywhere near it.</p>
<h3 id="heading-the-escaping-bug-that-passed-its-tests">The Escaping Bug That Passed Its Tests</h3>
<p>That third rule is where my worst bug lived. My escaper had this line:</p>
<pre><code class="language-ts">.replace(/;/g, '\;')   // ← this escapes nothing
</code></pre>
<p>vCard wants a literal backslash in front of any semicolon inside a value. <code>'\;'</code> looks like it produces one. It doesn't. JavaScript has no <code>\;</code> escape sequence, so it quietly drops the backslash and hands back a plain <code>';'</code>. That line was replacing every semicolon with itself.</p>
<p>The fix is <code>'\\;'</code>, where the first backslash escapes the second.</p>
<p>Then it got worse. I wrote a test for the escaper and asserted the <strong>unescaped</strong> output, because I still believed the line worked. The test agreed with the bug, which means it would have failed against correct code.</p>
<p>Then a third test tried to prove a field was absent with <code>not.toContain('N:')</code>. That can never pass. Every vCard starts with <code>BEGIN:VCARD</code>, and <code>BEGIN:</code> ends in <code>N:</code>.</p>
<p>Three mistakes in ten minutes, all the same misunderstanding.</p>
<p><strong>Test-first wouldn't have saved me.</strong> The test and the code shared the assumption. String escaping is a domain where they usually do.</p>
<h3 id="heading-ask-the-tag-before-you-write-to-it">Ask the Tag Before You Write to It</h3>
<p>A write replaces what's on the chip. The order matters:</p>
<pre><code class="language-text">1. Query the tag:      is it writable, how big is it really?
2. Refuse early:       read-only, or genuinely too small
3. Write
4. Read it back:       compare with what you sent
</code></pre>
<p><strong>Step 2 is the safety property.</strong> A refusal <em>before</em> the write leaves the tag untouched, while a failure <em>during</em> one can leave it half-written.</p>
<p>Step 4 exists because a write that reports success and didn't happen is the worst outcome available. Read back inside the same session and compare <strong>record content, not raw bytes</strong>. A tag may legally return a message whose framing differs from what you sent while carrying identical data.</p>
<p>All four in <strong>one session</strong>, not four. On iOS each <code>requestTechnology</code> puts a system sheet in front of the user, so splitting them means four sheets and four taps for one logical action. Android wouldn't notice the difference, which is exactly the sort of thing that makes an iOS-shaped design look arbitrary until you see it on the other platform.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/1e64e1cc-dae2-47d7-bdb5-76c93e3ca096.png" alt="The app's write screen after a successful write. A byte breakdown reads NDEF message 27 bytes, Tagframing (TLV) 3 bytes, Total needed 27 bytes, Reported capacity 137 bytes. Below it a green cardtitled &quot;Written and verified&quot; reads &quot;27 bytes written. The tag read back exactly what was sent&quot;,followed by reported capacity: 137 bytes and ndef status:2." style="display: block;" width="600" height="400" loading="lazy">

<p>You have all four steps in one screen: the tag was asked, the numbers came back measured rather than assumed, the write went out, and the read-back confirmed it byte for byte.</p>
<blockquote>
<p><strong>Checkpoint:</strong> <code>git checkout step-3-write</code>. Profile editor, vCard encoding, writing with a capacity check.</p>
</blockquote>
<h2 id="heading-will-it-fit-137-not-144">Will It Fit? 137, Not 144</h2>
<p>Here's where the project taught me something.</p>
<p>An NTAG213 has <strong>144 bytes</strong> of user memory. That number is in every spec sheet: 36 pages of 4 bytes, pages 4 through 39. I built the capacity check around it.</p>
<p>A realistic vCard (name, title, company, phone, email, one link) comes to <strong>184 bytes</strong> of text and <strong>202 bytes</strong> once it's wrapped as an NDEF message, which is the figure on the toggle a few sections back.</p>
<p>So an ordinary business card <strong>doesn't fit on an ordinary tag</strong>. That's a genuine product constraint, not a bug, and the app has to say so rather than fail mysteriously.</p>
<p>Except my number was wrong. When I finally asked a real tag how big it was, it said <strong>137</strong>.</p>
<p>144 is the chip's <em>user memory</em>. The number that matters to a writer is the maximum NDEF <strong>message</strong>, which is smaller by the tag's own bookkeeping. I had been <strong>seven bytes too generous</strong>, in the direction that tells someone their card fits when it doesn't.</p>
<p>The error hid a second one. A tag doesn't store your message bare: it wraps it in a few bytes of its own bookkeeping, called <strong>TLV framing</strong>, for type, length and value. I'd been adding those bytes to the message <em>and</em> comparing against user memory. Double-counting. Every capacity figure in play (Android's <code>getMaxSize()</code>, iOS's status query, a sensible assumption) is <em>already</em> a message size with framing excluded.</p>
<h3 id="heading-the-bigger-mistake">The Bigger Mistake</h3>
<p>Worse than the number was what I'd concluded about the platform.</p>
<p>Because iOS's <code>getTag()</code> returns only <code>{ id, tech }</code>, I concluded <strong>iOS can't report tag capacity</strong>. I wrote that in the code, in the platform comparison, and in the app's own UI, and I planned a native module around closing the gap. Here it is, shipped:</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/c3845917-23d2-4050-b76d-fa7937b19313.png" alt="A red error card in the app reading &quot;Too big for this tag. 184 bytes, assuming an NTAG213's 144.It is 40 bytes over, shorten the profile or write a URL instead.&quot; Below it, in italics, &quot;iOS doesnot report tag capacity, so this assumes an NTAG213. A larger tag will holdmore.&quot;" style="display: block;" width="600" height="400" loading="lazy">

<p>That italic line is the wrong conclusion, stated to the user as fact. Every number in the card above it rests on the guess it forced.</p>
<p>It's false. <code>ndefHandler.getNdefStatus()</code>, which is CoreNFC's <code>queryNDEFStatus</code>, returns both a read/write status and a real capacity, <strong>inside the session I was already opening</strong>. The capability was one call away from code that had been running for weeks.</p>
<p>Look at the shape of the mistake:</p>
<ul>
<li><p><strong>What I saw:</strong> one function, <code>getTag()</code>, hands back two fields and no size. True.</p>
</li>
<li><p><strong>What I decided:</strong> iOS can't tell you how many bytes fit on a tag. That doesn't follow.</p>
</li>
</ul>
<p>One function not answering a question doesn't mean the platform can't answer it. I tried one door, found it locked, and concluded there was no way into the building.</p>
<p>My rule for this project was that nothing gets written down as fact until I've seen it on a device. I followed it for the thing I measured. I forgot it for the thing I concluded from the measurement.</p>
<p>A conclusion you haven't checked is as dangerous as a number you haven't checked, and harder to catch, because it borrows the credibility of the real measurement sitting underneath it.</p>
<p>So the app now asks the tag, and only assumes when no tag has answered yet. When it assumes, it says so, every time:</p>
<pre><code class="language-text">Too big for this tag
202 bytes, assuming an NTAG213's 137. It is 65 bytes over.
Shorten the profile or write a link instead.

No tag has reported its size yet, so this assumes an NTAG213.
Tags state their real capacity when you write to them.
</code></pre>
<p>The word "assuming" appears whenever the number is assumed. It's repetitive by design: the moment the app stops saying it, a reader starts believing it measured something.</p>
<p>Here's the same card once a tag has answered:</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/716bffb6-f7e0-4c24-966f-e93cae6e08b1.png" alt="A red error card reading &quot;Too big for this tag. 202 of the 137 bytes this tag reports. It is 65bytes over, shorten the profile or write a link instead.&quot;" style="display: block;" width="600" height="400" loading="lazy">

<p>"This tag reports" instead of "assuming an NTAG213's". Same card, same layout, and the one word that changes is the one that says whether the number came from a chip or from me.</p>
<h3 id="heading-a-bug-that-made-this-harder-to-find">A Bug That Made This Harder to Find</h3>
<p>My pre-flight check threw the <strong>library's own</strong> <code>TagSizeTooSmall</code> when a message wouldn't fit. So when a write failed, the error said <code>TagSizeTooSmall</code>, exactly what CoreNFC would have produced if <em>it</em> had rejected the write.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/09e44354-736b-4a85-bee3-f97bfdb20b62.png" alt="The app's write screen. A byte breakdown reads NDEF message 202 bytes, Tag framing (TLV) 3 bytes,Total needed 205 bytes, Assumed capacity 144 bytes. Below it a red card titled &quot;Too big for thistag&quot; expands a developer detail section showing NfcError.TagSizeTooSmall and message: &quot;&quot; (empty)." style="display: block;" width="600" height="400" loading="lazy">

<p>There are two things in that developer panel. <code>NfcError.TagSizeTooSmall</code> is the library's class, raised by my own code before the tag was ever consulted. And <code>message: "" (empty)</code> is the defect behind it: the class carried the entire meaning, and the string a screen would print carried none of it.</p>
<p>Our refusal and the tag's refusal were the same string. The one question I was trying to answer (did the platform report a capacity?) was the one the error had erased.</p>
<p><strong>Never throw a dependency's error type from your own logic.</strong> It collapses "we refused" and "they refused" into one signal, and you'll want to tell them apart precisely when something is going wrong.</p>
<p>With a dedicated error type carrying the tag's own numbers, the answer was immediate:</p>
<pre><code class="language-text">WritePreflightError: too-big
tag reported status 2, 137 bytes
needed 202 bytes
</code></pre>
<p>There it was. The platform had been reporting capacity all along.</p>
<p>Same screen, same chip, before and after:</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/a39df4b8-8df2-48e5-b8ff-8a0be5848670.png" alt="The app's Tag Info screen before the fix. Capacity reads &quot;Not reported&quot;, with the explanation&quot;CoreNFC does not expose tag capacity&quot; and a note that a later phase will read it from the tag'scapability container instead." style="display: block;" width="600" height="400" loading="lazy">

<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/3e9b42f9-fee3-4f2f-8951-7b9f54a2c092.png" alt="The app's Tag Info screen. Capacity reads 137 bytes, annotated &quot;Reported by the tag itself&quot;.Above it, NDEF type reads &quot;Not reported&quot; with the note &quot;CoreNFC does not report the NDEF type name&quot;.Below, Records 1, Writable Yes, and a chip identified as NTAG21x / MIFARE Ultralight with a 7-byteUID." style="display: block;" width="600" height="400" loading="lazy">

<p>Every word under "Capacity" in the first shot is mine, and the confident one is wrong. The blue line beneath it is worse: a whole phase of native work, scheduled to close a gap that wasn't there.</p>
<p>The second reads a number, annotated <em>reported by the tag itself</em>, and nothing was added to the platform in between. Note what didn't change, though. "NDEF type" still says "Not reported", because that one genuinely isn't available. One question the platform can't answer, sitting directly above one it always could, which is exactly why I believed the wrong thing for so long.</p>
<h2 id="heading-a-focus-session-you-cant-end-without-the-tag">A Focus Session You Can't End Without the Tag</h2>
<p>A business card is a fine demo, but it only exercises half of what tags are good for. The other half is using a chip as a <strong>physical condition</strong>: something that must be true in the real world before software will do a thing.</p>
<p>So the app has a second feature: a focus timer you can't stop without walking to the tag.</p>
<p>You leave the chip somewhere inconvenient. Downstairs, in a drawer, at the back of a cupboard. Tap it to start a session. To end the session, you have to go back to it.</p>
<p>This idea isn't mine. <a href="https://github.com/awaseem/foqos">Foqos</a> (open source, on the App Store), <a href="https://github.com/cajdata/TapBlok/">TapBlok</a>, nfcGuard, and Focusaur all converge on it, and they converge because the insight isn't about NFC at all:</p>
<p><strong>The friction is geography, not the gesture.</strong> Tapping costs a second. What costs you is that the tag is downstairs. The tag's <em>location</em> is the product. NFC is merely what makes a location enforceable.</p>
<p>Three rules follow, and each is a line of code.</p>
<h4 id="heading-1-one-tag-two-meanings">1. One tag, two meanings.</h4>
<p>The same tap starts a session when idle and ends one when focused. Two tags would be two objects to lose and two habits to build. All of the decision lives in one pure function:</p>
<pre><code class="language-ts">export function verdictForTap(
  scannedTagId: string,
  boundTagId: string | null,
  isFocused: boolean
): TapVerdict {
  if (!boundTagId) return { action: 'bind' };

  if (normaliseTagId(scannedTagId) !== normaliseTagId(boundTagId)) {
    return { action: 'wrong-tag', expected: boundTagId };
  }

  return isFocused ? { action: 'end' } : { action: 'start' };
}
</code></pre>
<p>That <code>wrong-tag</code> branch is the rule everything rests on. Accept any tag and the ritual becomes "own a sticker" rather than "go to the place where the sticker lives".</p>
<p>The normalising matters more than it looks. The same physical chip is reported as <code>04C4FC91DF2A81</code> by one read path and <code>04:c4:fc:91:df:2a:81</code> by another. Treating those as different tags is a maddening bug: the right chip, in your hand, silently refused.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/abeb82a9-da3a-40e6-a84e-56988bede20c.png" alt="The app's Focus tab during a session. A large counter reads &quot;5s focused&quot; above a green &quot;Tap tag tofinish&quot; button, with a quieter underlined link below reading &quot;I cannot reach mytag&quot;." style="display: block;" width="600" height="400" loading="lazy">

<p>The green button isn't a button that ends anything. It starts a scan, and the scan is what ends the session. Underneath it, deliberately quieter, is the way out for the airport.</p>
<h4 id="heading-2-the-timer-counts-up-never-down">2. The timer counts up, never down.</h4>
<p>A countdown invites you to wait it out on the sofa, since the session ends whether or not you did anything. Counting up measures what actually happened.</p>
<h4 id="heading-3-a-broken-session-is-recorded-not-prevented">3. A broken session is recorded, not prevented.</h4>
<p>And this is where the design gets interesting.</p>
<h3 id="heading-what-it-can-actually-enforce">What It Can Actually Enforce</h3>
<p>It can't block TikTok. Really blocking another app on iOS requires <code>com.apple.developer.family-controls</code>, a <strong>privileged entitlement</strong> that Apple reviews individually and grants only to apps whose core purpose is digital wellbeing or parental control, and it's required even for TestFlight. Foqos has it. If you're following this handbook, you likely will not, and promising otherwise would be a promise you couldn't keep.</p>
<p>So it enforces the one thing it actually can: <strong>the record</strong>.</p>
<p>There's an escape hatch, because a commitment device with no way out is one you uninstall the first time you're genuinely stuck at an airport. Taking it costs a permanent, visible mark: this session will be recorded as ended early. That mark is permanent and you'll see it every time you open this tab.</p>
<p>And the <strong>history is the vault</strong>, not notes or credentials, but the record itself, because that's the only thing in the app worth protecting from its own user. The protection is asymmetric:</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>Reading the record</td>
<td>Always free. The point is that you look at it</td>
</tr>
<tr>
<td>Adding to it</td>
<td>Only by living through a session</td>
</tr>
<tr>
<td><strong>Clearing it</strong></td>
<td><strong>Requires the tag</strong></td>
</tr>
</tbody></table>
<p>A history you can wipe at 11pm from the sofa records nothing. Erasing it costs exactly what earning it did: the walk.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/fd78fb0a-2aa2-402e-8c6f-c91738a27c49.png" alt="The Focus tab between sessions. Three figures across the top read 1m Focused, 2 Streak, 0 Endedearly. Below, a list headed &quot;The record&quot; holds two entries, &quot;4s focused&quot; and &quot;1m focused&quot;, bothdated 13 Sep, above a collapsed control labelled &quot;Clear therecord&quot;." style="display: block;" width="600" height="400" loading="lazy">

<p>"Ended early" is a column whether or not you have any, which is the point. It sits next to the streak, permanently, so the cost of the escape hatch is visible before you ever use it. And "Clear the record" is the collapsed control at the bottom: the one action in the app that asks for the tag.</p>
<p>Here are two smaller decisions that turned out to matter. <strong>A running session survives a relaunch</strong>, because it's persisted, so force-quitting isn't a silent way out. The only exits are the tag and the hatch, and one leaves a mark.</p>
<p>And <strong>broken sessions still count toward total focused time</strong>, because you <em>were</em> focused until you weren't. Zeroing it would be punitive rather than accurate.</p>
<p>The streak, by contrast, is deliberately harsh: one broken session resets it to zero. A number that can't be lost isn't worth looking at.</p>
<h3 id="heading-two-react-bugs-the-compiler-caught">Two React Bugs the Compiler Caught</h3>
<p>Both are general React bugs rather than NFC ones, and neither was caught by me. The React Compiler ships lint rules through <a href="https://react.dev/reference/eslint-plugin-react-hooks"><code>eslint-plugin-react-hooks</code></a> that flag code it can't safely optimise, and two of them fired here. You don't have to adopt the compiler to get them.</p>
<pre><code class="language-ts">const [now, setNow] = useState(Date.now()); // ✗ impure during render
</code></pre>
<p>That's the <a href="https://react.dev/reference/eslint-plugin-react-hooks/lints/purity"><code>purity</code></a> rule, and it names this exact case: <code>Date.now()</code> is listed alongside <code>Math.random()</code> and <code>crypto.randomUUID()</code> as an API that "returns a different value for the same inputs". Reading the clock during render makes the component produce different output each time.</p>
<p>The obvious fix (setting it at the top of an effect) trips a second rule. <a href="https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect"><code>set-state-in-effect</code></a> puts it plainly: "Setting state immediately inside an effect forces React to restart the entire render cycle", producing "an extra render pass that could have been avoided".</p>
<p>The <code>purity</code> page's own fix is a lazy initialiser, <code>useState(() =&gt; Date.now())</code>, and for a clock that starts when the component mounts, that's the right answer. This timer doesn't start at mount, it starts when a session does, so a mount-time stamp would already be stale by then and <code>elapsed</code> would render negative for a frame.</p>
<p>Starting at <code>0</code> is both pure and a usable sentinel: falsy means "no tick yet", so the label shows nothing rather than nonsense.</p>
<p>The version that's both correct and clean defers by one task:</p>
<pre><code class="language-ts">useEffect(() =&gt; {
  if (!session) return;

  // Deferred rather than called straight away: a synchronous setState inside
  // an effect cascades a second render pass. A zero timeout hands it to the
  // next task, which updates just as promptly without the cascade.
  const first = setTimeout(() =&gt; setNow(Date.now()), 0);
  const id = setInterval(() =&gt; setNow(Date.now()), 1000);

  return () =&gt; {
    clearTimeout(first);
    clearInterval(id);
  };
}, [session]);
</code></pre>
<h2 id="heading-why-your-nfc-lock-isnt-secure">Why Your NFC Lock Isn't Secure</h2>
<p>The focus feature uses a tag's identifier as a key. So do most NFC "lock" apps. It's worth being blunt about what that is and isn't.</p>
<p>A tag's UID is world-readable and trivially copied. It's not a secret. It's a serial number, broadcast to anything that asks.</p>
<p>This is also what Apple's own Shortcuts automation keys on, as the first section noted, which tells you how the platform itself rates the guarantee: fine for "turn on my desk lamp", never offered as a credential. A £20 device clones one in seconds, and phones can emulate some of them outright. An access system built on "is this UID correct?" is theatre.</p>
<p>For the focus timer, that's completely fine, and worth saying: <strong>the threat model is you, being lazy, in your own house.</strong> Cloning your own tag to skip a walk is a level of effort that defeats the point of the exercise. Friction is the product, security isn't.</p>
<p>But if you're reaching for a tag as an actual credential (a door, a payment, or a device pairing), the UID is the wrong primitive and you need a chip that can do cryptography.</p>
<p>An <strong>NTAG424 DNA</strong> is the usual answer. Rather than presenting a static number, it computes a message authentication code over a counter that increments on every tap, using a key that never leaves the chip. Each tap produces a different, signed value, so a captured one is useless a second later. That's the difference between an identifier and an authenticator.</p>
<p>So here's what you take away: <strong>A UID answers "which tag is this?" and nothing more.</strong> If your security depends on the answer being unforgeable, you need a chip that signs, not one that announces.</p>
<h2 id="heading-four-gotchas-that-cost-me-an-evening-each">Four Gotchas That Cost Me an Evening Each</h2>
<p>Each of these looked like a bug in my code and was really a quirk of the platform.</p>
<h3 id="heading-gotcha-1-the-system-sheet-vanishes-with-no-error">Gotcha 1: The System Sheet Vanishes With No Error</h3>
<p>You start a scan. The sheet appears for a moment and disappears. No error, no rejection, and nothing in the console.</p>
<p>This happens because the CoreNFC session was <strong>deallocated</strong>. Swift frees an object as soon as nothing is holding a reference to it, which is what Automatic Reference Counting, or ARC, does. So if you keep the session in a local variable inside the function that started it, the variable dies when the function returns, and the session goes with it.</p>
<p>To fix this, retain the session on something that outlives the call. In an Expo module, a property:</p>
<pre><code class="language-swift">// Held for the life of the module, not the scan.
private var readSession: Any?
</code></pre>
<p>This is the single easiest way to get a CoreNFC integration subtly wrong, and nothing tells you.</p>
<h3 id="heading-gotcha-2-your-result-gets-overwritten-by-the-session-ending">Gotcha 2: Your Result Gets Overwritten by the Session Ending</h3>
<p>You read a tag successfully, resolve the promise, and JavaScript receives an error instead.</p>
<p>This happens because <strong>a successful read also invalidates the session</strong>, so <code>didInvalidateWithError</code> fires <em>after</em> your completion handler. If both paths settle the same promise, the later one wins.</p>
<p>To fix this, guard settling so it happens exactly once. One lock, one place:</p>
<pre><code class="language-swift">private func settle(resolving value: [String: Any]) {
  lock.lock()
  defer { lock.unlock() }

  guard let promise else { return }   // already settled: do nothing
  self.promise = nil
  promise.resolve(value)
}
</code></pre>
<p>With four nested asynchronous steps and five failure paths, this has to be enforced rather than assumed.</p>
<h3 id="heading-gotcha-3-missing-required-entitlement-for-an-entitlement-you-have">Gotcha 3: <code>Missing required entitlement</code> for an Entitlement You Have</h3>
<p>You have <code>NDEF</code> and <code>TAG</code> in your entitlements and the session still refuses to start.</p>
<p>This happens because of <strong>polling options</strong>, the list of radio standards you tell CoreNFC to listen for when you open a session. Each one is gated by its own entitlement. I asked for <code>[.iso14443, .iso15693, .iso18092]</code>, and that last one is FeliCa, a standard used mostly in Japan, which additionally requires <code>com.apple.developer.nfc.readersession.felica.systemcodes</code>. Asking for it without that key fails <strong>the entire session</strong>, not just that polling mode, and the error never says "FeliCa".</p>
<p>To fix this, ask only for what you can sign for:</p>
<pre><code class="language-swift">pollingOption: [.iso14443, .iso15693],
</code></pre>
<p><code>.iso14443</code> covers NTAG and MIFARE, which is everything a tag project needs. I'd added the third "so unexpected tags produce better errors". It produced a session that couldn't start.</p>
<p>This is the same lesson as the wildcard-profile error from earlier, arriving from the opposite direction: there, a <em>missing</em> entitlement surfaced as a code-signing failure. Here, an entitlement I never needed surfaced as a runtime one.</p>
<h3 id="heading-gotcha-4-cannot-find-yourclass-in-scope-for-a-file-that-exists">Gotcha 4: <code>cannot find 'YourClass' in scope</code> for a File That Exists</h3>
<p>You add a Swift file to a local Expo module, build, and the compiler insists the class doesn't exist.</p>
<p>This happens because of how iOS dependencies are wired up. CocoaPods is the package manager that builds them, and each one ships a <strong>podspec</strong>, a small file listing which sources belong to it. Yours says "every <code>.swift</code> file in this folder", written as <code>**/*.swift</code>.</p>
<p>The catch: <strong>CocoaPods expands that pattern once, when</strong> <code>pod install</code> <strong>runs.</strong> It's a list, not a live rule. A file you create afterwards isn't in the Xcode build at all, so the compiler is telling the truth. As far as it knows, your class doesn't exist.</p>
<p>To fix this, remember the rule and stop losing ten minutes to it each time:</p>
<blockquote>
<p>Adding a <strong>function</strong> to an existing file → rebuild. Adding a <strong>file</strong> → <code>pod install</code>, <em>then</em> rebuild.</p>
</blockquote>
<p>The error message mentions neither.</p>
<h2 id="heading-why-you-cant-build-tap-to-pay">Why You Can't Build Tap to Pay</h2>
<p>This is where the gap between the two platforms stops being a matter of degree. Know it before you promise anything to a product manager.</p>
<p>"Tap to pay" means two different things.</p>
<p>First, there's <strong>paying with your phone</strong>: Apple Pay, or a bank card in Google Wallet. On iOS the Secure Element is closed. There's no third-party API. Not restricted, not entitled: absent.</p>
<p>Second, there's <strong>accepting payments on your phone</strong>: <em>Tap to Pay on iPhone</em>, or the <code>ProximityReader</code> framework. This exists, and you still can't just build it:</p>
<ul>
<li><p>An <strong>organization-level</strong> developer account, requested as the <strong>Account Holder</strong></p>
</li>
<li><p><strong>Separate TEST and LIVE entitlements</strong>, applied for individually</p>
</li>
<li><p>Apple reviews against predefined criteria, and LIVE approval can take <strong>weeks</strong></p>
</li>
<li><p>You must integrate through an approved payment service provider: Stripe, Adyen, or Square</p>
</li>
</ul>
<p>Now Android. <code>HostApduService</code> lets <strong>any app emulate a card.</strong> No approval, no entitlement, and no PSP. Implement <code>processCommandApdu()</code>, register your <strong>AID</strong>, and you're done. An AID is an Application Identifier, the number a payment terminal asks for to decide which app on the phone should answer.</p>
<p>There's one real gate: AIDs registered under <code>CATEGORY_PAYMENT</code> only work when your app is the default wallet (the Wallet role holder on Android 15+) or is foregrounded and calls <code>setPreferredService</code>. But <code>CATEGORY_OTHER</code>, which covers closed-loop cards, loyalty, access control and stored value, is <strong>open and always active</strong>.</p>
<table>
<thead>
<tr>
<th></th>
<th>iOS</th>
<th>Android</th>
</tr>
</thead>
<tbody><tr>
<td>Emulate a card</td>
<td><strong>Impossible</strong></td>
<td><code>HostApduService</code>, no approval</td>
</tr>
<tr>
<td>Payment AIDs</td>
<td>N/A</td>
<td>Default-wallet gated</td>
</tr>
<tr>
<td>Non-payment AIDs</td>
<td>N/A</td>
<td><strong>Open</strong></td>
</tr>
<tr>
<td>Accept payments</td>
<td>Entitlement + PSP + weeks</td>
<td>Open</td>
</tr>
</tbody></table>
<p>Unlike every other difference in this handbook, this isn't a difference of degree or of shape. <strong>One platform simply doesn't offer the capability.</strong> If your product plan involves a phone pretending to be a card, that plan is Android-only, and it's better to learn it now than after a sprint.</p>
<h2 id="heading-why-you-might-write-your-own-native-module">Why You Might Write Your Own Native Module</h2>
<p>Up to this point everything has run on <code>react-native-nfc-manager</code>. The last third of this project replaced it, and the reason changed partway through.</p>
<p>The original justification was the capacity gap: <em>iOS can't report capacity, so we need our own native code to read it.</em> That argument evaporated, as you've seen. It was an inference, not an observation.</p>
<p>So rather than quietly keeping the work with its motivation gone, here's the real version: <strong>some teams can't take a third-party dependency.</strong> Internal-only policies, audit requirements, or simply a package they can't get a fix merged into on any useful timescale. "How would I build this myself?" is worth answering on its own terms.</p>
<p>And for <em>this</em> dependency specifically, the evidence was already gathered, by reading it:</p>
<table>
<thead>
<tr>
<th>Finding</th>
<th>Where</th>
</tr>
</thead>
<tbody><tr>
<td>Text decoder discards the language code it just measured</td>
<td><code>ndef-lib/ndef-text.js</code></td>
</tr>
<tr>
<td>UTF-16 flag ignored, an open <code>TODO</code></td>
<td><code>ndef-lib/ndef-text.js</code></td>
</tr>
<tr>
<td><code>String.fromCharCode</code> truncates above U+FFFF</td>
<td><code>ndef-lib/util.js</code></td>
</tr>
<tr>
<td><code>index.d.ts</code> is invalid TypeScript, compiles only because <code>skipLibCheck</code> is on</td>
<td><code>index.d.ts</code></td>
</tr>
<tr>
<td>Package root throws outside a native runtime</td>
<td><code>src/NativeNfcManager.js</code></td>
</tr>
<tr>
<td>Every error class carries an empty <code>message</code></td>
<td><code>src/NfcError.js</code></td>
</tr>
</tbody></table>
<p>That last one caused a real bug in Phase 1: a failed scan rendered <strong>nothing at all</strong>, because the screen did <code>setError(err.message)</code>, the message was <code>''</code>, and React treats an empty string as falsy. The meaning lived only in the class.</p>
<p>None of these are fixable from JavaScript.</p>
<h3 id="heading-the-scaffolding-is-no-longer-the-hard-part">The Scaffolding Is No Longer the Hard Part</h3>
<pre><code class="language-bash">npx create-expo-module@latest --local --name NfcNative \
  --package com.you.nfcnative -p apple android --features Function
</code></pre>
<p>There are four files, wired into the build automatically by <code>pod install</code>. No Xcode project surgery, <code>RCT_EXPORT_METHOD</code> macros, or hand-written JSI, the C++ layer that lets JavaScript call native code directly. If you last wrote a React Native native module in the bridge era, that's the headline.</p>
<p>There are two snags, and neither are documented: <code>--name</code> sets the <em>native module</em> name, while the <strong>directory</strong> comes from a positional path argument (so without one it lands in <code>modules/my-module</code>). And the generated podspec declares an iOS deployment target that can silently raise your app's minimum.</p>
<h3 id="heading-typed-errors-that-actually-carry-a-message">Typed Errors That Actually Carry a Message</h3>
<pre><code class="language-swift">internal final class NoNfcSettingsException: Exception {
  override var reason: String {
    "iOS has no NFC setting to open. NFC is available whenever the hardware supports it."
  }
}
</code></pre>
<p>Expo's <code>Exception</code> gives each one a code <em>and</em> a message, both readable from JavaScript. That's the direct fix for the defect behind the silent failure above.</p>
<p>And here's the part that surprised me: <strong>owning the native side doesn't exempt you from error plumbing.</strong> Expo wraps your exception:</p>
<pre><code class="language-text">FunctionCallException: Calling the 'openNfcSettings' function has failed
  → Caused by: NoNfcSettingsException: iOS has no NFC setting to open. …
</code></pre>
<p><code>err.message</code> is now the <em>framework</em> describing its own plumbing. Your sentence is at the end of the cause chain. This is the mirror image of the library's problem. There the message was empty, here it's buried, and both break the same reflex.</p>
<p>Here's that chain rendered in the app, exactly as JavaScript received it:</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/6952f351-8efb-41d9-a983-af13129575a2.png" alt="The app's developer panel showing a purple error block: &quot;Error: FunctionCallException: Calling the'openNfcSettings' function has failed (at ExpoModulesCore/AsyncFunctionDefinition.swift:123) →Caused by: NoNfcSettingsException: iOS has no NFC setting to open. NFC is available whenever thehardware supports it. (at NfcNative/NfcNativeModule.swift:58)&quot;" style="display: block;" width="600" height="400" loading="lazy">

<p>We have three lines of framework before a single word a person could use. The fix isn't in Swift, it's in the screen: walk the cause chain, show the deepest message first, and put the rest behind a disclosure for whoever actually wants it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/1a9b90a4-7d80-46db-a63f-34db085f99ef.png" alt="The same panel after the fix, showing only &quot;iOS has no NFC setting to open. NFC is availablewhenever the hardware supports it. (at NfcNative/NfcNativeModule.swift:58)&quot; above a collapsedsection labelled RAW ERROR CHAIN." style="display: block;" width="600" height="400" loading="lazy">

<p>Same failure, same information, with nothing thrown away. The sentence written in Swift is the one that leads, and <code>RAW ERROR CHAIN</code> is one tap away when you need it.</p>
<p>Owning the native side changes which layer surprises you.</p>
<h3 id="heading-the-bug-272-passing-tests-could-not-catch">The Bug 272 Passing Tests Could Not Catch</h3>
<p>After switching the app over, cancelling a scan rendered a red "Could not read the tag" card instead of nothing.</p>
<p>Our Swift throws <code>UserCancelledException</code>. The mapping table was keyed on <code>UserCancelledException</code>. They don't match, because <strong>Expo derives the code</strong>: strip the trailing <code>Exception</code>, split camelCase, upper-case, prefix <code>ERR_</code>:</p>
<pre><code class="language-text">UserCancelledException  →  ERR_USER_CANCELLED
</code></pre>
<p>Why every test passed:</p>
<pre><code class="language-ts">const wrapped = (code, message) =&gt;
  new Error(`Calling the 'readTag' function has failed → Caused by: ${code}: ${message}`);
</code></pre>
<p>There's no <code>code</code> property, because I didn't know Expo set one. <strong>The code and its tests shared a single wrong assumption and agreed with each other perfectly.</strong></p>
<p>A fixture you invented can only prove your code is self-consistent. It took a thumb on a Cancel button.</p>
<p>The fix keeps the table keyed on the Swift class names and <em>derives</em> the <code>ERR_</code> forms, so there's one source of truth instead of two lists that drift. The regression is now pinned by a test using the verbatim device error, <code>code</code> property and all.</p>
<blockquote>
<p><strong>Checkpoint:</strong> <code>git checkout step-4-own-module</code>. The module alongside the library.</p>
</blockquote>
<h2 id="heading-how-to-prove-parity-before-you-switch">How to Prove Parity Before You Switch</h2>
<p>Don't swap implementations on faith. Read the same physical tag through both and diff the results.</p>
<p>The design decision that made this useful: <strong>"different" isn't one outcome.</strong> Our read reports capacity and writability that the library's read path doesn't carry, and scoring that as a mismatch would be actively misleading.</p>
<table>
<thead>
<tr>
<th>Status</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>same</code></td>
<td>Both reported it, they agree</td>
</tr>
<tr>
<td><code>differs</code></td>
<td>Both reported it, they disagree. <strong>The only bad one</strong></td>
</tr>
<tr>
<td><code>native-only</code></td>
<td>Ours knows more. <em>The reason to switch</em></td>
</tr>
<tr>
<td><code>library-only</code></td>
<td>We lost something. <strong>Also blocks the swap</strong></td>
</tr>
<tr>
<td><code>neither</code></td>
<td>Nothing to conclude</td>
</tr>
</tbody></table>
<p><code>library-only</code> blocking the swap matters: losing information is a real problem even though it isn't a contradiction.</p>
<p>The result on a real NTAG213: <strong>four fields are identical, two are reported only by our module, with zero conflicts.</strong> That's the evidence the switch was made on, rather than a feeling that the new code looked right.</p>
<h2 id="heading-what-a-config-plugin-was-doing-for-you">What a Config Plugin Was Doing For You</h2>
<p>The riskiest part of deleting the dependency wasn't code.</p>
<p><code>react-native-nfc-manager</code> ships a <strong>config plugin</strong>, and that plugin was generating the iOS NFC entitlement and <code>NFCReaderUsageDescription</code>. Remove the package and both vanish, and <strong>the app loses NFC with no error at all.</strong> Nothing fails at build time. The sheet simply never appears again.</p>
<p>So the order was: declare them yourself in <code>app.json</code>, prebuild, verify the output is <strong>byte-identical</strong> to what the plugin produced, <em>then</em> remove the plugin, verify again, <em>then</em> remove the package.</p>
<p>Removing a dependency means inheriting its build configuration. The code it exports is the visible half.</p>
<h3 id="heading-keep-the-evidence-after-deleting-the-dependency">Keep the Evidence After Deleting the Dependency</h3>
<p>The argument for replacing that library rests on defects in a package that no longer exists. Delete it and the tests proving those defects stop running, and the <em>agreement</em> tests go too, leaving a hand-typed 36-entry lookup table unverified.</p>
<p>So the repo keeps a frozen copy under <code>vendor/</code>, with its MIT licence, imported by nothing but one test file, and excluded from ESLint and Prettier, because its value is being wrong in documented ways, and reformatting it would destroy the thing it demonstrates.</p>
<pre><code class="language-text">✓ every error class is constructed with an empty message
✓ turns U+1F600 into U+F600, a Private Use Area character
✓ discards the language code it just measured
✓ ignores the UTF-16 flag in the status byte
</code></pre>
<p>If a future version fixes any of that, these fail, which is the signal to reconsider, not a nuisance.</p>
<blockquote>
<p><strong>Checkpoint:</strong> <code>git checkout step-5-no-dependency</code></p>
</blockquote>
<h2 id="heading-how-to-lock-a-tag-forever">How to Lock a Tag Forever</h2>
<p>One operation in this whole field can't be undone. It's the only place where getting the interaction design wrong destroys something physical, which is why it comes last.</p>
<p><code>NFCNDEFTag.writeLock</code> on iOS, <code>Ndef.makeReadOnly()</code> on Android. Both burn the chip's lock bits. The tag can be read forever and never written again: not by your app, or any other app, or any phone. There's no undo and no factory reset.</p>
<p>Real deployments do this constantly. An event badge, a product-authentication seal, or a museum label: anything handed to the public gets locked, because a tag you can rewrite is a tag anyone can rewrite.</p>
<h3 id="heading-the-gate-is-the-feature">The Gate Is the Feature</h3>
<p>The native call is four lines. Everything interesting happens before it.</p>
<p>Two taps guards a write in this app, and that's right for a write: a write is reversible, you simply write something else. It's plainly not enough here. So the gate borrows the pattern GitHub uses for deleting a repository: <strong>type the thing's name to prove you know which thing you're destroying.</strong></p>
<p>The <code>status</code> it takes is the tag's own NDEF state, the same value the write path asks for: not NDEF at all, read-write, or already read-only.</p>
<pre><code class="language-ts">export function lockGate(tagId, status, typed): LockGate {
  if (!tagId) return { state: 'no-tag' };
  if (status === NDEF_STATUS.READ_ONLY) return { state: 'already-locked' };
  if (status === NDEF_STATUS.NOT_SUPPORTED) return { state: 'not-lockable' };

  return normaliseTagId(typed) === normaliseTagId(tagId)
    ? { state: 'armed', tagId }
    : { state: 'needs-confirmation', expected: tagId };
}
</code></pre>
<p>A confirmation dialog measures willingness. Typing the identifier measures <strong>attention</strong>. The failure mode worth designing against isn't someone who wants to lock a tag. It's someone who wants to lock a tag and is holding the wrong one.</p>
<p>Which is also why the screen won't arm until you've <strong>read the tag first</strong>, and shows what's currently on it. An unintended chip announces itself before it can be spent.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/41953d11-0ac3-42ec-be20-a7205b856dd6.png" alt="The app's Lock a tag screen. A red card headed &quot;This cannot be undone&quot; explains that the tag cannever be written again by any app or any phone. Below it the tag's details, Identifier04C4FC91DF2A81 and Status Writable, then a field headed &quot;Type the identifier to continue&quot; with theidentifier typed into it, and a red &quot;Lock this tag forever&quot; button." style="display: block;" width="600" height="400" loading="lazy">

<p>The identifier is on screen and also has to be typed. That looks redundant until you picture the failure it's for: the right person, the wrong chip.</p>
<p>Note the order in that function: <code>already-locked</code> is checked <em>before</em> the typed confirmation, so nobody can type their way into "locking" an already-locked tag and be told it worked. It didn't work. There was nothing to do.</p>
<h3 id="heading-nothing-to-do-is-not-something-went-wrong">"Nothing to Do" Is Not "Something Went Wrong"</h3>
<p><code>AlreadyLockedException</code> is deliberately distinct from <code>LockFailedException</code>, and the UI renders it <strong>green</strong>, with no lock button. The tag is in exactly the state you asked for. Reporting that as a failure would alarm someone about a perfectly good chip.</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/3c4efe39-77c7-4aff-9eae-0ce0fbf70bb1.png" alt="The same screen after locking. Status reads &quot;Locked, read-only, permanently&quot;, and a green cardheaded &quot;Already locked&quot; reads &quot;This tag is permanently read-only. Nothing to do, and nothing was changed.&quot;" style="display: block;" width="600" height="400" loading="lazy">

<p>"Nothing to do, and nothing was changed" is doing real work in that sentence. It tells you the app didn't try, which is the part you want to know about an operation that can't be repeated.</p>
<p>This is the same principle as never throwing a dependency's error type from your own logic: two different situations must not arrive as one signal, and the moment you want them apart is the moment something is going wrong.</p>
<h3 id="heading-verify-because-you-cant-retry-to-find-out">Verify, Because You Can't Retry to Find Out</h3>
<p>Both implementations re-read the status afterwards. That check exists in the write path too, but it carries different weight here:</p>
<p>A failed write is recoverable: write again. A lock that reports success and didn't happen sends a tag into the world believing it's protected, and you can't retry to find out, because <strong>retrying is itself the destructive act.</strong></p>
<p>So an unverified lock isn't reported as a soft warning the way an unverified write is. The copy says the chip's state is unknown and to read it before relying on it.</p>
<p>The strongest confirmation comes later, from the tag rather than the app. Try to write to it again and CoreNFC itself refuses, in the system sheet, before your code gets a say:</p>
<img src="https://cdn.hashnode.com/uploads/covers/66c84fbe8c8c80534346db05/541fc3c0-a92a-45e1-8c0e-31e38c7663e2.png" alt="541fc3c0-a92a-45e1-8c0e-31e38c7663e2" style="display: block;" width="600" height="400" loading="lazy">

<p>That sentence is written by iOS, not by this app. It's the only proof that really counts, and the one you can never collect twice.</p>
<h3 id="heading-a-separate-class-not-a-flag">A Separate Class, Not a Flag</h3>
<p><code>NfcLockSession</code> duplicates a fair amount of the write session: setup, delegate, and settle-once discipline. That's deliberate.</p>
<p>The alternative was a <code>lock: Bool</code> on the write session. <strong>A boolean parameter that sometimes destroys the tag is exactly what gets passed by accident in a refactor three months later</strong>, by someone who has never read the file. Two call sites, two intentions, and no shared branch reachable from the wrong place.</p>
<p>Sometimes the right response to "this is nearly the same code" is to let it be nearly the same code.</p>
<h3 id="heading-and-one-test-that-was-right-while-the-code-was-wrong">And One Test That Was Right While the Code Was Wrong</h3>
<pre><code class="language-ts">it('refuses a tag that is not NDEF at all', () =&gt; {
  expect(lockGate(TAG, NDEF_STATUS.NOT_SUPPORTED, TAG).state).toBe('armed');
});
</code></pre>
<p>The name says <em>refuses</em>. The assertion says <em>armed</em>. It passed, because the code did arm, and <code>writeLock</code> is a method on <code>NFCNDEFTag</code>, so a non-NDEF chip should never have been offered it.</p>
<p>The name was right and the code was wrong. It was caught by reading a <strong>passing</strong> test's name next to its assertion, which is the only way it could have been caught: a test that agrees with the wrong code is invisible to a test run.</p>
<h2 id="heading-how-would-you-actually-ship-this">How Would You Actually Ship This?</h2>
<p>Everything above was built locally with <code>expo run:ios</code>, Xcode, CocoaPods, and twice, a completely full disk. The alternative is EAS Build, and it deserves an real comparison rather than a recommendation.</p>
<p>Everything below was run: one production build on EAS, plus a deliberately rigged experiment to test the headline claim rather than assume it. The only thing I have <em>not</em> done is install the resulting <code>.ipa</code>. It's an App Store build, so it can't be side-loaded, and every NFC claim in this handbook still rests on locally-built binaries on a real phone.</p>
<h3 id="heading-the-step-eas-would-have-saved">The Step EAS Would Have Saved</h3>
<p>The worst afternoon of this project was this error:</p>
<pre><code class="language-text">Provisioning Profile "iOS Team Provisioning Profile: *" does not support
the NFC Tag Reading capability.
</code></pre>
<p>The fix was manual and undiscoverable from the message: register an explicit App ID in Apple's portal, tick <strong>NFC Tag Reading</strong>, and regenerate the profile. Nothing in the error suggests opening a browser.</p>
<p><strong>EAS does that step automatically.</strong> If a supported entitlement is in your entitlements file, <code>eas build</code> enables the matching capability on the Apple Developer Console and skips it if it's already on. And <code>com.apple.developer.nfc.readersession.formats</code>, exactly the key this app declares, is on the supported list by name.</p>
<p>So the single most painful manual step in the whole handbook is automated by the thing I didn't use.</p>
<h3 id="heading-how-to-prove-it-rather-than-believe-it">How to Prove It Rather Than Believe It</h3>
<p>Running <code>eas build</code> against TapCard's real bundle identifier can't demonstrate this, and it's worth understanding why before trusting anyone's screenshot of it working:</p>
<pre><code class="language-text">✔ Bundle identifier registered com.nfccard.tap
✔ Synced capabilities: No updates
</code></pre>
<p><code>No updates</code>, because that App ID already had NFC Tag Reading enabled. I enabled it by hand, in a browser, in the chapter this section is about. All this proves is that EAS agrees with work I already did. Plenty of "EAS handles it for you" claims rest on exactly this output.</p>
<p>The real test needs a bundle identifier that has never existed. So: a throwaway project, <code>com.nfccard.tap.eastest</code>, containing essentially nothing but the entitlement, deliberately kept separate from the real app rather than temporarily renaming its bundle ID, which risks muddling stored credentials.</p>
<pre><code class="language-text">✔ Bundle identifier registered com.nfccard.tap.eastest
✔ Synced capabilities: Enabled: NFC Tag Reading
</code></pre>
<p><strong>That's the claim, observed.</strong> An App ID that didn't exist, registered and given the NFC capability from the entitlements file alone, with no browser and no portal. And because the sync runs at the credentials step, that command was <code>eas credentials:configure-build</code>, and it consumed no build.</p>
<p>One practical note if you repeat this: run the <strong>real</strong> build first. Distribution certificates are account-wide and Apple limits how many you may hold, so doing the throwaway first would burn one on an app you intend to delete. Done in that order, the scratch app offered to reuse the real certificate and only created its own provisioning profile, which is per bundle ID.</p>
<h3 id="heading-what-the-cli-actually-does">What the CLI Actually Does</h3>
<p>The mapping isn't magic and it's not buried. It's a lookup table, and NFC has an entry in it (<code>eas-cli/build/credentials/ios/appstore/capabilityList.js</code>):</p>
<pre><code class="language-js">{
  name: 'NFC Tag Reading',
  entitlement: 'com.apple.developer.nfc.readersession.formats',
  capability: CapabilityType.NFC_TAG_READING,
  // Technically it seems only `TAG` is allowed, but many apps and packages tell users to add `NDEF` as well.
  validateOptions: createValidateStringArrayOptions(['NDEF', 'TAG']),
  getSyncOperation: getDefinedValueSyncOperation,
}
</code></pre>
<p>Read that comment again, because it is quietly about you: <code>NDEF</code> <strong>may not be a real value.</strong> Every tutorial tells you to write <code>["NDEF", "TAG"]</code>, this handbook's own <code>app.json</code> writes <code>["NDEF", "TAG"]</code>, and the person maintaining the mapping table clearly suspects only <code>TAG</code> means anything, but accepts both, because refusing the pair would break everybody. That's what a convention looks like when nobody checks the spec.</p>
<p><code>getDefinedValueSyncOperation</code> is the other half. The operation keys off whether the entitlement is <em>defined</em>, which is why the sync runs in both directions rather than only adding things.</p>
<p>And one practical detail the documentation doesn't tell you: the sync is triggered by the <strong>credentials</strong> step, not the build step.</p>
<pre><code class="language-text">SetUpTargetBuildCredentials.runAsync()
  └─ ensureBundleIdExistsAsync({ entitlements, … })
       └─ syncCapabilitiesAsync()
            → "Synced capabilities: Enabled: NFC Tag Reading"    (or "No updates")
</code></pre>
<p>So <code>eas credentials:configure-build --platform ios</code> registers the App ID and syncs the capabilities <strong>without consuming a build</strong>. If all you want is Apple's side of the setup done correctly, you don't have to pay for a build to get it.</p>
<h3 id="heading-the-trap-that-comes-with-it">The Trap That Comes With It</h3>
<p>The sync runs both ways: if a capability is enabled for your app remotely, but not present in the native entitlements file, running <code>eas build</code> will automatically <strong>disable</strong> it.</p>
<p>A team that manages capabilities by hand in the portal <em>and</em> builds with EAS will watch EAS switch things off. The entitlements file becomes the source of truth whether you meant it to or not.</p>
<p><code>EXPO_NO_CAPABILITY_SYNC=1</code> opts out, with the caveat that opting out means remote changes stop syncing, which produces provisioning-profile mismatches later. Pick one owner for capabilities and let it own them.</p>
<h3 id="heading-what-eas-would-not-have-helped-with">What EAS Would Not Have Helped With</h3>
<p>"Use EAS" isn't an answer to most of this project's pain, and pretending otherwise would be selling something:</p>
<table>
<thead>
<tr>
<th>Problem</th>
<th>Would EAS have helped?</th>
</tr>
</thead>
<tbody><tr>
<td>NFC Tag Reading capability on the App ID</td>
<td>✅ automated</td>
</tr>
<tr>
<td>A full disk, twice</td>
<td>✅ builds happen elsewhere</td>
</tr>
<tr>
<td>A Gradle daemon holding memory after the build</td>
<td>✅ nothing runs locally</td>
</tr>
<tr>
<td><code>pod install</code> needed after adding a Swift file</td>
<td>✅ every build is clean</td>
</tr>
<tr>
<td>The deallocated CoreNFC session</td>
<td>❌ a code bug</td>
</tr>
<tr>
<td>Settling a promise twice</td>
<td>❌ a code bug</td>
</tr>
<tr>
<td>The FeliCa polling entitlement</td>
<td>❌ not a capability, a key EAS doesn't manage</td>
</tr>
<tr>
<td><code>String.fromCharCode</code> truncating an emoji</td>
<td>❌ a dependency bug</td>
</tr>
<tr>
<td>Expo deriving <code>ERR_USER_CANCELLED</code></td>
<td>❌ a wrong assumption</td>
</tr>
<tr>
<td>Reading a tag at all</td>
<td>❌ there is no cloud substitute for a chip</td>
</tr>
</tbody></table>
<p><strong>EAS removes machine problems, not NFC problems.</strong> Every finding in this handbook that was actually about NFC would have happened identically.</p>
<h3 id="heading-the-trade">The Trade</h3>
<p>Local builds cost disk, memory, and setup. This project filled a 460 GB disk twice, had three background processes killed under memory pressure, and lost a rebuild to a stale Gradle daemon.</p>
<p>EAS costs queue time and a cloud project, and puts your signing credentials on Expo's servers. What it can't shorten is the loop that actually matters here: <strong>you still have to walk to a phone and hold a chip against it.</strong> A cloud build that goes green tells you nothing about whether the tag read.</p>
<p>For a solo project with a working local toolchain, local wins on iteration speed. For a team, a CI pipeline, or anyone who has just watched their disk hit 100% mid-build, the capability sync alone is a strong argument.</p>
<h2 id="heading-a-sneak-peek-at-the-android-side">A Sneak Peek at the Android Side</h2>
<p>Android deserves its own handbook, and it's getting one. This section is the preview for anyone who doesn't want to wait: the Kotlin counterpart to the Swift above, and the architectural differences that make NFC on the two platforms genuinely different jobs rather than the same job twice.</p>
<p>Read it as a design preview rather than a verified implementation. The Kotlin compiles against the documented API and mirrors Swift that <em>is</em> verified on hardware, so the shapes are right, and the full treatment with a device in hand is the handbook that follows this one.</p>
<p>The differences that matter are visible from the API surface rather than from a device, and they're the ones that decide how you structure the code.</p>
<h3 id="heading-android-has-no-session">Android Has No Session</h3>
<p>iOS hands you a session, and the session is the model: you begin it, the OS draws a sheet, it hands you a tag, and it invalidates itself. Android gives you <strong>reader mode</strong>: a callback bound to your foreground Activity that fires whenever a tag comes near.</p>
<pre><code class="language-kotlin">adapter.enableReaderMode(activity, ::onTagDiscovered, flags, Bundle())
</code></pre>
<p>Everything the iOS session did for you becomes yours:</p>
<table>
<thead>
<tr>
<th></th>
<th>iOS</th>
<th>Android</th>
</tr>
</thead>
<tbody><tr>
<td>Scanning UI</td>
<td>The OS draws a sheet</td>
<td><strong>The app draws everything</strong></td>
</tr>
<tr>
<td>Session end</td>
<td>Automatic after one tag</td>
<td><code>disableReaderMode</code> <strong>on every exit path</strong></td>
</tr>
<tr>
<td>Needs</td>
<td>Nothing on screen</td>
<td><strong>The foreground Activity</strong>, not a Context</td>
</tr>
<tr>
<td>Callback thread</td>
<td>Main</td>
<td><strong>A binder thread</strong></td>
</tr>
<tr>
<td>Cancelling</td>
<td>The system sheet provides it</td>
<td><strong>Build it yourself</strong></td>
</tr>
</tbody></table>
<p>That last row reaches all the way back into the JavaScript. The cross-platform <code>cancelScan()</code> is a real implementation on Android and a <strong>documented no-op on iOS</strong>, where the system sheet owns cancelling and the Swift module deliberately doesn't implement the function at all:</p>
<pre><code class="language-ts">export async function cancelScanNative(): Promise&lt;void&gt; {
  if (Platform.OS !== 'android') return;
  await NfcNative.cancelScan();
}
</code></pre>
<p>Also: pass <code>FLAG_READER_NO_PLATFORM_SOUNDS</code>, or the OS plays its own discovery sound over an app that is already telling the user what to do.</p>
<h3 id="heading-the-kotlin-and-one-design-note">The Kotlin, and One Design Note</h3>
<pre><code class="language-kotlin">private fun onTagDiscovered(tag: Tag) {
  val ndef = Ndef.get(tag) ?: run {
    stopReaderMode(); rejectOnce(NotNdefException()); return
  }

  try {
    ndef.connect()

    val status = NfcTagInfo.status(ndef)
    val capacity = ndef.maxSize

    messageToWrite?.let { message -&gt;
      // Ask before acting, same order as the Swift: refusing leaves the tag
      // untouched, failing partway through a write may not.
      if (!ndef.isWritable) { … }
      if (message.toByteArray().size &gt; capacity) { … }
      ndef.writeNdefMessage(message)
    }

    // Read back in the same connection. For a write this is verification,
    // for a read it is simply the result.
    val onTag = ndef.ndefMessage
    …
  } finally {
    runCatching { ndef.close() }
  }
}
</code></pre>
<p>Android has no equivalent of iOS's <code>NFCNDEFStatus</code>, so the status is <strong>derived</strong> rather than reported.</p>
<pre><code class="language-kotlin">fun status(ndef: Ndef?): Int =
  when {
    ndef == null -&gt; 1     // not NDEF: signalled by Ndef.get() returning null
    ndef.isWritable -&gt; 2  // read-write
    else -&gt; 3             // read-only
  }
</code></pre>
<p>iOS answers that question directly. Android signals "not NDEF" by <code>Ndef.get()</code> returning null and exposes <code>isWritable</code> on a connected tag. Mapping both onto one set of numbers keeps the TypeScript from ever needing to know which platform it's talking to, which is the entire job of a native module.</p>
<h3 id="heading-if-you-port-this-the-differences-that-will-matter">If You Port This, the Differences That Will Matter</h3>
<table>
<thead>
<tr>
<th></th>
<th>iOS</th>
<th>Android</th>
</tr>
</thead>
<tbody><tr>
<td>Permission model</td>
<td>App ID + capability + paid account</td>
<td>One manifest line, free</td>
</tr>
<tr>
<td>Failure when misconfigured</td>
<td>Code-signing error that never says "NFC"</td>
<td>Permission missing</td>
</tr>
<tr>
<td>Entitlement granularity</td>
<td><strong>Per polling option</strong></td>
<td>One permission covers all</td>
</tr>
<tr>
<td>Scanning UI</td>
<td>System sheet, not restylable</td>
<td><strong>None</strong>. You draw everything</td>
</tr>
<tr>
<td>Capacity from a read</td>
<td>❌ (ask the status query)</td>
<td>✅ <code>getMaxSize()</code></td>
</tr>
<tr>
<td>Writable from a read</td>
<td>❌ (ask the status query)</td>
<td>✅ <code>isWritable</code></td>
</tr>
<tr>
<td>Antenna</td>
<td>Top edge</td>
<td>Centre back</td>
</tr>
<tr>
<td>Card emulation</td>
<td><strong>Impossible</strong></td>
<td><code>HostApduService</code>, open</td>
</tr>
<tr>
<td>Permanent locking</td>
<td><code>writeLock</code>, irreversible</td>
<td><code>makeReadOnly()</code>, irreversible</td>
</tr>
</tbody></table>
<p>Two patterns come from that table.</p>
<p><strong>iOS front-loads the pain and Android back-loads it.</strong> Portals, entitlements and signing before you read a byte, versus reader mode, Activity lifecycle and building your own cancel once you're running.</p>
<p><strong>And the capacity difference is narrower than it looks.</strong> It isn't that iOS tells you less. It's that Android volunteers this on an ordinary read while iOS makes you ask a specific question inside a session. Same data, different price of admission. I got that wrong for three documents, as you've seen.</p>
<h2 id="heading-the-demo-repository">The Demo Repository</h2>
<p>Everything above is one project, <a href="https://github.com/FastheDeveloper/nfc"><strong>TapCard</strong></a>, and it's a single app rather than a snippet dump.</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Where</th>
<th>What is there</th>
</tr>
</thead>
<tbody><tr>
<td>App</td>
<td><code>app/(tabs)/</code></td>
<td>Read, Write, Focus and Profile screens, plus a Tag Info route</td>
</tr>
<tr>
<td>Pure logic</td>
<td><code>lib/</code></td>
<td>The NDEF decoder and encoder, vCard, capacity, error mapping, focus rules. ~2,240 lines, no React Native imports</td>
</tr>
<tr>
<td>Native module</td>
<td><code>modules/nfc-native/</code></td>
<td>~1,010 lines of Swift and ~475 of Kotlin: sessions, typed exceptions, tag conversions</td>
</tr>
<tr>
<td>State</td>
<td><code>store/</code></td>
<td>Zustand + AsyncStorage: profile, last tag, focus record</td>
</tr>
<tr>
<td>Evidence</td>
<td><code>vendor/</code></td>
<td>The removed dependency, frozen, with the tests that justify its removal</td>
</tr>
<tr>
<td>Notes</td>
<td><code>DEVLOG.md</code>, <code>GOTCHAS.md</code>, <code>PLATFORM-NOTES.md</code></td>
<td>Every command and error verbatim, 75 traps, the running comparison</td>
</tr>
</tbody></table>
<p><strong>293 tests, 15 suites, about a second, and no hardware.</strong> That's the payoff of keeping the decoding pure.</p>
<p>And the tagged checkpoints, so you can read the app at any stage rather than only at the end:</p>
<pre><code class="language-bash">git checkout step-0-scaffold        # boots, no NFC
git checkout step-1-first-read      # entitlements + raw dump
git checkout step-2-decode          # own decoder, Tag Info
git checkout step-3-write           # vCard, capacity checks
git checkout step-4-own-module      # native module alongside the library
git checkout step-5-no-dependency   # library removed
git checkout step-6-android         # Kotlin reader mode
</code></pre>
<p>Clone it, buy a pack of stickers, check out <code>step-1-first-read</code>, and hold a chip against your own phone. That loop is the fastest way to make everything above concrete.</p>
<h2 id="heading-what-to-know-before-you-start">What to Know Before You Start</h2>
<p><strong>Buy the tags first.</strong> There's no simulator. When my chips went missing in the post the project stopped dead for two weeks, and no amount of clever architecture substituted for a chip.</p>
<p><strong>Read your dependencies before trusting them.</strong> Twenty minutes with <code>ndef-lib</code> found three real defects and changed the architecture of the app. None of them were in an issue tracker I'd have thought to search.</p>
<p><strong>Assume the failure will be silent.</strong> Of the seventy-five traps I logged, roughly a dozen produce <strong>no error at all</strong>: the deallocated session, the removed config plugin, the unescaped semicolon, the truncated emoji, the empty error message, and the gitignored native module. In NFC work "nothing happened" is the most common symptom, so instrument accordingly and confirm on the real surface rather than trusting a return value.</p>
<p><strong>Put the platform difference in the type, not in a comment.</strong> Model "this platform doesn't tell us" as a first-class state:</p>
<pre><code class="language-ts">type Fact = {
  label: string;
  value: string | null; // null = the platform did not report it
  unavailable?: string; // why, in plain language
};
</code></pre>
<p>A UI that renders a bare dash for both an absent value and a zero teaches nothing.</p>
<p><strong>And don't let a conclusion inherit the credibility of the observation underneath it.</strong> That one cost the most, and it wasn't about NFC at all.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You now have the whole picture on iOS: the entitlement maze, a decoder written by hand because the popular one loses data, a write path that asks the tag before it acts, a focus timer enforced by geography, a native module in Swift, a dependency deleted with its evidence preserved, and a tag locked forever behind a gate that makes you type its name.</p>
<p>Three things are worth exploring next.</p>
<ol>
<li><p><strong>Background tag reading:</strong> Tap a tag with the app closed. iOS surfaces a notification the user must tap, and only for certain record types. It's the feature that makes NFC feel magic, and the rules around which records qualify are worth a piece of their own.</p>
</li>
<li><p><strong>Cryptographic tags:</strong> An NTAG424 DNA signs a counter on every tap. If you ever want a tag to be a credential rather than a label, that's where to start.</p>
</li>
<li><p><strong>And Android</strong>, which is the next handbook. The preview above is the map, and the full walkthrough on real hardware is what comes after this one.</p>
</li>
</ol>
<p>The interesting part was never <code>requestTechnology</code>. It was everything the two platforms decline to tell you when you get it wrong.</p>
<h2 id="heading-sources-and-further-reading">Sources and Further Reading</h2>
<p><strong>Apple, CoreNFC and entitlements:</strong></p>
<ul>
<li><p><a href="https://developer.apple.com/documentation/corenfc">Core NFC</a>, <a href="https://developer.apple.com/documentation/corenfc/nfctagreadersession"><code>NFCTagReaderSession</code></a>, and <a href="https://developer.apple.com/documentation/corenfc/nfcndeftag"><code>NFCNDEFTag</code></a></p>
</li>
<li><p><a href="https://developer.apple.com/documentation/corenfc/nfcndeftag/queryndefstatus(completionhandler:)"><code>queryNDEFStatus</code></a>: the call this project wrongly concluded did not exist</p>
</li>
<li><p><a href="https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.nfc.readersession.formats">Near Field Communication Tag Reader Session Formats entitlement</a></p>
</li>
<li><p><a href="https://developer.apple.com/documentation/ProximityReader/setting-up-the-entitlement-for-tap-to-pay-on-iPhone">Setting up the entitlement for Tap to Pay on iPhone</a></p>
</li>
<li><p><a href="https://developer.apple.com/documentation/xcode/configuring-family-controls">Configuring Family Controls</a></p>
</li>
<li><p><a href="https://developer.apple.com/forums/thread/808604">CoreNFC availability on iPad</a>: an Apple engineer confirming the framework is iPhone-only</p>
</li>
</ul>
<p><strong>Android:</strong></p>
<ul>
<li><p><a href="https://developer.android.com/develop/connectivity/nfc/nfc">NFC basics</a> and <a href="https://developer.android.com/develop/connectivity/nfc/advanced-nfc">Advanced NFC</a></p>
</li>
<li><p><a href="https://developer.android.com/reference/android/nfc/NfcAdapter#enableReaderMode(android.app.Activity,%20android.nfc.NfcAdapter.ReaderCallback,%20int,%20android.os.Bundle)"><code>NfcAdapter.enableReaderMode</code></a></p>
</li>
<li><p><a href="https://developer.android.com/reference/android/nfc/tech/Ndef"><code>Ndef</code></a>: <code>getMaxSize()</code>, <code>isWritable()</code></p>
</li>
<li><p><a href="https://developer.android.com/develop/connectivity/nfc/hce">Host-based card emulation</a></p>
</li>
</ul>
<p><strong>The format:</strong></p>
<ul>
<li><p>NFC Forum <a href="https://nfc-forum.org/build/specifications">NDEF and RTD specifications</a>: the URI prefix table and the Text record status byte</p>
</li>
<li><p><a href="https://datatracker.ietf.org/doc/html/rfc2426">RFC 2426</a>: vCard 3.0, including the <code>N</code> field and line folding</p>
</li>
</ul>
<p><strong>Expo and React Native:</strong></p>
<ul>
<li><p><a href="https://react.dev/reference/eslint-plugin-react-hooks"><code>eslint-plugin-react-hooks</code></a>, and the two rules that caught the focus timer: <a href="https://react.dev/reference/eslint-plugin-react-hooks/lints/purity"><code>purity</code></a> and <a href="https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect"><code>set-state-in-effect</code></a></p>
</li>
<li><p><a href="https://docs.expo.dev/modules/overview/">Expo Modules API</a> and <a href="https://docs.expo.dev/config-plugins/introduction/">Config plugins</a></p>
</li>
<li><p><a href="https://docs.expo.dev/workflow/continuous-native-generation/">Continuous Native Generation</a></p>
</li>
<li><p><a href="https://docs.expo.dev/build-reference/ios-capabilities/">iOS capabilities on EAS Build</a>: which entitlements EAS syncs, and <code>EXPO_NO_CAPABILITY_SYNC</code></p>
</li>
<li><p><code>expo-modules-core</code>, <code>ios/Core/Exceptions/CodedError.swift</code>: where <code>ERR_USER_CANCELLED</code> comes from</p>
</li>
</ul>
<p><strong>Shipped NFC you can go and check, cited in "Where You Have Already Seen This":</strong></p>
<ul>
<li><p><a href="https://support.apple.com/guide/shortcuts/setting-triggers-apde31e9638b/ios">Setting triggers in Shortcuts</a>, Apple. The NFC trigger needs iPhone XS or later and iOS 13.1</p>
</li>
<li><p><a href="https://support.apple.com/guide/iphone/mark-an-item-as-lost-iph1b451b75f/ios">Mark an AirTag or other item as lost in Find My</a>, Apple</p>
</li>
<li><p><a href="https://en-americas-support.nintendo.com/app/answers/detail/a_id/13260/">amiibo FAQ</a>, Nintendo, on read-only versus read/write figures</p>
</li>
<li><p><a href="https://www.gov.uk/guidance/using-the-uk-immigration-id-check-app">Using the "UK Immigration: ID Check" app</a>, GOV.UK</p>
</li>
<li><p><a href="https://www.apple.com/business/tap-to-pay-on-iphone/">Tap to Pay on iPhone</a> and its <a href="https://developer.apple.com/tap-to-pay/regions/">supported regions</a>, Apple</p>
</li>
</ul>
<p><strong>Prior art for the focus feature:</strong></p>
<ul>
<li><a href="https://github.com/awaseem/foqos">Foqos</a> (open source, <a href="https://apps.apple.com/us/app/foqos-tap-to-block/id6736793117">App Store</a>) and <a href="https://github.com/cajdata/TapBlok/">TapBlok</a></li>
</ul>
<p><strong>The library this project replaced:</strong></p>
<ul>
<li><a href="https://github.com/revtel/react-native-nfc-manager"><code>react-native-nfc-manager</code></a>: MIT. The defects described here were found in 3.17.2 by reading the source, and a frozen copy lives in the demo repo's <code>vendor/</code> with the tests that pin them.</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Apple’s Foundation Models in a Web App with a macOS Companion ]]>
                </title>
                <description>
                    <![CDATA[ Not every AI feature needs a cloud model, with its per-token bills, network round-trips, and private data leaving your machine. If you're on a modern Mac, a capable language model is already on your d ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-apple-s-foundation-models-in-a-web-app-with-a-macos-companion/</link>
                <guid isPermaLink="false">6a5e92afe12aa31dae6e8a79</guid>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Balogun Wahab ]]>
                </dc:creator>
                <pubDate>Mon, 20 Jul 2026 21:27:11 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/7f0e2343-7394-46b5-a4c8-3ef0fecfa57a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Not every AI feature needs a cloud model, with its per-token bills, network round-trips, and private data leaving your machine. If you're on a modern Mac, a capable language model is already on your disk.</p>
<p><strong>Foundation Models</strong> is Apple's Swift framework for working with large language models. It's the on-device model behind Apple Intelligence, Apple's Private Cloud Compute, or another provider's server model.</p>
<p>This tutorial targets the on-device model: you send it a prompt and it runs entirely on the Mac's own hardware locally, free-per-call, and offline-friendly.</p>
<p>Paired with Apple Vision for reading images on device, that's enough to build real AI features like summaries, classification, and structured extraction without the data ever leaving your machine.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ul>
<li><p><a href="#heading-what-you-will-build">What You Will Build</a></p>
</li>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-why-a-macos-companion-app">Why a macOS Companion App?</a></p>
</li>
<li><p><a href="#heading-foundation-models-cant-read-images-directly">Foundation Models Can't Read Images Directly</a></p>
</li>
<li><p><a href="#heading-project-structure">Project Structure</a></p>
</li>
<li><p><a href="#heading-build-the-react-app">Build the React App</a></p>
<ul>
<li><p><a href="#heading-check-companion-health">Check Companion Health</a></p>
</li>
<li><p><a href="#heading-convert-the-image-to-base64">Convert the Image to Base64</a></p>
</li>
<li><p><a href="#heading-analyze-immediately-after-upload">Analyze Immediately After Upload</a></p>
</li>
<li><p><a href="#heading-send-the-image-to-the-companion">Send the Image to the Companion</a></p>
</li>
<li><p><a href="#heading-render-the-json-output">Render the JSON Output</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-build-the-macos-companion-app">Build the macOS Companion App</a></p>
</li>
<li><p><a href="#heading-check-foundation-models-availability">Check Foundation Models Availability</a></p>
</li>
<li><p><a href="#heading-extract-text-with-apple-vision">Extract Text with Apple Vision</a></p>
</li>
<li><p><a href="#heading-ask-foundation-models-to-explain-the-vision-output">Ask Foundation Models to Explain the Vision Output</a></p>
</li>
<li><p><a href="#heading-return-json-to-the-browser">Return JSON to the Browser</a></p>
</li>
<li><p><a href="#heading-run-the-app">Run the App</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a href="#heading-resources">Resources</a></p>
</li>
</ul>
<h2 id="heading-what-you-will-build">What You Will Build</h2>
<p>You'll build <strong>Vision Bridge</strong>, a web app that sends an image to a local macOS companion. The companion reads the image with Apple Vision, reasons about it with Foundation Models, and returns structured JSON to the browser: private, on-device AI behind a plain web interface.</p>
<p>You can find the complete source code in this GitHub repository: <a href="http://github.com/03balogun/vision-bridge">github.com/03balogun/vision-bridge</a>.</p>
<p>The goal isn't to build a giant product but rather to understand the architecture behind how this works.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5db93b3da2342e8354088115/6d18db01-e921-4291-bb2e-26be2c02b304.png" alt="Screenshot of the Vision Bridge app, with image upload on the left and JSON output on the right" style="display: block;" width="3024" height="1714" loading="lazy">

<p>Vision Bridge has two parts:</p>
<ul>
<li><p>A React app with a split-screen interface.</p>
</li>
<li><p>A macOS companion app that exposes a local API.</p>
</li>
</ul>
<p>The React app has:</p>
<ul>
<li><p>An image upload area</p>
</li>
<li><p>An image preview</p>
</li>
<li><p>Automatic analysis after upload</p>
</li>
<li><p>A JSON output viewer</p>
</li>
<li><p>A companion health status indicator</p>
</li>
</ul>
<p>The macOS companion app has:</p>
<ul>
<li><p><code>GET /v1/health</code></p>
</li>
<li><p><code>POST /v1/analyze-image</code></p>
</li>
<li><p>Apple Vision OCR</p>
</li>
<li><p>Foundation Models availability checks</p>
</li>
<li><p>Foundation Models reasoning over Vision output</p>
</li>
</ul>
<p>The final response looks like this:</p>
<pre><code class="language-json">{
  "support": {
    "visionAvailable": true,
    "foundationModelAvailable": true,
    "foundationModelStatus": "available"
  },
  "image": {
    "filename": "screenshot.png",
    "contentType": "image/png",
    "byteCount": 1048576,
    "width": 1440,
    "height": 900
  },
  "vision": {
    "detectedText": [
      {
        "text": "Build failed",
        "confidence": 0.96,
        "boundingBox": {
          "x": 0.12,
          "y": 0.31,
          "width": 0.45,
          "height": 0.08
        }
      }
    ]
  },
  "model": {
    "summary": "The image appears to show a software build failure.",
    "description": "A developer tool window is showing an error state with diagnostic text.",
    "suggestedTags": ["screenshot", "developer-tool", "error"],
    "possibleUses": [
      "Generate alt text",
      "Summarize screenshots",
      "Extract document data"
    ]
  }
}
</code></pre>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along, you need:</p>
<ul>
<li><p>macOS 26 or newer</p>
</li>
<li><p>Xcode with the macOS 26 SDK</p>
</li>
<li><p>Node.js 20 or newer</p>
</li>
<li><p>Basic React knowledge</p>
</li>
<li><p>Basic Swift knowledge</p>
</li>
<li><p>A Mac that supports Apple Intelligence</p>
</li>
</ul>
<p>Foundation Models availability depends on the Mac, the OS version, and Apple Intelligence settings. The companion checks this at runtime, which we'll cover below.</p>
<h2 id="heading-why-a-macos-companion-app">Why a macOS Companion App?</h2>
<p>You can't write this in a regular React app:</p>
<pre><code class="language-ts">import FoundationModels from "apple-frameworks";
</code></pre>
<p>That API doesn't exist in the browser. A native macOS app, however, can use any Apple framework, so the companion acts as a local bridge. The same pattern works for any native capability the web platform doesn't expose.</p>
<h2 id="heading-foundation-models-cant-read-images-directly">Foundation Models Can't Read Images Directly</h2>
<p>The public Foundation Models framework is a language model interface. It doesn't currently expose direct image input the way a multimodal cloud model might, so this tutorial never sends the image to the model. Instead, the companion feeds the Vision OCR observations and image metadata into the prompt. The model reasons over structured text, never the original pixels.</p>
<p>That split plays to each framework's strength: Vision is excellent at pulling machine-readable information out of images, and Foundation Models turns that information into summaries, labels, explanations, and structured output.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5db93b3da2342e8354088115/a5c11ad4-dcac-4690-bc6d-08b27fd6fed8.png" alt="Vision Bridge architecture: the browser sends the image over localhost to the Swift companion, which runs Apple Vision OCR, feeds the observations to Foundation Models, and returns structured JSON" style="display: block;" width="2492" height="1572" loading="lazy">

<p>The above diagram shows the round trip that the rest of this tutorial builds. The browser sends the uploaded image as base64 JSON over localhost to the Swift companion. Inside the companion, Apple Vision runs OCR on the image and produces text observations: the recognized strings, their confidence scores, and their bounding boxes.</p>
<p>Those observations, not the image itself, are formatted into a prompt for Foundation Models, which generates a summary, description, and tags. The companion then bundles the Vision output and the model output into one JSON response and returns it to the browser.</p>
<h2 id="heading-project-structure">Project Structure</h2>
<p>Create a project with this structure:</p>
<pre><code class="language-text">vision-bridge/
  apps/
    web/
      src/
        main.tsx
        styles.css
      package.json
      vite.config.ts
    macos-companion/
      Package.swift
      Sources/
        VisionBridgeCompanion/
          main.swift
  package.json
  README.md
</code></pre>
<p>The root <code>package.json</code> gives us a few convenient commands:</p>
<pre><code class="language-json">{
  "scripts": {
    "dev": "npm --workspace apps/web run dev",
    "build": "npm --workspace apps/web run build",
    "companion": "swift run --package-path apps/macos-companion VisionBridgeCompanion"
  },
  "workspaces": ["apps/web"]
}
</code></pre>
<h2 id="heading-build-the-react-app">Build the React App</h2>
<p>The web app is intentionally simple. It has one job: let the user pick an image and show the JSON returned by the companion.</p>
<p>The web app uses Vite, React, Lucide icons, and a JSON viewer:</p>
<pre><code class="language-json">{
  "dependencies": {
    "@vitejs/plugin-react": "^6.0.3",
    "lucide-react": "^0.468.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-json-view-lite": "^2.5.0",
    "vite": "^8.1.3"
  }
}
</code></pre>
<p>After defining the dependencies, install them:</p>
<pre><code class="language-plaintext">npm install
</code></pre>
<p>The API base URL points to the local companion:</p>
<pre><code class="language-ts">const API_BASE_URL = "http://127.0.0.1:43119";
</code></pre>
<h3 id="heading-check-companion-health">Check Companion Health</h3>
<p>The web app pings the companion so the UI can show whether the native bridge is online:</p>
<pre><code class="language-ts">async function checkHealth() {
  setHealthError(null);

  try {
    const response = await fetch(`${API_BASE_URL}/v1/health`);
    if (!response.ok) {
      throw new Error(`Health check failed with ${response.status}`);
    }

    const payload = await response.json();
    setHealth(payload);
  } catch (error) {
    setHealth(null);
    setHealthError(error instanceof Error ? error.message : "Companion unavailable");
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5db93b3da2342e8354088115/dc3c37eb-1d9c-4b44-82db-f38adada4f19.png" alt="Screenshot of the companion online status pill" style="display: block;" width="732" height="212" loading="lazy">

<h3 id="heading-convert-the-image-to-base64">Convert the Image to Base64</h3>
<p>When the user selects a file, the app converts it to base64 so it can be sent as JSON:</p>
<pre><code class="language-ts">function readFileAsBase64(file: File) {
  return new Promise&lt;string&gt;((resolve, reject) =&gt; {
    const reader = new FileReader();
    reader.onload = () =&gt; {
      const result = String(reader.result);
      resolve(result.includes(",") ? result.split(",")[1] : result);
    };
    reader.onerror = () =&gt; reject(reader.error);
    reader.readAsDataURL(file);
  });
}
</code></pre>
<p>This isn't the only way to upload files. You could also use <code>multipart/form-data</code>, but JSON keeps the demo easy to inspect.</p>
<h3 id="heading-analyze-immediately-after-upload">Analyze Immediately After Upload</h3>
<p>The app starts analysis as soon as an image is uploaded:</p>
<pre><code class="language-ts">async function handleFile(file: File) {
  if (!file.type.startsWith("image/")) {
    setError("Choose a PNG, JPEG, HEIC, or another browser-readable image.");
    return;
  }

  const base64 = await readFileAsBase64(file);
  const nextImage = {
    file,
    previewUrl: URL.createObjectURL(file),
    base64,
  };

  setSelectedImage(nextImage);
  setAnalysis(null);
  setError(null);
  setCopied(false);

  analyzeImage(nextImage);
}
</code></pre>
<p><code>handleFile</code> does the preparation work for every new image. It rejects anything that isn't a browser-readable image, converts the file to base64, and builds a single object holding everything the rest of the flow needs: the original <code>File</code> (for its name and MIME type), an object URL for the preview, and the base64 payload for the API call.</p>
<p>It then clears out the previous run the old analysis, any error message, and the "copied" indicator so the UI never shows results from the last image next to a new one. Finally, it kicks off <code>analyzeImage(nextImage)</code> immediately.</p>
<p>Note that it passes the fresh object directly instead of relying on the <code>selectedImage</code> state: React state updates don't apply until the next render, so reading the state here would still give you the <em>previous</em> image.</p>
<p>The <code>Analyze</code> button still exists in the UI, but it works as a manual rerun button.</p>
<h3 id="heading-send-the-image-to-the-companion">Send the Image to the Companion</h3>
<p>Here's the core request:</p>
<pre><code class="language-ts">const analysisRequestId = useRef(0);

async function analyzeImage(image = selectedImage) {
  if (!image) {
    setError("Choose an image first.");
    return;
  }

  const requestId = analysisRequestId.current + 1;
  analysisRequestId.current = requestId;

  setRequestState("loading");
  setError(null);
  setCopied(false);

  try {
    const response = await fetch(`${API_BASE_URL}/v1/analyze-image`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        filename: image.file.name,
        mimeType: image.file.type || "application/octet-stream",
        base64: image.base64,
      }),
    });

    const payload = await response.json();

    if (requestId !== analysisRequestId.current) {
      return;
    }

    if (!response.ok) {
      throw new Error(payload.error?.message ?? `Analysis failed with ${response.status}`);
    }

    setAnalysis(payload);
    setRequestState("success");
  } catch (error) {
    if (requestId !== analysisRequestId.current) {
      return;
    }

    setRequestState("error");
    setError(error instanceof Error ? error.message : "Could not analyze image");
  }
}
</code></pre>
<p>This function is the entire client side of the bridge. It flips <code>requestState</code> to <code>loading</code> (which drives the spinner and disables the button), then sends a <code>POST</code> to <code>/v1/analyze-image</code> with a JSON body containing three fields: the filename, the MIME type, and the base64 image data. That body maps one-to-one onto the <code>AnalyzeImageRequest</code> struct the Swift companion decodes later.</p>
<p>Notice that the response is parsed as JSON <em>before</em> checking <code>response.ok</code>. That's deliberate: when the companion rejects a request (bad base64, oversized image), it still returns a JSON body with an <code>error.message</code> field, so the UI can show the companion's own explanation instead of a generic status code. On success, the payload goes straight into state, and the JSON viewer re-renders with the result.</p>
<p>The <code>requestId</code> bookkeeping guards against stale responses. If a user uploads a second image while the first is still analyzing, whichever request finishes <em>last</em> would win, and OCR plus model generation takes long enough that responses can genuinely arrive out of order. So every call increments a counter stored in a ref and remembers its own ID.</p>
<p>After the <code>await</code>, it checks whether it's still the newest request; if a newer upload started in the meantime, the older response is silently discarded instead of overwriting the latest image's result. The same check runs in the <code>catch</code> block, so an old failure can't clobber a newer success either. If you also want to cancel the in-flight HTTP request rather than just ignore its result, an <code>AbortController</code> is the natural next step.</p>
<h3 id="heading-render-the-json-output">Render the JSON Output</h3>
<p>The output pane uses <code>react-json-view-lite</code>:</p>
<pre><code class="language-tsx">&lt;JsonView
  data={jsonData}
  shouldExpandNode={allExpanded}
  style={jsonViewTheme}
/&gt;
</code></pre>
<h2 id="heading-build-the-macos-companion-app">Build the macOS Companion App</h2>
<p>The companion is a Swift command-line app. It exposes a small local HTTP API.</p>
<p>If you come from the web side, the mapping is simple: Swift Package Manager is Swift's npm, <code>Package.swift</code> is its <code>package.json</code>, and <code>swift run</code> is its <code>npm start</code>. It ships with Xcode, so there's nothing extra to install.</p>
<p>The <code>Package.swift</code> file looks like this:</p>
<pre><code class="language-swift">// swift-tools-version: 6.0

import PackageDescription

let package = Package(
    name: "VisionBridgeCompanion",
    platforms: [
        .macOS("26.0")
    ],
    products: [
        .executable(
            name: "VisionBridgeCompanion",
            targets: ["VisionBridgeCompanion"]
        )
    ],
    targets: [
        .executableTarget(
            name: "VisionBridgeCompanion"
        )
    ]
)
</code></pre>
<p>The companion imports the Apple frameworks it needs:</p>
<pre><code class="language-swift">import Foundation
import FoundationModels
import ImageIO
import Network
import Vision
</code></pre>
<p>It listens on <code>127.0.0.1:43119</code>:</p>
<pre><code class="language-swift">private let defaultPort: UInt16 = 43119
</code></pre>
<p>The app exposes two routes:</p>
<pre><code class="language-swift">switch (request.method, request.path) {
case ("GET", "/v1/health"):
    let health = HealthResponse(support: ModelSupport.current)
    return try json(health)

case ("POST", "/v1/analyze-image"):
    let payload = try JSONDecoder().decode(AnalyzeImageRequest.self, from: request.body)
    let response = try await service.analyze(payload)
    return try json(response)

default:
    return try json(
        ErrorResponse(error: APIErrorPayload(message: "Route not found")),
        status: .notFound
    )
}
</code></pre>
<p>This <code>switch</code> is the companion's entire routing layer — no web framework, just pattern matching on the method and path.</p>
<p>The two routes split the work cleanly:</p>
<ul>
<li><p><code>GET /v1/health</code> is the cheap, read-only route. It runs no analysis, it just reports whether Vision and Foundation Models are usable on this Mac via <code>ModelSupport.current</code> (covered in the next section). The React app calls it on load to render the online/offline status pill, so the user knows the bridge is up before they upload anything.</p>
</li>
<li><p><code>POST /v1/analyze-image</code> is where the real work happens. It decodes the request body into an <code>AnalyzeImageRequest</code> (with the same <code>filename</code>, <code>mimeType</code>, and <code>base64</code> fields the browser sent) and hands it to the analysis service. This validates the image, runs Vision OCR, prompts Foundation Models, and returns the combined result. The <code>try await</code> matters here: analysis is asynchronous, and the route simply waits for it before serializing the response.</p>
</li>
</ul>
<p>Anything else falls through to a JSON 404, so even unknown routes respond in the same format the browser already knows how to parse.</p>
<p>Errors work the same way: thrown errors are caught in one place and converted into JSON error responses with an appropriate status code, which is exactly what the web app's <code>payload.error?.message</code> check reads.</p>
<p>One practical detail: because the browser calls the companion from a different origin (the Vite dev server), every response also carries CORS headers, and the router answers preflight <code>OPTIONS</code> requests with an empty <code>204</code>. Without that, the browser would block the <code>fetch</code> before it ever reached these routes.</p>
<h2 id="heading-check-foundation-models-availability">Check Foundation Models Availability</h2>
<p>The companion shouldn't assume that the model is available. Check it first:</p>
<pre><code class="language-swift">private struct ModelSupport: Encodable {
    let visionAvailable: Bool
    let foundationModelAvailable: Bool
    let foundationModelStatus: String

    static var current: ModelSupport {
        let model = SystemLanguageModel.default

        switch model.availability {
        case .available:
            return ModelSupport(
                visionAvailable: true,
                foundationModelAvailable: true,
                foundationModelStatus: "available"
            )

        case .unavailable(let reason):
            return ModelSupport(
                visionAvailable: true,
                foundationModelAvailable: false,
                foundationModelStatus: "unavailable.\(reason.description)"
            )

        @unknown default:
            return ModelSupport(
                visionAvailable: true,
                foundationModelAvailable: false,
                foundationModelStatus: "unavailable.unknown"
            )
        }
    }
}
</code></pre>
<p>A user might have an unsupported Mac, Apple Intelligence might be disabled, or the model might not be ready yet. The response tells the browser which case it's dealing with.</p>
<h2 id="heading-extract-text-with-apple-vision">Extract Text with Apple Vision</h2>
<p>The companion decodes the base64 image, checks its metadata, then runs Vision OCR.</p>
<p>Here's the text recognition flow:</p>
<pre><code class="language-swift">private func recognizeText(in imageData: Data) async throws -&gt; [DetectedText] {
    var request = RecognizeTextRequest()
    request.recognitionLevel = .accurate
    request.automaticallyDetectsLanguage = true
    request.usesLanguageCorrection = true

    let observations = try await request.perform(on: imageData)

    var detectedText: [DetectedText] = []

    for observation in observations {
        guard let candidate = observation.topCandidates(1).first else {
            continue
        }

        let bounds = NormalizedBox.from(points: [
            observation.topLeft,
            observation.topRight,
            observation.bottomRight,
            observation.bottomLeft
        ])

        detectedText.append(DetectedText(
            text: candidate.string,
            confidence: Double(candidate.confidence),
            boundingBox: bounds
        ))
    }

    return detectedText
}
</code></pre>
<p>Vision gives us structured observations:</p>
<ul>
<li><p>recognized text</p>
</li>
<li><p>confidence scores</p>
</li>
<li><p>normalized bounding boxes</p>
</li>
</ul>
<p>Those observations become the model’s context.</p>
<h2 id="heading-ask-foundation-models-to-explain-the-vision-output">Ask Foundation Models to Explain the Vision Output</h2>
<p>Now the companion creates a prompt from the image metadata and OCR results.</p>
<p>Notice the instruction:</p>
<pre><code class="language-text">You cannot see the original image. Use only the metadata and OCR observations below.
</code></pre>
<p>That keeps the model honest. It shouldn't pretend to see pixels it never received.</p>
<p>Here's the prompt shape:</p>
<pre><code class="language-swift">let textPreview = detectedText
    .prefix(30)
    .map { "- \($0.text) (confidence: \(String(format: "%.2f", $0.confidence)))" }
    .joined(separator: "\n")

let prompt = """
You are summarizing Apple Vision OCR output for a developer tool named Vision Bridge.
You cannot see the original image. Use only the metadata and OCR observations below.

Image:
- filename: \(image.filename)
- content type: \(image.contentType)
- size: \(image.width ?? 0)x\(image.height ?? 0)

OCR observations:
\(textPreview.isEmpty ? "- No text detected." : textPreview)

Return a compact JSON object with these exact keys:
summary: one sentence
description: one short paragraph
suggestedTags: 3 to 6 short tags
possibleUses: 3 to 5 practical use cases for this kind of image analysis
"""
</code></pre>
<p>Then call the model:</p>
<pre><code class="language-swift">let session = LanguageModelSession(
    model: .default,
    instructions: "Return valid JSON only. Do not include Markdown fences."
)

let response = try await session.respond(to: prompt)
let raw = response.content.trimmingCharacters(in: .whitespacesAndNewlines)
</code></pre>
<p>Even when you ask for JSON, always validate the output. Models can still return Markdown fences or malformed text. The sample app strips simple Markdown code fences and falls back to a raw response if parsing fails.</p>
<h2 id="heading-return-json-to-the-browser">Return JSON to the Browser</h2>
<p>The companion combines the support state, image metadata, Vision results, and model output:</p>
<pre><code class="language-swift">return AnalyzeImageResponse(
    support: support,
    image: metadata,
    vision: VisionPayload(detectedText: detectedText),
    model: modelInsight
)
</code></pre>
<p>The browser doesn't need to know how Vision or Foundation Models work. It just receives JSON. The native app owns the native capabilities, while the web app owns the interface.</p>
<p>It's worth pausing on what each of the four blocks actually gives you, because they're not all the same kind of data:</p>
<ul>
<li><p><code>support</code> tells you what was possible on this Mac. If <code>foundationModelAvailable</code> is <code>false</code>, the <code>model</code> block still exists but contains a fallback message rather than real analysis, and the <code>foundationModelStatus</code> string (for example, <code>unavailable.appleIntelligenceNotEnabled</code>) tells the UI <em>why</em>, so it can explain rather than silently degrade.</p>
</li>
<li><p><code>image</code> echoes back the file's metadata plus the measured pixel dimensions. It's useful as a sanity check, and you need the width and height to do anything spatial with the Vision results.</p>
</li>
<li><p><code>vision</code> is the ground truth. Each entry in <code>detectedText</code> is a string Vision actually found, with a confidence score between 0 and 1 and a normalized bounding box: coordinates expressed as fractions of the image size, so <code>x: 0.12, width: 0.45</code> means "starts 12% from the left and spans 45% of the width." Because the boxes are normalized, you can draw highlight overlays on the preview at any display size by multiplying by the rendered dimensions. Low-confidence entries are worth filtering or flagging before you trust them.</p>
</li>
<li><p><code>model</code> is interpretation, not observation. The <code>summary</code>, <code>description</code>, <code>suggestedTags</code>, and <code>possibleUses</code> fields are generated by the language model from the OCR text. This is useful as alt text, captions, or tag suggestions, but they inherit whatever the OCR missed and should be treated as a draft, not a fact. When the model's output can't be parsed as JSON, <code>rawResponse</code> carries the unparsed text so nothing is lost.</p>
</li>
</ul>
<p>For a screenshot of a failed build, the model block might come back like this:</p>
<pre><code class="language-json">{
  "model": {
    "summary": "The image appears to show a software build failure.",
    "description": "A developer tool window is showing an error state with diagnostic text.",
    "suggestedTags": ["screenshot", "developer-tool", "error"],
    "possibleUses": [
      "Generate alt text",
      "Summarize screenshots",
      "Extract document data"
    ]
  }
}
</code></pre>
<p>That combination (exact text with positions from Vision, plus a human-readable interpretation from the model) is enough to build real features on top of a searchable screenshot library indexed by <code>detectedText</code> and <code>suggestedTags</code>, automatic alt text for uploaded images, or click-to-highlight overlays powered by the bounding boxes.</p>
<p>And because the prompt lives in the companion, changing what comes back (say, extracting line items from receipts instead of tagging screenshots) is a prompt edit, not an architecture change.</p>
<h2 id="heading-run-the-app">Run the App</h2>
<p>Start the companion:</p>
<pre><code class="language-sh">npm run companion
</code></pre>
<p>In another terminal, start the web app:</p>
<pre><code class="language-sh">npm run dev
</code></pre>
<p>Open the Vite URL:</p>
<pre><code class="language-text">http://127.0.0.1:5173
</code></pre>
<p>If that port is busy, Vite will choose another one.</p>
<p>The companion should be available at:</p>
<pre><code class="language-text">http://127.0.0.1:43119
</code></pre>
<p>You can test it directly:</p>
<pre><code class="language-sh">curl http://127.0.0.1:43119/v1/health
</code></pre>
<p>Expected response:</p>
<pre><code class="language-json">{
  "app": "Vision Bridge Companion",
  "ok": true,
  "support": {
    "foundationModelAvailable": true,
    "foundationModelStatus": "available",
    "visionAvailable": true
  },
  "version": "0.1.0"
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/5db93b3da2342e8354088115/76a47c9a-934c-4133-ba7c-e2a9c6b6dad4.png" alt="Screenshot of terminal running companion" style="display: block;" width="1448" height="556" loading="lazy">

<h2 id="heading-conclusion">Conclusion</h2>
<p>You now have a React interface that uploads an image, a Swift companion that analyzes it with Apple-native frameworks, and structured JSON flowing between them.</p>
<p>Vision Bridge is intentionally small, but the bridge itself is reusable. Once you have a trusted native companion, a web app can do more than send prompts to a remote model: it can ask the Mac to work with local context, use any Apple framework, and return structured data the browser can render, store, or sync.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a href="https://developer.apple.com/documentation/foundationmodels">Apple Foundation Models documentation</a></p>
</li>
<li><p><a href="https://developer.apple.com/documentation/vision">Apple Vision documentation</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Secure iOS Apps in Swift: Common Security Pitfalls and How to Fix Them ]]>
                </title>
                <description>
                    <![CDATA[ These days, there are many ways attackers can try to compromise your applications. And thanks to the continued increase in cyberattacks, the demand for secure mobile applications – and by extension, secure coding – has never been higher. So if you’re... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-secure-ios-apps-in-swift-common-security-pitfalls-and-how-to-fix-them/</link>
                <guid isPermaLink="false">68ffdf1761d216440f5bb38a</guid>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ios app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Tray ]]>
                </dc:creator>
                <pubDate>Mon, 27 Oct 2025 21:07:35 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761599240278/644f6ebb-6092-4ea0-99e3-a568bfb0390c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>These days, there are many ways attackers can try to compromise your applications. And thanks to the continued increase in cyberattacks, the demand for secure mobile applications – and by extension, secure coding – has never been higher.</p>
<p>So if you’re an iOS developer, you should also learn to prioritize security at every stage of app development.</p>
<p>Swift, Apple’s modern programming language, offers a wealth of tools and frameworks that simplify development while enhancing security, but only when used correctly.</p>
<p>This article explores 10 common security pitfalls in Swift-based iOS apps and offers practical strategies to mitigate them.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>Before diving in, you’ll need:</p>
<ul>
<li><p>Working knowledge of Swift and iOS development.</p>
</li>
<li><p>Access to Xcode.</p>
</li>
<li><p>Basic understanding of how iOS apps communicate with servers.</p>
</li>
<li><p>Familiarity with Terminal/command line basics.</p>
</li>
</ul>
<p>The code examples are practical and explained step-by-step, making them accessible to junior developers while still offering value to experienced ones looking to strengthen their app's security.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<dl>
<ul>
<li><a href="" id="heading-what-are-the-most-prevalent-security-traps-in-swift-ios-applications">What are the Most Prevalent Security Traps in Swift iOS Applications?</a>
<ul>
<li><a href="" id="heading-1-insecure-data-storage">1. Insecure Data Storage</a></li>
<li><a href="" id="heading-2-weak-network-communication">2. Weak Network Communication</a></li>
<li><a href="" id="heading-3-improper-input-validation">3. Improper Input Validation</a></li>
<li><a href="" id="heading-4-hardcoding-secrets">4. Hardcoding Secrets</a></li>
<li><a href="" id="heading-5-insufficient-authentication-and-authorization">5. Insufficient Authentication and Authorization</a></li>
<li><a href="" id="heading-6-insecure-logging-and-error-handling">6. Insecure Logging and Error Handling</a></li>
<li><a href="" id="heading-7-ignoring-code-obfuscation-and-reverse-engineering">7. Ignoring Code Obfuscation and Reverse Engineering</a></li>
<li><a href="" id="heading-8-insecure-third-party-libraries">8. Insecure Third-Party Libraries</a></li>
<li><a href="" id="heading-9-insufficient-biometric-and-multi-factor-authentication">9. Insufficient Biometric and Multi-Factor Authentication</a></li>
<li><a href="" id="heading-10-disregarding-periodic-security-testing">10. Disregarding Periodic Security Testing</a></li>
</ul>
</li>
</ul>
</dl>

<h2 id="heading-what-are-the-most-prevalent-security-traps-in-swift-ios-applications"><strong>What are the Most Prevalent Security Traps in Swift iOS Applications?</strong></h2>
<p>Swift and iOS offer robust security features, but mistakes still happen. Following are the most common traps and how to fix them:</p>
<h3 id="heading-1-insecure-data-storage">1. Insecure Data Storage</h3>
<p>Among the most common mistakes developers make is having sensitive data stored insecurely. Passwords, tokens, or even individual user data can be left by accident in UserDefaults or local storage in unencrypted form. </p>
<p>While UserDefaults is convenient for small amounts of data, it is not secure for sensitive data as it is so easily accessible to attackers if the device is compromised.</p>
<h4 id="heading-how-to-fix">How to Fix:</h4>
<p>Use the Keychain Services API to securely store sensitive data. Keychain encrypts data and binds it to the device so that it can't be accessed by other unauthorized applications or users.</p>
<p>You can securely store credentials using libraries in Swift such as KeychainAccess or the built-in SecItemAdd and SecItemCopyMatching functions.</p>
<p>For example, this how you can store a user password in Keychain so as to ensure sensitive data is stored securely:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">do</span> {

<span class="hljs-keyword">try</span> keychain.<span class="hljs-keyword">set</span>(<span class="hljs-string">"userPassword123"</span>, key: <span class="hljs-string">"userPassword"</span>)

} <span class="hljs-keyword">catch</span> {

    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error saving to Keychain: \(error)"</span>)

}
</code></pre>
<p>Behind the scenes, here’s what happens when you call <code>keychain.set("userPassword123", key: "userPassword")</code> inside a KeychainManager class that uses Apple’s native Security framework for storage:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Security

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">KeychainManager</span> </span>{
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">set</span><span class="hljs-params">(<span class="hljs-number">_</span> value: String, key: String)</span></span> <span class="hljs-keyword">throws</span> {
     <span class="hljs-comment">// 1. Convert string to Data</span>
     <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> data = value.data(using: .utf8) <span class="hljs-keyword">else</span> {
         <span class="hljs-keyword">throw</span> <span class="hljs-type">NSError</span>(domain: <span class="hljs-string">"KeychainManager"</span>, code: -<span class="hljs-number">1</span>)
     }

     <span class="hljs-comment">// 2. Build the query dictionary</span>
     <span class="hljs-keyword">let</span> query: [<span class="hljs-type">String</span>: <span class="hljs-type">Any</span>] = [
         <span class="hljs-comment">// Store as password</span>
         kSecClass <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecClassGenericPassword,
         <span class="hljs-comment">// Your app's bundle identifier</span>
         kSecAttrService <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: <span class="hljs-string">"com.yourapp.keychain"</span>,
         <span class="hljs-comment">// "userPassword"</span>
         kSecAttrAccount <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: key,
         <span class="hljs-comment">// "userPassword123" encrypted</span>
         kSecValueData <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: data,
         kSecAttrAccessible <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecAttrAccessibleAfterFirstUnlock
     ]
     <span class="hljs-comment">// 3. Save to keychain (iOS encrypts it automatically)</span>
     <span class="hljs-keyword">let</span> status = <span class="hljs-type">SecItemAdd</span>(query <span class="hljs-keyword">as</span> <span class="hljs-type">CFDictionary</span>, <span class="hljs-literal">nil</span>)
     <span class="hljs-comment">// 4. Check if successful</span>
     <span class="hljs-keyword">guard</span> status == errSecSuccess <span class="hljs-keyword">else</span> {
         <span class="hljs-keyword">throw</span> <span class="hljs-type">NSError</span>(domain: <span class="hljs-string">"KeychainManager"</span>, code: <span class="hljs-type">Int</span>(status))
     }
 }
}
</code></pre>
<p>When this function runs, iOS converts the string value, such as "userPassword123", into encrypted binary data and stores it securely in the device’s Keychain database. The entry is saved under the provided key (for example, "userPassword"), and only your app can access it.</p>
<p>Behind the scenes, the Keychain leverages strong security features, including hardware-backed encryption using device-specific keys, optional biometric protection through Face ID or Touch ID, and app-level isolation to ensure that no other app can read or modify your stored credentials.</p>
<h3 id="heading-2-weak-network-communication">2. Weak Network Communication</h3>
<p>Transmitting sensitive data over the network is another area prone to vulnerabilities. Using unencrypted HTTP connections exposes your app to man-in-the-middle (MITM) attacks, allowing attackers to intercept and modify data in transit.  </p>
<p><strong>The Problem</strong>: When data travels between your app and server over an insecure connection, attackers on the same network (like public Wi-Fi) can:</p>
<ul>
<li><p>Read sensitive information (passwords, personal data, payment details)</p>
</li>
<li><p>Modify requests and responses</p>
</li>
<li><p>Impersonate your legitimate server</p>
</li>
</ul>
<h4 id="heading-how-to-fix-1">How to Fix:</h4>
<p><strong>1. Always Use HTTPS</strong><br>HTTPS encrypts all data in transit, making it unreadable to attackers. iOS's App Transport Security (ATS) enforces this by blocking insecure HTTP connections by default:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ❌ INSECURE - HTTP connection (blocked by ATS by default)</span>
<span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"http://api.example.com/login"</span>)

<span class="hljs-comment">// ✅ SECURE - HTTPS connection</span>
<span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"https://api.example.com/login"</span>)
</code></pre>
<p>You’ll want to avoid adding ATS exceptions to your Info.plist unless absolutely necessary. If a third-party API only supports HTTP, contact them to upgrade or find a more secure alternative.</p>
<p><strong>2. Implement Certificate Pinning (Advanced Protection)</strong></p>
<p>Even with HTTPS, your app could still be vulnerable to sophisticated MITM attacks. An attacker could install a fraudulent certificate on a user's device (through malware or social engineering), for example, and intercept HTTPS traffic that appears valid. The attacker's fake certificate would be trusted by the device, allowing them to decrypt and read "secure" communications.</p>
<p>Certificate pinning solves this by making your app trust only your specific server's certificate, rejecting all others – even if they're otherwise valid.</p>
<p><strong>How Certificate Pinning Works:</strong></p>
<p>Your app stores the expected certificate (or its public key hash) and validates it during each connection:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureNetworkManager</span>: <span class="hljs-title">NSObject</span>, <span class="hljs-title">URLSessionDelegate</span> </span>{

    <span class="hljs-comment">// Store your server's certificate hash</span>
    <span class="hljs-comment">// Get this by running: openssl x509 -in certificate.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> expectedPublicKeyHash = <span class="hljs-string">"YOUR_CERTIFICATE_HASH_HERE"</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">urlSession</span><span class="hljs-params">(
        <span class="hljs-number">_</span> session: URLSession,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping <span class="hljs-params">(URLSession.AuthChallengeDisposition, URLCredential?)</span></span></span> -&gt; <span class="hljs-type">Void</span>
    ) {
        <span class="hljs-comment">// Step 1: Check if this is a server trust challenge (certificate validation)</span>
        <span class="hljs-keyword">guard</span> challenge.protectionSpace.authenticationMethod == <span class="hljs-type">NSURLAuthenticationMethodServerTrust</span>,
              <span class="hljs-keyword">let</span> serverTrust = challenge.protectionSpace.serverTrust
        <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Not a certificate challenge; use default handling</span>
            completionHandler(.performDefaultHandling, <span class="hljs-literal">nil</span>)
            <span class="hljs-keyword">return</span>
        }

        <span class="hljs-comment">// Step 2: Validate that the server's certificate matches our pinned certificate</span>
        <span class="hljs-keyword">if</span> isValidServerTrust(serverTrust) {
            <span class="hljs-comment">// Certificate matches - proceed with the connection</span>
            completionHandler(.useCredential, <span class="hljs-type">URLCredential</span>(trust: serverTrust))
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Certificate doesn't match - reject the connection to prevent MITM attack</span>
            completionHandler(.cancelAuthenticationChallenge, <span class="hljs-literal">nil</span>)
        }
    }

    <span class="hljs-comment">// Validates the server's certificate against our pinned hash</span>
    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isValidServerTrust</span><span class="hljs-params">(<span class="hljs-number">_</span> serverTrust: SecTrust)</span></span> -&gt; <span class="hljs-type">Bool</span> {
        <span class="hljs-comment">// Extract the server's certificate</span>
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> serverCertificate = <span class="hljs-type">SecTrustGetCertificateAtIndex</span>(serverTrust, <span class="hljs-number">0</span>) <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }

        <span class="hljs-comment">// Get the public key from the certificate</span>
        <span class="hljs-keyword">let</span> serverPublicKey = <span class="hljs-type">SecCertificateCopyKey</span>(serverCertificate)
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> publicKey = serverPublicKey <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }

        <span class="hljs-comment">// Convert the public key to data and hash it</span>
        <span class="hljs-keyword">var</span> error: <span class="hljs-type">Unmanaged</span>&lt;<span class="hljs-type">CFError</span>&gt;?
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> publicKeyData = <span class="hljs-type">SecKeyCopyExternalRepresentation</span>(publicKey, &amp;error) <span class="hljs-keyword">as</span> <span class="hljs-type">Data?</span> <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }

        <span class="hljs-comment">// Hash the public key using SHA-256</span>
        <span class="hljs-keyword">let</span> publicKeyHash = <span class="hljs-type">SHA256</span>.hash(data: publicKeyData)
        <span class="hljs-keyword">let</span> publicKeyHashString = <span class="hljs-type">Data</span>(publicKeyHash).base64EncodedString()

        <span class="hljs-comment">// Compare with our expected hash</span>
        <span class="hljs-keyword">return</span> publicKeyHashString == expectedPublicKeyHash
    }
}
</code></pre>
<p>What this code does, step-by-step:</p>
<ol>
<li><p><code>urlSession(_:didReceive:completionHandler:)</code> – This method is called whenever your app makes an HTTPS connection. iOS asks: "Should I trust this server's certificate?"</p>
</li>
<li><p>Check authentication method – We verify this is a server trust challenge (certificate validation), not some other type of authentication.</p>
</li>
<li><p>Validate the certificate – We call <code>isValidServerTrust()</code>, which:</p>
<ul>
<li><p>Extracts the server's certificate from the connection</p>
</li>
<li><p>Gets the public key from that certificate</p>
</li>
<li><p>Hashes the public key using SHA-256</p>
</li>
<li><p>Compares the hash to our stored, expected hash</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li>Make a decision:</li>
</ol>
<ul>
<li><p>If hashes match, then the server is legitimate. Proceed with <code>.useCredential</code>.</p>
</li>
<li><p>If hashes don't match, we have a potential MITM attack. Cancel with <code>.cancelAuthenticationChallenge</code>.</p>
</li>
</ul>
<p>So how does this prevent MITM attacks? Even if an attacker installs a fraudulent certificate on the user's device and intercepts traffic, their certificate's hash won't match your pinned hash. Your app will reject the connection, preventing the attacker from decrypting your traffic.</p>
<p><strong>3. Additional Protection: Recommend a VPN on Public Wi-Fi</strong></p>
<p>You can also recommend that users connect through a VPN when on public Wi-Fi for an added layer of security, and provide guidance on <a target="_blank" href="https://surfshark.com/blog/how-to-use-a-vpn">how to use a VPN</a> effectively to keep their data safe.</p>
<p>For developers, maintaining strong app security also depends on having a well-optimized system, learning <a target="_blank" href="https://cleanmymac.com/blog/macos-tahoe-slow">how to speed up a slow Mac</a> can help ensure smoother builds, faster testing, and a more secure overall development workflow.</p>
<h3 id="heading-3-improper-input-validation">3. Improper Input Validation</h3>
<p>Some developers neglect correct input validation, leading to a number of vulnerabilities including SQL injection, remote code execution, and data corruption.</p>
<p>While Swift has strong typing support, some developers don’t sanitize user input or API responses. Incorporating real-time <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-email-validation-api-for-flask-user-authentication/">API email validation</a> ensures that users provide legitimate, properly formatted email addresses before they are stored or processed, reducing both security risks and data quality issues.</p>
<h4 id="heading-how-to-fix-2">How to Fix:</h4>
<p>Input validation is your first line of defense against malicious data. Here's how to protect your iOS applications:</p>
<p><strong>1. Validate User Input with Patterns</strong></p>
<p>Always validate user input using regular expressions or predefined patterns before processing. For example, when accepting email addresses:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isValidEmail</span><span class="hljs-params">(<span class="hljs-number">_</span> email: String)</span></span> -&gt; <span class="hljs-type">Bool</span> {
    <span class="hljs-keyword">let</span> emailRegex = <span class="hljs-string">"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"</span>
    <span class="hljs-keyword">let</span> emailPredicate = <span class="hljs-type">NSPredicate</span>(format: <span class="hljs-string">"SELF MATCHES %@"</span>, emailRegex)
    <span class="hljs-keyword">return</span> emailPredicate.evaluate(with: email)
}

<span class="hljs-comment">// Only accept properly formatted data</span>
<span class="hljs-keyword">guard</span> isValidEmail(userEmail) <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Reject invalid input</span>
    <span class="hljs-keyword">return</span>
}
</code></pre>
<p>This ensures that only properly formatted data is accepted, preventing malformed or malicious input from entering your system.</p>
<p><strong>2. Sanitize API Responses</strong></p>
<p>Never trust external data. Always validate and sanitize API responses before using them:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> userAge = apiResponse[<span class="hljs-string">"age"</span>] <span class="hljs-keyword">as</span>? <span class="hljs-type">Int</span>,
   userAge &gt;= <span class="hljs-number">0</span> &amp;&amp; userAge &lt;= <span class="hljs-number">150</span> {
    <span class="hljs-comment">// Safe to use</span>
    user.age = userAge
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Handle invalid data appropriately</span>
    <span class="hljs-keyword">throw</span> <span class="hljs-type">ValidationError</span>.invalidAge
}
</code></pre>
<p><strong>3. Use Parameterized Queries (Most Critical)</strong></p>
<p>The most dangerous mistake is building database queries through string concatenation. Consider this vulnerable code:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ❌ NEVER DO THIS - Vulnerable to SQL Injection</span>
<span class="hljs-keyword">let</span> username = userInput  <span class="hljs-comment">// Could be: "admin' OR '1'='1"</span>
<span class="hljs-keyword">let</span> query = <span class="hljs-string">"SELECT * FROM users WHERE username = '\(username)'"</span>
database.execute(query)
</code></pre>
<p>If a malicious user enters admin' OR '1'='1 as their username, the query becomes:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">WHERE</span> username = <span class="hljs-string">'admin'</span> <span class="hljs-keyword">OR</span> <span class="hljs-string">'1'</span>=<span class="hljs-string">'1'</span>
</code></pre>
<p>This would return all users in the database instead of just one, potentially exposing sensitive data. The secure solution uses parameterized queries:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ✅ SAFE - Using parameterized queries</span>
<span class="hljs-keyword">let</span> query = <span class="hljs-string">"SELECT * FROM users WHERE username = ?"</span>
database.execute(query, withArgumentsIn: [username])
</code></pre>
<p>In this approach, the <code>?</code> is a placeholder that the database treats as a parameter, not as part of the SQL command. The username value is passed separately in the <code>withArgumentsIn</code> array.</p>
<p>This means that even if a user tries to inject SQL code like <code>admin' OR '1'='1</code>, the database will treat the entire string as a literal username to search for – not as executable SQL code. The database engine automatically escapes any special characters, completely eliminating the risk of SQL injection.</p>
<p>By separating the query structure from the data, parameterized queries ensure that user input can never alter the intended logic of your SQL statements.</p>
<h3 id="heading-4-hardcoding-secrets">4. Hardcoding Secrets</h3>
<p>API keys, credentials, or private tokens hard-coded in the source code is another serious security mistake. Attackers can extract such secrets from compiled binaries using reverse-engineering tools, especially for apps released to the public.</p>
<p>Once exposed, these credentials can be used to access your backend services, potentially leading to data breaches or unauthorized charges.</p>
<h4 id="heading-the-problem-hardcoded-secrets">The Problem – Hardcoded Secrets:</h4>
<pre><code class="lang-swift"><span class="hljs-comment">// NEVER DO THIS</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">APIClient</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> apiKey = <span class="hljs-string">"1234567890abcdef"</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> secretToken = <span class="hljs-string">"sk_live_51H..."</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">makeRequest</span><span class="hljs-params">()</span></span> {
        <span class="hljs-comment">// These secrets are embedded in your binary</span>
        <span class="hljs-keyword">let</span> headers = [<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">"Bearer \(apiKey)"</span>]
    }
}
</code></pre>
<p><strong>How to Fix:</strong></p>
<p>Never store sensitive credentials directly in your code. Here are secure alternatives:</p>
<p><strong>Solution 1: Fetch Secrets from Backend at Runtime</strong></p>
<p>The most secure approach is to never store secrets on the client at all. Instead, authenticate users and let your backend make authorized API calls:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">APIClient</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> sessionToken: <span class="hljs-type">String?</span>

    <span class="hljs-comment">// User logs in and receives a temporary session token</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">authenticateUser</span><span class="hljs-params">(email: String, password: String)</span></span> async <span class="hljs-keyword">throws</span> {
        <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">try</span> await backend.login(email: email, password: password)
        <span class="hljs-comment">// Store only a temporary, user-specific session token</span>
        <span class="hljs-keyword">self</span>.sessionToken = response.sessionToken
    }

    <span class="hljs-comment">// Backend handles the actual API calls with the real API key</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchUserData</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; <span class="hljs-type">UserData</span> {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> token = sessionToken <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-type">AuthError</span>.notAuthenticated
        }

        <span class="hljs-comment">// Your backend receives this request, validates the session token,</span>
        <span class="hljs-comment">// then uses its own API keys to fetch data from third-party services</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> await backend.getUserData(sessionToken: token)
    }
}
</code></pre>
<p><strong>How this works:</strong></p>
<p>Your app never knows the actual API keys. When a user needs data, your app sends a request to your own backend server with a session token. Your backend validates the token, then uses its own securely stored API keys to make the actual third-party API calls. This way, the real secrets never leave your server.</p>
<p><strong>Solution 2: Environment Variables or Config Files (Development Only)</strong></p>
<p>For development environments, use .xcconfig files that are excluded from version control:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Secrets.xcconfig (add to .gitignore!)</span>
<span class="hljs-type">API_KEY</span> = your_dev_api_key_here
<span class="hljs-type">API_SECRET</span> = your_dev_secret_here

<span class="hljs-comment">// Access in your code through Info.plist</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> apiKey: <span class="hljs-type">String</span> = {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> key = <span class="hljs-type">Bundle</span>.main.object(forInfoDictionaryKey: <span class="hljs-string">"API_KEY"</span>) <span class="hljs-keyword">as</span>? <span class="hljs-type">String</span> <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"API_KEY not found in configuration"</span>)
        }
        <span class="hljs-keyword">return</span> key
    }()
}
</code></pre>
<p><strong>Important</strong>: This approach is only suitable for non-production environments! Never ship production API keys with your app, even in config files.</p>
<h3 id="heading-5-insufficient-authentication-and-authorization">5. Insufficient Authentication and Authorization</h3>
<p>Relying on client-side authentication and authorization checks is risky. Attackers can cause the app to bypass these checks and access in an unauthorized way by brute forcing or tampering with the app/runtime.</p>
<h4 id="heading-how-to-fix-3">How to Fix:</h4>
<ul>
<li><p>Do authentication and authorization on the server side instead of the client-side.</p>
</li>
<li><p>Use JWT (JSON Web Tokens) or OAuth 2.0 for authenticated user login.</p>
</li>
<li><p>Token expiration and refresh logic needs to be implemented in order to minimize the likelihood of token theft.</p>
</li>
</ul>
<p><strong>Example: Securely sending JWT:</strong></p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> request = <span class="hljs-type">URLRequest</span>(url: apiURL)

request.setValue(<span class="hljs-string">"Bearer \(jwtToken)"</span>, forHTTPHeaderField: <span class="hljs-string">"Authorization"</span>)
</code></pre>
<h3 id="heading-6-insecure-logging-and-error-handling">6. Insecure Logging and Error Handling</h3>
<p>Extensive and insecure logging practices, as well as uncaught exceptions, can lead to the exposure of sensitive information including usernames, passwords, and API keys.</p>
<h4 id="heading-how-to-fix-4">How to Fix:</h4>
<ul>
<li><p>Log sensitive information carefully.</p>
</li>
<li><p>Implement controlled error management and provide the minimum amount of information in user-presented messages.</p>
</li>
<li><p>Implement secure logging libraries that mask or encrypt personal data.</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">try</span> someRiskyOperation()
} <span class="hljs-keyword">catch</span> {
    <span class="hljs-comment">// Log error securely</span>
    <span class="hljs-type">Logger</span>.log(<span class="hljs-string">"Operation failed: \(error.localizedDescription)"</span>)
}
</code></pre>
<h3 id="heading-7-ignoring-code-obfuscation-and-reverse-engineering">7. Ignoring Code Obfuscation and Reverse Engineering</h3>
<p>Swift binaries can be reverse-engineered to expose sensitive business logic, algorithms, or hidden secrets. Attackers use tools like Hopper Disassembler, class-dump, or IDA Pro to decompile your app and analyze how it works internally. This risk is often underestimated, especially for smaller apps, but any app can be a target.</p>
<p>This means that when you compile a Swift app, the resulting binary contains:</p>
<ul>
<li><p>Class names and method signatures</p>
</li>
<li><p>String literals (URLs, error messages, keys)</p>
</li>
<li><p>The structure of your code logic</p>
</li>
<li><p>Algorithm implementations</p>
</li>
</ul>
<p>An attacker can extract this information and use it to understand your app's authentication flow and bypass it, copy your proprietary algorithms, find hardcoded API endpoints or keys you thought were "hidden", discover premium features to unlock without paying, and so on.</p>
<p><strong>Why It's Bad – Real Example:</strong></p>
<p>Let's imagine you have a premium feature check in your app:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FeatureManager</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isPremiumUser</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> {
        <span class="hljs-comment">// Check if user has premium access</span>
        <span class="hljs-keyword">let</span> hasSubscription = <span class="hljs-type">UserDefaults</span>.standard.bool(forKey: <span class="hljs-string">"premium_unlocked"</span>)
        <span class="hljs-keyword">return</span> hasSubscription
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">unlockPremiumFeature</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">guard</span> isPremiumUser() <span class="hljs-keyword">else</span> {
            showPaywall()
            <span class="hljs-keyword">return</span>
        }
        <span class="hljs-comment">// Show premium content</span>
        showPremiumContent()
    }
}
</code></pre>
<p>An attacker could reverse-engineer your app and discover that the method <code>isPremiumUser()</code> controls access, and that it simply checks a <code>UserDefaults</code> key called <code>premium_unlocked</code>. They would then know that they could use runtime manipulation tools to set this value to true, bypassing your paywall entirely.</p>
<p><strong>How to Fix:</strong></p>
<p><strong>1. Use Swift Compiler Optimizations</strong></p>
<p>Enable optimization flags that strip debugging symbols and make the binary harder to read:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// In your build settings:</span>
<span class="hljs-comment">// - Set "Optimization Level" to "-O" (or -Osize) for release builds</span>
<span class="hljs-comment">// - Enable "Strip Debug Symbols During Copy" = YES</span>
<span class="hljs-comment">// - Set "Strip Style" to "All Symbols"</span>
</code></pre>
<p>This removes function names and makes the compiled code less readable – though class/method names remain partially visible.</p>
<p><strong>2. Use Symbol Obfuscation Tools</strong></p>
<p>Tools like SwiftShield can rename your classes, methods, and properties to meaningless names:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Before obfuscation (readable to attackers):</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FeatureManager</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isPremiumUser</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> { ... }
}

<span class="hljs-comment">// After obfuscation (harder to understand):</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">a7f3b2</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">x9k2m</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> { ... }
}
</code></pre>
<p>While this doesn't prevent reverse engineering, it makes it significantly harder for attackers to understand what the code does.</p>
<p><strong>3. Move Sensitive Logic to the Server (Best Practice)</strong></p>
<p>Instead of checking premium status locally, verify it server-side:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ✅ Secure approach - Server validates everything</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FeatureManager</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">unlockPremiumFeature</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">do</span> {
            <span class="hljs-comment">// Server checks if user truly has premium access</span>
            <span class="hljs-keyword">let</span> hasAccess = <span class="hljs-keyword">try</span> await backend.verifyPremiumAccess(userId: currentUserId)

            <span class="hljs-keyword">if</span> hasAccess {
                showPremiumContent()
            } <span class="hljs-keyword">else</span> {
                showPaywall()
            }
        } <span class="hljs-keyword">catch</span> {
            <span class="hljs-comment">// Handle error</span>
            showPaywall()
        }
    }
}
</code></pre>
<p><strong>How this works:</strong></p>
<p>Your backend maintains the source of truth about premium access. Even if an attacker reverse-engineers your app and tries to bypass the check, the server will reject unauthorized requests. The app becomes just a UI layer, while all critical decisions happen server-side – where attackers can't manipulate them.</p>
<p>The key principle is to assume your app code is public: never rely on client-side checks for security-critical operations like payments, access control, or authentication. Use obfuscation to make reverse engineering harder, but ultimately move sensitive logic to your secure backend</p>
<h3 id="heading-8-insecure-third-party-libraries">8. Insecure Third-Party Libraries</h3>
<p>Third-party libraries are at risk if they are hacked or outdated. Developers might inadvertently prioritize app functionality over potential security risks from dependencies, and <a target="_blank" href="https://airbyte.com/top-etl-tools-for-sources/etl-tools">ETL tools</a> can further help by streamlining the monitoring and processing of dependency-related data to identify vulnerabilities more efficiently.</p>
<p>On a broader scale, implementing strong data center security practices ensures that even if third-party components introduce risks, the underlying infrastructure remains resilient against attacks.</p>
<h4 id="heading-how-to-fix-5">How to Fix:</h4>
<ul>
<li><p>Use only high-quality, well-maintained libraries.</p>
</li>
<li><p>Update dependencies and monitor CVEs (Common Vulnerabilities and Exposures).</p>
</li>
<li><p>Audit library code if it handles sensitive data.</p>
</li>
</ul>
<h3 id="heading-9-insufficient-biometric-and-multi-factor-authentication">9. Insufficient Biometric and Multi-Factor Authentication</h3>
<p>Most applications rely on passwords alone, which are vulnerable to being hacked. Enabling biometrics like Face ID or Touch ID enhances security for users.</p>
<h4 id="heading-how-to-fix-6">How to Fix:</h4>
<ul>
<li><p>Tie LocalAuthentication framework for biometric authentication.</p>
</li>
<li><p>Combine biometrics with server-based authentication for multifactor authentication (MFA).</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> LocalAuthentication

<span class="hljs-keyword">let</span> context = <span class="hljs-type">LAContext</span>()

<span class="hljs-keyword">var</span> error: <span class="hljs-type">NSError?</span>

<span class="hljs-keyword">if</span> context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &amp;error) {

    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,

                        localizedReason: <span class="hljs-string">"Access your account"</span>) { success, authError <span class="hljs-keyword">in</span>

        <span class="hljs-type">DispatchQueue</span>.main.async {

         <span class="hljs-keyword">if</span> success {

                <span class="hljs-comment">// Proceed securely</span>

         } <span class="hljs-keyword">else</span> {

                <span class="hljs-comment">// Handle failure (authError may contain the reason)</span>

                <span class="hljs-built_in">print</span>(<span class="hljs-string">"Authentication failed: \(authError?.localizedDescription ?? "</span><span class="hljs-type">Unknown</span> error<span class="hljs-string">")"</span>)

         }

     }

}

} <span class="hljs-keyword">else</span> {

<span class="hljs-comment">// Biometrics not available, check error for details</span>

    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Biometrics unavailable: \(error?.localizedDescription ?? "</span><span class="hljs-type">Unknown</span> error<span class="hljs-string">")"</span>)

}
</code></pre>
<h3 id="heading-10-disregarding-periodic-security-testing">10. Disregarding Periodic Security Testing</h3>
<p>Apps, despite following best practices during development, often contain unexplored vulnerabilities that emerge from complex interactions, third-party dependencies, or newly discovered attack vectors. Regular security testing is absolutely essential to discover these vulnerabilities before attackers exploit them.</p>
<p>Security testing should happen at multiple stages, using accessible tools and practices:</p>
<ol>
<li><p><strong>Automated security scans:</strong> Run automatically with every build to catch common issues.</p>
</li>
<li><p><strong>Self-conducted code audits:</strong> Regular security-focused reviews of your own code using established guidelines.</p>
</li>
<li><p><strong>Vulnerability scanning tools:</strong> Use free tools like MobSF to analyze your app for security flaws.</p>
</li>
<li><p><strong>Dependency audits:</strong> Checking third-party libraries for known security vulnerabilities.</p>
</li>
</ol>
<p><strong>How to Fix:</strong></p>
<p><strong>1. Implement Automated Security Scans in CI/CD</strong></p>
<p>Integrate security scanning tools into your continuous integration pipeline so every code change is automatically checked:</p>
<pre><code class="lang-swift"># <span class="hljs-type">Example</span>: <span class="hljs-type">GitHub</span> <span class="hljs-type">Actions</span> workflow <span class="hljs-keyword">for</span> automated security scanning
name: <span class="hljs-type">Security</span> <span class="hljs-type">Scan</span>

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: macos-latest

    steps:
      - name: <span class="hljs-type">Checkout</span> code
        uses: actions/checkout@v3

      - name: <span class="hljs-type">Run</span> <span class="hljs-type">MobSF</span> <span class="hljs-type">Security</span> <span class="hljs-type">Scan</span>
        run: |
          # <span class="hljs-type">Mobile</span> <span class="hljs-type">Security</span> <span class="hljs-type">Framework</span> - scans <span class="hljs-keyword">for</span> common vulnerabilities
          docker run -v $(pwd):/app opensecurity/mobile-security-framework-mobsf

      - name: <span class="hljs-type">Dependency</span> <span class="hljs-type">Vulnerability</span> <span class="hljs-type">Check</span>
        run: |
          # <span class="hljs-type">Check</span> <span class="hljs-type">CocoaPods</span>/<span class="hljs-type">SPM</span> dependencies <span class="hljs-keyword">for</span> known <span class="hljs-type">CVEs</span>
          brew install dependency-check
          dependency-check --scan ./<span class="hljs-type">Podfile</span>.lock --format <span class="hljs-type">JSON</span>

      - name: <span class="hljs-type">Secret</span> <span class="hljs-type">Detection</span>
        run: |
          # <span class="hljs-type">Detect</span> accidentally committed secrets
          brew install truffleHog
          truffleHog filesystem . --json

      - name: <span class="hljs-type">Fail</span> build on critical issues
        run: |
          <span class="hljs-keyword">if</span> grep -q <span class="hljs-string">"CRITICAL"</span> security-report.json; then
            echo <span class="hljs-string">"Critical security issues found!"</span>
            exit <span class="hljs-number">1</span>
          fi
</code></pre>
<p><strong>Automated scans check for:</strong></p>
<ul>
<li><p>Hardcoded API keys, tokens, or passwords</p>
</li>
<li><p>Insecure network configurations (allowing HTTP instead of HTTPS)</p>
</li>
<li><p>Weak cryptographic algorithms</p>
</li>
<li><p>Known vulnerabilities in third-party libraries</p>
</li>
<li><p>Improper SSL/TLS certificate validation</p>
</li>
<li><p>Insecure data storage (storing sensitive data in UserDefaults)</p>
</li>
<li><p>Excessive app permissions</p>
</li>
</ul>
<p><strong>Example output from an automated scan:</strong></p>
<pre><code class="lang-swift"><span class="hljs-type">Security</span> <span class="hljs-type">Scan</span> <span class="hljs-type">Results</span>:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[<span class="hljs-type">CRITICAL</span>] <span class="hljs-type">Hardcoded</span> <span class="hljs-type">API</span> <span class="hljs-type">Key</span> <span class="hljs-type">Found</span>
  <span class="hljs-type">File</span>: <span class="hljs-type">APIClient</span>.swift:<span class="hljs-number">15</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">API</span> key <span class="hljs-string">"sk_live_abc123..."</span> detected <span class="hljs-keyword">in</span> source code

[<span class="hljs-type">HIGH</span>] <span class="hljs-type">Insecure</span> <span class="hljs-type">HTTP</span> <span class="hljs-type">Connection</span>
  <span class="hljs-type">File</span>: <span class="hljs-type">NetworkManager</span>.swift:<span class="hljs-number">42</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">App</span> allows cleartext <span class="hljs-type">HTTP</span> traffic to api.example.com
  <span class="hljs-type">Fix</span>: <span class="hljs-type">Enforce</span> <span class="hljs-type">HTTPS</span> or add exception to <span class="hljs-type">Info</span>.plist <span class="hljs-keyword">if</span> <span class="hljs-keyword">required</span>

[<span class="hljs-type">MEDIUM</span>] <span class="hljs-type">Weak</span> <span class="hljs-type">Encryption</span> <span class="hljs-type">Algorithm</span>
  <span class="hljs-type">File</span>: <span class="hljs-type">DataEncryption</span>.swift:<span class="hljs-number">28</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">Using</span> <span class="hljs-type">MD5</span> <span class="hljs-keyword">for</span> hashing (cryptographically broken)
  <span class="hljs-type">Fix</span>: <span class="hljs-type">Use</span> <span class="hljs-type">SHA</span>-<span class="hljs-number">256</span> or better

[<span class="hljs-type">LOW</span>] <span class="hljs-type">Outdated</span> <span class="hljs-type">Dependency</span>
  <span class="hljs-type">Library</span>: <span class="hljs-type">Alamofire</span> <span class="hljs-number">4.2</span>.<span class="hljs-number">0</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">Known</span> vulnerability <span class="hljs-type">CVE</span>-<span class="hljs-number">2021</span>-<span class="hljs-number">12345</span>
  <span class="hljs-type">Fix</span>: <span class="hljs-type">Update</span> to version <span class="hljs-number">5.6</span>.<span class="hljs-number">0</span> or later
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
<span class="hljs-type">Build</span> <span class="hljs-type">Failed</span>: <span class="hljs-number">2</span> critical issues must be fixed before deployment
</code></pre>
<p><strong>2. Use MobSF (Mobile Security Framework) for Vulnerability Analysis</strong></p>
<p>MobSF is a free, automated tool that analyzes your iOS app for security issues:</p>
<pre><code class="lang-swift"># <span class="hljs-type">Install</span> and run <span class="hljs-type">MobSF</span> locally
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p <span class="hljs-number">8000</span>:<span class="hljs-number">8000</span> opensecurity/mobile-security-framework-mobsf

# <span class="hljs-type">Upload</span> your .ipa file through the web interface at localhost:<span class="hljs-number">8000</span>
# <span class="hljs-type">MobSF</span> will analyze and provide a detailed security report
</code></pre>
<p>What MobSF checks:</p>
<ul>
<li><p>Binary analysis for hardcoded secrets</p>
</li>
<li><p>Insecure data storage patterns</p>
</li>
<li><p>Weak cryptographic implementations</p>
</li>
<li><p>Insecure network connections</p>
</li>
<li><p>Code quality and security best practices</p>
</li>
<li><p>Compliance with security standards</p>
</li>
</ul>
<p><strong>3. Conduct Regular Code Audits Using OWASP MSTG</strong></p>
<p>Use the OWASP Mobile Security Testing Guide as a checklist to audit your own code:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Example: Following OWASP MSTG recommendations for secure storage</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureStorage</span> </span>{
    <span class="hljs-comment">// ❌ Insecure - UserDefaults is not encrypted</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">saveTokenInsecurely</span><span class="hljs-params">(<span class="hljs-number">_</span> token: String)</span></span> {
        <span class="hljs-type">UserDefaults</span>.standard.<span class="hljs-keyword">set</span>(token, forKey: <span class="hljs-string">"authToken"</span>)
    }

    <span class="hljs-comment">// ✅ Secure - Using Keychain as OWASP recommends</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">saveTokenSecurely</span><span class="hljs-params">(<span class="hljs-number">_</span> token: String)</span></span> <span class="hljs-keyword">throws</span> {
        <span class="hljs-keyword">let</span> data = token.data(using: .utf8)!
        <span class="hljs-keyword">let</span> query: [<span class="hljs-type">String</span>: <span class="hljs-type">Any</span>] = [
            kSecClass <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecClassGenericPassword,
            kSecAttrAccount <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: <span class="hljs-string">"authToken"</span>,
            kSecValueData <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: data,
            kSecAttrAccessible <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
        ]

        <span class="hljs-type">SecItemDelete</span>(query <span class="hljs-keyword">as</span> <span class="hljs-type">CFDictionary</span>)
        <span class="hljs-keyword">let</span> status = <span class="hljs-type">SecItemAdd</span>(query <span class="hljs-keyword">as</span> <span class="hljs-type">CFDictionary</span>, <span class="hljs-literal">nil</span>)

        <span class="hljs-keyword">guard</span> status == errSecSuccess <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-type">StorageError</span>.saveFailed
        }
    }
}
</code></pre>
<p><strong>OWASP MSTG Checklist for Self-Audit:</strong></p>
<ul>
<li><p>[ ] Are all sensitive data encrypted at rest?</p>
</li>
<li><p>[ ] Is HTTPS enforced for all network calls?</p>
</li>
<li><p>[ ] Are certificates properly validated?</p>
</li>
<li><p>[ ] Is sensitive data excluded from logs?</p>
</li>
<li><p>[ ] Are API keys and secrets not hardcoded?</p>
</li>
<li><p>[ ] Is user input validated and sanitized?</p>
</li>
<li><p>[ ] Are authentication tokens stored securely in Keychain?</p>
</li>
</ul>
<p><strong>4. Automated Dependency Scanning</strong></p>
<p>Monitor your dependencies continuously for newly discovered vulnerabilities:</p>
<pre><code class="lang-swift"># <span class="hljs-type">For</span> <span class="hljs-type">CocoaPods</span> projects
gem install cocoapods-audit
pod audit

# <span class="hljs-type">For</span> <span class="hljs-type">Swift</span> <span class="hljs-type">Package</span> <span class="hljs-type">Manager</span>
# <span class="hljs-type">Use</span> <span class="hljs-type">GitHub</span> <span class="hljs-type">Dependabot</span> (free <span class="hljs-keyword">for</span> <span class="hljs-keyword">public</span> repos) or
brew install swift-outdated
swift-outdated
</code></pre>
<p>And set up automated alerts with these tools:</p>
<ul>
<li><p><strong>GitHub Dependabot:</strong> Automatically creates PRs when vulnerable dependencies are detected (free)</p>
</li>
<li><p><strong>Snyk</strong>: Free tier available for open-source projects</p>
</li>
<li><p><strong>OWASP Dependency-Check:</strong> Free command-line tool</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Developing secure iOS apps using Swift is all about forward-thinking. You should do all you can to avoid these common errors, like insecure storage of data, poor network communication, hard-coded secrets, or poor authentication.</p>
<p>Using Keychain for confidential information, requiring HTTPS, input validation, and multifactor authentication are all steps that decrease risk.</p>
<p>Regular testing for security vulnerabilities and limiting third-party library use can also further enhance your app's security.</p>
<p>Security is a continuous responsibility. Swift provides tools, but the developers need to apply those tools carefully. Security being tackled right from the start protects users' information, creates trust, and protects the reputation of the application.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Embedded Swift: A Modern Approach to Low-Level Programming ]]>
                </title>
                <description>
                    <![CDATA[ Embedded programming has long been dominated by C and C++, powering everything from microcontrollers to real-time systems. While these languages offer unmatched low-level control, they also introduce persistent challenges, manual memory management, u... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/embedded-swift-a-modern-approach-to-low-level-programming/</link>
                <guid isPermaLink="false">688d5fc7d30be1cecdacf767</guid>
                
                    <category>
                        <![CDATA[ embedded systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Firmware Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C++ ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ memory-management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programming languages ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Soham Banerjee ]]>
                </dc:creator>
                <pubDate>Sat, 02 Aug 2025 00:45:59 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754090186842/80a42dca-f2c4-49de-b704-2e90134c6397.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Embedded programming has long been dominated by C and C++, powering everything from microcontrollers to real-time systems. While these languages offer unmatched low-level control, they also introduce persistent challenges, manual memory management, unsafe pointer operations, and subtle logic bugs stemming from weak type systems and undefined behavior.</p>
<p>With the release of Swift 6 and its new Embedded Swift compilation mode, developers now have access to a modern, memory-safe, and performant alternative that’s tailored specifically for resource-constrained systems.</p>
<p>While languages like Rust have also emerged to address these issues, Embedded Swift brings the clarity and safety of Swift to microcontroller environments, without giving up on determinism, binary size, or hardware access.</p>
<p>This article introduces Embedded Swift and explores how it compares to traditional C/C++ development. We’ll cover its key features, programming and memory models, how to set up the toolchain for STM32 microcontrollers, and how to link Swift with existing C drivers.</p>
<p>Along the way, we’ll examine performance trade-offs, growing ecosystem support, and the broader industry movement toward memory-safe languages. As I hope you’ll see, Swift is a serious contender in the future of embedded development.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most out of this article, you should have a basic understanding of programming in Swift and C. Familiarity with embedded hardware platforms and firmware development concepts will also be helpful.</p>
<p>If you're new to embedded systems, consider reviewing this <a target="_blank" href="https://www.freecodecamp.org/news/learn-embedded-systems-firmware-basics-handbook-for-devs/">introductory guide to embedded firmware</a> to build foundational knowledge before diving into Embedded Swift.</p>
<h2 id="heading-scope">Scope</h2>
<p>This article is intended as a practical introduction to Embedded Swift. It covers:</p>
<ul>
<li><p>An overview of Embedded Swift and its key language features</p>
</li>
<li><p>Swift’s programming and memory model in an embedded context</p>
</li>
<li><p>Setting up the Embedded Swift toolchain on macOS for STM32 microcontrollers</p>
</li>
<li><p>Interoperability with C code and linking to existing low-level drivers</p>
</li>
<li><p>A look at memory and instruction-level performance</p>
</li>
<li><p>Future directions and use cases for Embedded Swift</p>
</li>
</ul>
<p>Note that this article does not provide a full tutorial on the Swift language itself. While the primary focus is on STM32, similar principles apply to other supported platforms such as ESP32, Raspberry Pi Pico, and nRF52.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-swift-what-is-embedded-swift">What is Swift? What is Embedded Swift?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-swift-programming-model">Swift Programming Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-swift-memory-management">Swift Memory Management</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-memory-and-instruction-cycle-comparison">Memory and Instruction Cycle Comparison</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-setup-embedded-swift">How to Setup Embedded Swift</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-c-swift-linkages">C-Swift Linkages:</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-future-work">Future Work</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-swift-what-is-embedded-swift">What is Swift? What is Embedded Swift?</h2>
<p>Swift is a modern programming language developed by Apple that combines the performance of compiled languages with the expressiveness and safety of modern language design. While Swift was originally created for iOS and macOS development, it has evolved into a powerful general-purpose language used in server-side development, systems programming, and increasingly, embedded systems.</p>
<p>Embedded Swift is a special compilation mode introduced in Swift 6 that brings the benefits of Swift to resource-constrained platforms like microcontrollers. It lets developers use a safe, high-level language while still producing compact, deterministic, and performant binaries suitable for embedded applications.</p>
<h3 id="heading-key-features-of-swift">Key Features of Swift</h3>
<p>Embedded Swift retains many of the powerful language features that make Swift an attractive alternative to C/C++ in embedded development:</p>
<p><strong>Type Safety</strong>: Swift uses a strong static type system, which prevents many programming errors at compile time. Unlike C, where type mismatches can result in undefined behavior, Swift ensures all types are used correctly before code even runs.</p>
<p><strong>Strict Type Checking</strong>: Swift doesn't allow implicit type conversions that could lose data or cause unexpected behavior. For example:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// This won't compile in Swift</span>
<span class="hljs-keyword">let</span> integer: <span class="hljs-type">Int</span> = <span class="hljs-number">42</span>
<span class="hljs-keyword">let</span> decimal: <span class="hljs-type">Double</span> = <span class="hljs-number">3.14</span>
<span class="hljs-keyword">let</span> result = integer + decimal  <span class="hljs-comment">// Error: Cannot convert value of type 'Int' to expected argument type 'Double'</span>

<span class="hljs-comment">// You must be explicit about conversions</span>
<span class="hljs-keyword">let</span> result = <span class="hljs-type">Double</span>(integer) + decimal  <span class="hljs-comment">// Correct</span>
</code></pre>
<p><strong>Non-nullable Types by Default</strong>: In C, pointers can be null by default, which introduces risk. In Swift, variables cannot be nil unless explicitly marked as optionals:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> name: <span class="hljs-type">String</span> = <span class="hljs-string">"John"</span>
name = <span class="hljs-literal">nil</span>  <span class="hljs-comment">// Compile error - String cannot be nil</span>

<span class="hljs-keyword">var</span> optionalName: <span class="hljs-type">String?</span> = <span class="hljs-string">"John"</span>
optionalName = <span class="hljs-literal">nil</span>  <span class="hljs-comment">// This is allowed</span>
</code></pre>
<h4 id="heading-memory-safety-via-arc-covered-in-detail-later">Memory Safety via ARC (Covered in detail later):</h4>
<p>Swift manages memory automatically using Automatic Reference Counting (ARC). Unlike manual memory management in C/C++, ARC handles object lifecycles efficiently without unpredictable garbage collection pauses. We'll cover ARC and its impact in embedded contexts in a dedicated section later.</p>
<p><strong>Modern Syntax</strong>:<br>Swift's syntax is clean, consistent, and designed for readability. It supports modern paradigms including:</p>
<ul>
<li><p>Functional programming (map, filter, reduce)</p>
</li>
<li><p>Generics (type-safe abstractions)</p>
</li>
<li><p>Protocol-Oriented Programming (discussed in the next section)</p>
</li>
</ul>
<p>These features allow you to write more expressive and maintainable code compared to procedural C or inheritance-heavy C++.</p>
<p><strong>Performance</strong>:<br>Swift is designed to perform on par with C++ in many scenarios. Optimizations such as inlining, dead code elimination, and static dispatch help ensure that high-level abstractions don’t compromise performance. In embedded mode, Swift disables features like runtime reflection and dynamic dispatch to further reduce overhead.</p>
<p>To fully leverage Swift for embedded development, it's important to understand its programming model. Unlike C’s procedural approach or C++’s class-heavy design, Swift promotes protocol-oriented programming and composition, which offers both flexibility and safety in embedded system design.</p>
<h2 id="heading-swift-programming-model">Swift Programming Model</h2>
<p>Swift embraces a multi-paradigm programming model that blends object-oriented, functional, and protocol-oriented programming, all underpinned by strong type safety and memory safety.</p>
<p>For embedded developers coming from C or C++, this model may feel different at first. But it provides a more modular and testable way to build complex systems, something especially valuable in embedded applications where hardware abstraction and strict reliability are critical.</p>
<h3 id="heading-protocol-oriented-programming-pop">Protocol-Oriented Programming (POP)</h3>
<p>Swift emphasizes protocols over inheritance, encouraging developers to define behaviors through protocols and implement them using value types like <code>struct</code> and <code>enum</code>, rather than relying heavily on classes.</p>
<p>This philosophy favors composition over inheritance, allowing you to build complex functionality by combining smaller, well-defined components.</p>
<p>Key Concepts<strong>:</strong></p>
<ul>
<li><p><code>protocol</code> defines required behavior.</p>
</li>
<li><p>Protocol extensions provide default behavior.</p>
</li>
<li><p>Prefer value semantics using <code>struct</code>.</p>
</li>
</ul>
<p>Example<strong>:</strong></p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">Speakable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">speak</span><span class="hljs-params">()</span></span>
}

<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">Speakable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">speak</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Default sound"</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span>: <span class="hljs-title">Speakable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">speak</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Woof!"</span>)
    }
}
</code></pre>
<p>Embedded Swift uses protocols with static dispatch. With static dispatch, the compiler knows the exact memory address of the function to call and can generate a direct jump instruction. There's no runtime lookup, no indirection, and no uncertainty.</p>
<h4 id="heading-why-pop-matters-for-embedded-systems">Why POP Matters for Embedded Systems</h4>
<p>First, you get flexible hardware extraction. Protocols make it easy to define interfaces for hardware components, allowing for mock implementations during testing or platform-specific variations.</p>
<p>Second, you have nice low overhead. Embedded Swift uses static dispatch for protocols, meaning there’s no runtime lookup, and calls are resolved at compile time for maximum performance.</p>
<p>Also, <code>struct</code> and <code>enum</code> types avoid heap allocations, making code more efficient and predictable in low-memory environments.</p>
<p>Now that we’ve explored how Swift’s programming model enables safer and more modular embedded code, let’s turn to another critical piece of the puzzle: memory management. Swift’s use of Automatic Reference Counting (ARC) replaces manual memory handling and offers important benefits, and tradeoffs, for embedded systems.</p>
<h2 id="heading-swift-memory-management">Swift Memory Management</h2>
<p>One of Swift’s most impactful features, especially in the context of embedded systems, is its use of Automatic Reference Counting (ARC) for memory management. Unlike C/C++, where memory must be manually allocated and freed using <code>malloc</code> and <code>free</code>, Swift automates this process while maintaining deterministic performance.</p>
<p>This automation significantly reduces the risk of common memory-related bugs like leaks, dangling pointers, or use-after-free errors, all of which are notorious in low-level C code.</p>
<h3 id="heading-how-arc-works">How ARC works</h3>
<p>Swift supports ARC not only for the Cocoa Touch API's but for all APIs, providing a streamlined approach to memory management. Unlike garbage collection systems that can cause unpredictable pauses, ARC works deterministically at compile time and runtime to manage memory.</p>
<p>ARC automatically tracks and manages the lifetime of objects in memory based on how many references point to them.</p>
<ul>
<li><p>Reference Counting: Every object has a counter that tracks how many strong references point to it.</p>
</li>
<li><p>Retain / Release: The compiler inserts <code>retain</code> and <code>release</code> calls automatically during assignment and deinitialization.</p>
</li>
<li><p>Immediate Deallocation: When the reference count reaches zero, the object is deallocated immediately.</p>
</li>
<li><p>Deterministic: Unlike garbage collectors, ARC doesn’t introduce unpredictable pauses or runtime scanning.</p>
</li>
</ul>
<p>Swift offers multiple reference types to give you precise control over memory behavior and prevent cycles:</p>
<p><strong>Strong References</strong> (default)</p>
<ul>
<li><p>Keeps the referenced object alive.</p>
</li>
<li><p>Used in most cases.</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MotorController</span> </span>{
    <span class="hljs-keyword">var</span> sensor: <span class="hljs-type">SensorData?</span>  <span class="hljs-comment">// Strong reference</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateReading</span><span class="hljs-params">(newData: SensorData)</span></span> {
        <span class="hljs-keyword">self</span>.sensor = newData  <span class="hljs-comment">// Previous sensor data automatically deallocated</span>
    }
}
</code></pre>
<p><strong>Weak References</strong></p>
<ul>
<li><p>Used to break reference cycles (especially in two-way object relationships).</p>
</li>
<li><p>Automatically becomes <code>nil</code> when the referenced object is deallocated.</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Device</span> </span>{
    <span class="hljs-keyword">var</span> controller: <span class="hljs-type">MotorController?</span>

    <span class="hljs-keyword">deinit</span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Device deallocated"</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MotorController</span> </span>{
    <span class="hljs-keyword">weak</span> <span class="hljs-keyword">var</span> device: <span class="hljs-type">Device?</span>  <span class="hljs-comment">// ← Weak reference breaks the cycle</span>

    <span class="hljs-keyword">deinit</span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"MotorController deallocated"</span>)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">breakCycle</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">let</span> device = <span class="hljs-type">Device</span>()
    <span class="hljs-keyword">let</span> controller = <span class="hljs-type">MotorController</span>()

    device.controller = controller
    controller.device = device  <span class="hljs-comment">// ← This is now a weak reference</span>

    <span class="hljs-comment">// When this function ends, both objects are properly deallocated</span>
}

breakCycle()
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// Device deallocated</span>
<span class="hljs-comment">// MotorController deallocated</span>
</code></pre>
<p><strong>Unowned References</strong></p>
<ul>
<li><p>Non-optional version of <code>weak</code>.</p>
</li>
<li><p>Assumes the object will never be deallocated while still in use.</p>
</li>
<li><p>More lightweight than <code>weak</code>, but unsafe if misused.</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SensorSystem</span> </span>{
    <span class="hljs-keyword">unowned</span> <span class="hljs-keyword">let</span> controller: <span class="hljs-type">MotorController</span>  <span class="hljs-comment">// unowned reference</span>

    <span class="hljs-keyword">init</span>(controller: <span class="hljs-type">MotorController</span>) {
        <span class="hljs-keyword">self</span>.controller = controller
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MotorController</span> </span>{
    <span class="hljs-keyword">var</span> sensorSystem: <span class="hljs-type">SensorSystem?</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">setupSensors</span><span class="hljs-params">()</span></span> {
        sensorSystem = <span class="hljs-type">SensorSystem</span>(controller: <span class="hljs-keyword">self</span>)
    }

    <span class="hljs-keyword">deinit</span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"MotorController deallocated"</span>)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">testUnowned</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">let</span> controller = <span class="hljs-type">MotorController</span>()
    controller.setupSensors()
    <span class="hljs-comment">// sensorSystem deallocates before controller ends</span>
}

testUnowned()
<span class="hljs-comment">// Output: MotorController deallocated</span>
</code></pre>
<h3 id="heading-arc-overhead-in-embedded-systems">ARC Overhead in Embedded Systems</h3>
<p>While ARC provides safety benefits, it does introduce some overhead compared to manual memory management:</p>
<h4 id="heading-memory-overhead">Memory Overhead:</h4>
<p>ARC-managed class instances in Swift typically include an additional 4 or 8 bytes to store reference count metadata, depending on the system architecture, 4 bytes on 32-bit systems and 8 bytes on 64-bit systems. This metadata allows the runtime to track how many active references exist to a given object and deallocate it when no references remain. When developers use weak or unowned references, the memory footprint increases further. These references require additional data structures, such as side tables or tracking mechanisms, to manage object liveness and cleanup. In the case of weak references specifically, Swift maintains zeroing weak reference tables that automatically null out pointers once the referenced object is deallocated, ensuring memory safety.</p>
<h4 id="heading-cpu-overhead">CPU Overhead:</h4>
<p>ARC introduces some runtime overhead due to retain and release operations, which are inserted automatically during reference assignments. These operations involve incrementing or decrementing the reference count and are especially common in code that passes objects between functions or stores them in collections. To ensure thread safety, these updates are typically implemented using atomic operations, which add further instruction cycles. In complex object graphs, ARC may also engage in cycle detection and cleanup through the use of weak references to prevent memory leaks caused by strong reference cycles. While Swift's ARC provides deterministic and efficient memory management, it does so with both memory and CPU costs that developers should consider carefully, especially in performance-critical embedded systems.</p>
<h3 id="heading-type-safety-and-error-prevention">Type Safety and Error Prevention</h3>
<p>Swift's type system prevents many common errors that plague C/C++ programs:</p>
<ul>
<li><p><strong>Buffer Overflows</strong>: Swift arrays are bounds-checked, preventing buffer overflow vulnerabilities that are common in C.</p>
</li>
<li><p><strong>Null Pointer Dereferences</strong>: Swift's optional types make null pointer dereferences impossible at compile time.</p>
</li>
<li><p><strong>Use After Free</strong>: Swift's ownership model prevents use-after-free errors that can cause crashes or security vulnerabilities.</p>
</li>
</ul>
<p>Now that we’ve covered Swift's memory model and ARC behavior, let’s explore how it compares to C in terms of memory usage and instruction cycles, a crucial aspect when evaluating Embedded Swift for real-world deployment.</p>
<h2 id="heading-memory-and-instruction-cycle-comparison">Memory and Instruction Cycle Comparison</h2>
<p>Understanding the performance characteristics of Swift versus C is essential for embedded systems, where every instruction cycle and byte of memory matters. While Swift brings advantages like safety and expressiveness, these benefits come with certain trade-offs in terms of memory usage and runtime behavior that embedded developers must evaluate carefully.</p>
<h3 id="heading-memory-management">Memory Management:</h3>
<p>Swift uses Automatic Reference Counting (ARC) to manage memory. ARC tracks the number of references to each object and deallocates it when no references remain. This eliminates the need for explicit <code>free()</code> calls but introduces overhead.</p>
<p>C, in contrast, uses manual memory management. Developers allocate memory using <code>malloc</code> and release it using <code>free</code>, or rely on the stack for most short-lived data.</p>
<p>The table below provides the memory management comparison between Swift and C:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Swift (ARC)</strong></td><td><strong>C (Manual)</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Memory strategy</td><td>Automatic reference counting</td><td>Manual with <code>malloc</code>/<code>free</code></td></tr>
<tr>
<td>Overhead per object</td><td>4–8 bytes (for ref count)</td><td>None for stack; variable for heap</td></tr>
<tr>
<td>Deallocation</td><td>Deterministic, triggered by ARC</td><td>Developer-controlled</td></tr>
<tr>
<td>Weak reference support</td><td>Requires additional metadata</td><td>Not built-in</td></tr>
<tr>
<td>Thread safety</td><td>Atomic operations in ARC</td><td>Not guaranteed</td></tr>
<tr>
<td>Layout control</td><td>Limited, compiler-managed</td><td>Full control (via structs/pointers)</td></tr>
</tbody>
</table>
</div><p>Swift ensures safety through deterministic cleanup and predictable memory usage. But this comes at the cost of added memory and CPU overhead.</p>
<p>C’s approach offers complete control over memory layout and minimal runtime cost, but increases the risk of memory leaks and fragmentation without disciplined practices.</p>
<h3 id="heading-instruction-cycle-analysis">Instruction Cycle Analysis</h3>
<p>The safety features in Swift, such as bounds checking, optional unwrapping, and ARC updates, translate into additional CPU instructions. While this can impact performance, the Swift compiler is aggressive about optimization in release builds. For example, inlining and ARC elision can remove much of the overhead in performance-critical paths.</p>
<p>C has no built-in safety checks, allowing it to generate highly efficient, predictable code. Developers can even use inline assembly for tight control over performance.</p>
<p>The table below provides the instruction cycle comparison between Swift and C:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Instruction-Level Feature</strong></td><td><strong>Swift</strong></td><td><strong>C</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Reference count updates</td><td>2–4 instructions per assignment</td><td>N/A</td></tr>
<tr>
<td>Bounds checking</td><td>1–3 instructions per array access</td><td>None</td></tr>
<tr>
<td>Optional unwrapping</td><td>1–2 instructions per check</td><td>N/A</td></tr>
<tr>
<td>Method dispatch</td><td>Protocols introduce indirection</td><td>Direct calls or function pointers</td></tr>
<tr>
<td>Optimization potential</td><td>ARC elision, inlining, dead code removal</td><td>Full manual control, inline assembly</td></tr>
<tr>
<td>Predictability</td><td>High in optimized builds, with some abstraction overhead</td><td>Very high, minimal abstraction</td></tr>
</tbody>
</table>
</div><p>Although Swift inserts extra instructions for safety, much of this cost can be mitigated through compiler optimization.</p>
<p>C has no such features by default, making it ideal for applications where performance must be tightly controlled and the developer is willing to take full responsibility for safety.</p>
<h3 id="heading-instruction-count-comparison-swift-vs-c-loop-performance">Instruction Count Comparison: Swift vs C Loop Performance</h3>
<p>When evaluating Swift and C for embedded use, it's helpful to analyze instruction-level performance on basic operations, such as a loop that processes an array of floating-point numbers. This gives us a concrete sense of the computational cost of each language's safety and abstraction features.</p>
<p>Let’s consider a simple example: summing an array of <code>Float</code> values and returning the average. In Swift, the code uses a high-level <code>for-in</code> loop over an array:</p>
<p>Simple loop performance:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Swift loop with safety checks</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">processData</span><span class="hljs-params">(<span class="hljs-number">_</span> data: [Float])</span></span> -&gt; <span class="hljs-type">Float</span> {
    <span class="hljs-keyword">var</span> sum: <span class="hljs-type">Float</span> = <span class="hljs-number">0.0</span>
    <span class="hljs-keyword">for</span> value <span class="hljs-keyword">in</span> data {  <span class="hljs-comment">// Iterator with bounds checking</span>
        sum += value     <span class="hljs-comment">// Safe arithmetic</span>
    }
    <span class="hljs-keyword">return</span> sum / <span class="hljs-type">Float</span>(data.<span class="hljs-built_in">count</span>)  <span class="hljs-comment">// Safe division</span>
}
<span class="hljs-comment">// Estimated: ~8-10 instructions per iteration</span>
</code></pre>
<p>Although elegant and safe, this loop includes several safety mechanisms:</p>
<ol>
<li><p>Bounds checking on every array access</p>
</li>
<li><p>Reference counting if <code>data</code> is passed as a reference type</p>
</li>
<li><p>Overflow protection in debug mode</p>
</li>
<li><p>Optional handling or runtime checks if <code>data</code> might be empty</p>
</li>
</ol>
<p>These checks introduce runtime overhead, resulting in an estimated 8–10 instructions per iteration on most platforms (depending on optimization level and target architecture). In release builds, Swift aggressively inlines and strips redundant checks, but some level of abstraction cost remains, especially compared to raw memory access in C.</p>
<p>Now, compare that to its equivalent in C:</p>
<pre><code class="lang-c"><span class="hljs-comment">// C loop without safety checks</span>
<span class="hljs-function"><span class="hljs-keyword">float</span> <span class="hljs-title">process_data</span><span class="hljs-params">(<span class="hljs-keyword">float</span>* data, <span class="hljs-keyword">int</span> count)</span> </span>{
    <span class="hljs-keyword">float</span> sum = <span class="hljs-number">0.0f</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; count; i++) {  <span class="hljs-comment">// Direct pointer arithmetic</span>
        sum += data[i];                <span class="hljs-comment">// Direct memory access</span>
    }
    <span class="hljs-keyword">return</span> sum / count;  <span class="hljs-comment">// Direct division (no safety check)</span>
}
<span class="hljs-comment">// Estimated: ~4-5 instructions per iteration</span>
</code></pre>
<p>This version performs direct memory access with pointer arithmetic, no bounds checks, and no type safety. The C code is lower-level, with fewer runtime checks, and compiles down to just 4–5 instructions per iteration, depending on the target CPU and compiler flags. It is lean and fast, ideal for cycles-per-instruction-critical scenarios.</p>
<p>The table below shows the comparison of single loop performance between Swift and C:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Aspect</td><td>Swift</td><td>C</td></tr>
</thead>
<tbody>
<tr>
<td>Array access</td><td>Bounds-checked</td><td>Direct pointer access</td></tr>
<tr>
<td>Loop iteration</td><td>High-level iterator abstraction</td><td>Raw loop with pointer increment</td></tr>
<tr>
<td>Instruction count (per loop)</td><td>~8–10 (in debug), ~6–8 (in release)</td><td>~4–5</td></tr>
<tr>
<td>Division</td><td>Safe (avoids divide-by-zero in dev)</td><td>Direct</td></tr>
<tr>
<td>Overflow behavior</td><td>Checked in debug, unchecked in release</td><td>Unchecked</td></tr>
<tr>
<td>Readability and safety</td><td>High</td><td>Low</td></tr>
<tr>
<td>Performance</td><td>Lower (but optimizable)</td><td>Higher (manual)</td></tr>
</tbody>
</table>
</div><p>Now that we’ve compared Swift and C in terms of memory and cycle costs, let’s move into the practical side: how to set up Embedded Swift on an STM32 platform and get started with real-world development.</p>
<h2 id="heading-how-to-setup-embedded-swift">How to Setup Embedded Swift</h2>
<p>In this section, we'll walk through how to configure and use Embedded Swift for development on STM32 microcontrollers. STM32 is a popular family of ARM Cortex-M–based microcontrollers, commonly used in industrial, consumer, and IoT applications.</p>
<h3 id="heading-prerequisites-1">Prerequisites</h3>
<p><strong>Required Software:</strong></p>
<ul>
<li><p>Swift Development Snapshot (includes the Embedded Swift toolchain)</p>
</li>
<li><p>Swiftly - Easiest way to manage and install swift toolchains</p>
</li>
<li><p>Swiftc - Swift Compiler command-line tool</p>
</li>
<li><p>Python3 - Required to run scripts to convert Mach-O to binary files</p>
</li>
<li><p>Git (to clone sample repositories) like <a target="_blank" href="https://github.com/swiftlang/swift-embedded-examples">https://github.com/swiftlang/swift-embedded-examples</a></p>
</li>
<li><p>A Unix-like development environment (macOS is currently best supported)</p>
</li>
</ul>
<p><strong>Target Hardware:</strong> This guide focuses on STM32 microcontrollers, which are widely used in embedded applications and have excellent community support.</p>
<p>This guide walks you through the full setup process, from installing the required Swift toolchain to flashing the final binary onto your board. We’ll begin by installing the Swift Development Snapshot using Swiftly, a simple command-line utility for managing Swift toolchains. From there, we’ll configure the build system, set up the correct board variant, customize the build script, and compile the Swift and C source code into a binary. Finally, we’ll flash the firmware onto the STM32 using standard tools</p>
<h3 id="heading-install-swift-development-snapshot">Install Swift Development Snapshot</h3>
<p>The easiest way to install and manage Embedded Swift toolchains is by using the swiftly tool, which simplifies downloading and using Swift snapshots.</p>
<h4 id="heading-macos-installation">macOS Installation:</h4>
<p>The below steps will help install the Swift embedded toolchain:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Using Swiftly (Recommended)</span>
curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg
installer -pkg swiftly.pkg -target CurrentUserHomeDirectory
~/.swiftly/bin/swiftly init --quiet-shell-followup
<span class="hljs-built_in">source</span> <span class="hljs-string">"<span class="hljs-variable">${SWIFTLY_HOME_DIR:-<span class="hljs-variable">$HOME</span>/.swiftly}</span>/env.sh"</span>

<span class="hljs-comment"># Install and use development snapshot</span>
swiftly install main-snapshot
swiftly use main-snapshot

<span class="hljs-comment"># Verify installation</span>
swift --version
</code></pre>
<p>You can clone this Github example repository:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/swiftlang/swift-embedded-examples.git 
<span class="hljs-built_in">cd</span> swift-embedded-examples/projects/stm32-blink
</code></pre>
<p>The stm32-blink contains:</p>
<ul>
<li><p>Swift code that toggles GPIOs</p>
</li>
<li><p>A C startup file with vector table</p>
</li>
<li><p>A build.sh script that uses swiftc, clang, and a custom linker setup</p>
</li>
</ul>
<h3 id="heading-setup-the-stm32-board">Setup the STM32 Board</h3>
<p>Tell the build script which STM32 board is being used:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> STM_BOARD=STM32F746G_DISCOVERY
</code></pre>
<p>You can add your own board variant by defining the appropriate memory map and compiler flags in the script.</p>
<h3 id="heading-modify-buildsh-optional">Modify build.sh (Optional)</h3>
<p>Ensure the script correctly locates the following:</p>
<ul>
<li><p>swiftc: should point to the toolchain you installed with Swiftly</p>
</li>
<li><p>clang: can be macOS’s default Clang</p>
</li>
<li><p>libBuiltin.a, crt0.s, and macho2bin.py: used to provide minimal runtime support and convert output to flashable binaries</p>
</li>
</ul>
<p>If needed, update these paths:</p>
<pre><code class="lang-bash">SWIFT_EXEC=<span class="hljs-variable">${SWIFT_EXEC:-$(swiftly which swiftc)}</span>
CLANG_EXEC=<span class="hljs-variable">${CLANG_EXEC:-$(xcrun -f clang)}</span>
PYTHON_EXEC=<span class="hljs-variable">${PYTHON_EXEC:-$(which python3)}</span>
</code></pre>
<p>Ensure the linker flags match your target’s flash and RAM sizes.</p>
<h3 id="heading-build-and-flash-the-project">Build and Flash the Project:</h3>
<p>Run:</p>
<pre><code class="lang-bash">./build.sh
</code></pre>
<p>This compiles Swift and C code, links them, and produces a blink.bin file.</p>
<p>If successful, you’ll see:</p>
<pre><code class="lang-bash">.build/blink.bin  <span class="hljs-comment"># ready to flash Step 6: Flash the Firmware to STM32</span>
</code></pre>
<p>Use ST-Link tools or openocd to flash your board. Example using st-flash:</p>
<pre><code class="lang-bash">brew install stlink
st-flash write .build/blink.bin 0x8000000
</code></pre>
<p>You should now see an LED blinking.</p>
<p><a target="_blank" href="https://docs.swift.org/embedded/documentation/embedded/stm32baremetalguide">Here’s</a> a more detailed step by step approach to writing a bare metal code on STM32. For comprehensive installation guides covering other platforms (Raspberry Pi Pico, ESP32, nRF52), detailed IDE configuration, troubleshooting, and advanced examples, you can check out the official documentation:</p>
<ul>
<li><p>Complete Setup Guide: <a target="_blank" href="https://docs.swift.org/embedded/documentation/embedded/installembeddedswift/">Install Embedded Swift</a></p>
</li>
<li><p>Platform Examples: <a target="_blank" href="https://github.com/apple/swift-embedded-examples">Swift Embedded Examples Repository</a></p>
</li>
<li><p>Getting Started Tutorial: <a target="_blank" href="https://docs.swift.org/embedded/documentation/embedded">Embedded Swift on Microcontrollers</a></p>
</li>
</ul>
<p>Now that we’ve set up Embedded Swift and explored how to build and run an example project, let’s look at a critical real-world scenario: interfacing Swift with low-level C drivers.</p>
<h2 id="heading-c-swift-linkages">C-Swift Linkages</h2>
<p>In many embedded projects, low-level hardware drivers are written in C because of its close-to-metal control and widespread ecosystem support. Embedded Swift supports seamless interoperability with C, which lets you reuse existing C libraries and drivers, write hardware control logic in C, and implement higher-level application logic in Swift.</p>
<p>This hybrid model lets you combine Swift’s safety and productivity with C’s hardware-level control, with no runtime overhead or object translation.</p>
<p>Let’s walk through an example where a low-level sensor driver is implemented in C and the application logic is written in Swift.</p>
<h3 id="heading-c-header-file-sensordriverh">C Header File (sensor_driver.h):</h3>
<p>This C header file defines the public interface for a low-level sensor driver. It includes standard fixed-width integer types and declares four functions:</p>
<ul>
<li><p>sensor_init(): Initializes the hardware sensor</p>
</li>
<li><p>sensor_read_temperature() and sensor_read_humidity(): Read raw sensor values</p>
</li>
<li><p>sensor_delay_ms(): Delays execution for a given number of milliseconds</p>
</li>
</ul>
<p>This interface acts as a bridge between Swift and C. Swift will link to these functions by name, no wrappers or bindings required.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> SENSOR_DRIVER_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SENSOR_DRIVER_H</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdint.h&gt;</span></span>

<span class="hljs-comment">// Low-level sensor driver functions</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sensor_init</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>;
<span class="hljs-function"><span class="hljs-keyword">uint32_t</span> <span class="hljs-title">sensor_read_temperature</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>;
<span class="hljs-function"><span class="hljs-keyword">uint32_t</span> <span class="hljs-title">sensor_read_humidity</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sensor_delay_ms</span><span class="hljs-params">(<span class="hljs-keyword">uint32_t</span> milliseconds)</span></span>;

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
<h3 id="heading-c-implementation-sensordriverc">C Implementation (sensor_driver.c):</h3>
<p>This implementation assumes the sensor is memory-mapped at a fixed address (<code>0x40001000</code>). Each register, temperature, humidity, and control, is accessed by offset from that base address.</p>
<p>The <code>sensor_init</code>() function writes <code>0x01</code> to the control register, presumably enabling or starting the sensor hardware.</p>
<p>The <code>sensor_read_temperature()</code> method and <code>sensor_read_humidity()</code> method reads from memory-mapped registers and return the raw ADC values from the sensor.</p>
<p>The <code>sensor_delay_ms()</code> method performs a simple busy-wait loop using nop (no-operation) instructions to approximate a delay. This is suitable for short, coarse-grained delays in bare-metal contexts.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"sensor_driver.h"</span></span>

<span class="hljs-comment">// Hardware register addresses</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SENSOR_BASE_ADDR    0x40001000</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> TEMP_REG_OFFSET     0x00</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> HUMIDITY_REG_OFFSET 0x04</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> CONTROL_REG_OFFSET  0x08</span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sensor_init</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{
    <span class="hljs-comment">// Initialize sensor hardware</span>
    <span class="hljs-keyword">volatile</span> <span class="hljs-keyword">uint32_t</span>* control_reg = (<span class="hljs-keyword">volatile</span> <span class="hljs-keyword">uint32_t</span>*)(SENSOR_BASE_ADDR + CONTROL_REG_OFFSET);
    *control_reg = <span class="hljs-number">0x01</span>; <span class="hljs-comment">// Enable sensor</span>
}

<span class="hljs-function"><span class="hljs-keyword">uint32_t</span> <span class="hljs-title">sensor_read_temperature</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{
    <span class="hljs-keyword">volatile</span> <span class="hljs-keyword">uint32_t</span>* temp_reg = (<span class="hljs-keyword">volatile</span> <span class="hljs-keyword">uint32_t</span>*)(SENSOR_BASE_ADDR + TEMP_REG_OFFSET);
    <span class="hljs-keyword">return</span> *temp_reg;
}

<span class="hljs-function"><span class="hljs-keyword">uint32_t</span> <span class="hljs-title">sensor_read_humidity</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>{
    <span class="hljs-keyword">volatile</span> <span class="hljs-keyword">uint32_t</span>* humidity_reg = (<span class="hljs-keyword">volatile</span> <span class="hljs-keyword">uint32_t</span>*)(SENSOR_BASE_ADDR + HUMIDITY_REG_OFFSET);
    <span class="hljs-keyword">return</span> *humidity_reg;
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sensor_delay_ms</span><span class="hljs-params">(<span class="hljs-keyword">uint32_t</span> milliseconds)</span> </span>{
    <span class="hljs-comment">// Simple delay implementation</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint32_t</span> i = <span class="hljs-number">0</span>; i &lt; milliseconds * <span class="hljs-number">1000</span>; i++) {
        __asm__(<span class="hljs-string">"nop"</span>);
    }
}
</code></pre>
<h3 id="heading-swift-code-using-c-driver">Swift Code Using C Driver:</h3>
<p>To use these C functions from Swift, you declare them using <code>@_silgen_name</code>, which tells the Swift compiler to link directly to these symbol names at runtime.</p>
<p>The <code>SensorController</code> class encapsulates sensor-related logic. In its <code>init()</code> method, it calls the <code>sensor_init()</code> function defined in C to initialize the sensor hardware.</p>
<p>The <code>readSensors()</code> method reads the raw values from the C driver, converts them into human-readable units using helper functions, stores them internally, and returns the processed values.</p>
<p>The <code>convertTemperature()</code> and <code>convertHumidity()</code> conversion methods apply a basic linear formula to turn raw ADC values into temperature in Celsius and humidity in percentage, respectively. These formulas would be based on the specific sensor’s datasheet.</p>
<p>The <code>checkThresholds()</code> method applies simple threshold logic, a good example of where Swift’s readability and type safety shine. You could easily expand this logic to include error bounds, state machines, or alerts.</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Import C driver functions</span>

<span class="hljs-comment">/*
These declarations match the C function signatures exactly. 
They allow Swift to invoke the C functions as if they were native Swift functions 
— with zero overhead.
*/</span>
@_silgen_name(<span class="hljs-string">"sensor_init"</span>)
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sensor_init</span><span class="hljs-params">()</span></span>

@_silgen_name(<span class="hljs-string">"sensor_read_temperature"</span>)
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sensor_read_temperature</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">UInt32</span>

@_silgen_name(<span class="hljs-string">"sensor_read_humidity"</span>)
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sensor_read_humidity</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">UInt32</span>

@_silgen_name(<span class="hljs-string">"sensor_delay_ms"</span>)
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sensor_delay_ms</span><span class="hljs-params">(<span class="hljs-number">_</span> ms: UInt32)</span></span>

<span class="hljs-comment">// Swift sensor controller using C driver</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SensorController</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> lastTemperature: <span class="hljs-type">Float</span> = <span class="hljs-number">0.0</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> lastHumidity: <span class="hljs-type">Float</span> = <span class="hljs-number">0.0</span>

    <span class="hljs-keyword">init</span>() {
        <span class="hljs-comment">// Initialize the C driver</span>
        sensor_init()
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">readSensors</span><span class="hljs-params">()</span></span> -&gt; (temperature: <span class="hljs-type">Float</span>, humidity: <span class="hljs-type">Float</span>) {
        <span class="hljs-comment">// Read raw values from C driver</span>
        <span class="hljs-keyword">let</span> rawTemp = sensor_read_temperature()
        <span class="hljs-keyword">let</span> rawHumidity = sensor_read_humidity()

        <span class="hljs-comment">// Convert raw values to meaningful units in Swift</span>
        <span class="hljs-keyword">let</span> temperature = convertTemperature(rawValue: rawTemp)
        <span class="hljs-keyword">let</span> humidity = convertHumidity(rawValue: rawHumidity)

        <span class="hljs-comment">// Store for comparison</span>
        lastTemperature = temperature
        lastHumidity = humidity

        <span class="hljs-keyword">return</span> (temperature: temperature, humidity: humidity)
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">convertTemperature</span><span class="hljs-params">(rawValue: UInt32)</span></span> -&gt; <span class="hljs-type">Float</span> {
        <span class="hljs-comment">// Convert raw ADC value to Celsius</span>
        <span class="hljs-keyword">return</span> (<span class="hljs-type">Float</span>(rawValue) * <span class="hljs-number">3.3</span> / <span class="hljs-number">4095.0</span> - <span class="hljs-number">0.5</span>) * <span class="hljs-number">100.0</span>
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">convertHumidity</span><span class="hljs-params">(rawValue: UInt32)</span></span> -&gt; <span class="hljs-type">Float</span> {
        <span class="hljs-comment">// Convert raw ADC value to percentage</span>
        <span class="hljs-keyword">return</span> <span class="hljs-type">Float</span>(rawValue) * <span class="hljs-number">100.0</span> / <span class="hljs-number">4095.0</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">checkThresholds</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> {
        <span class="hljs-comment">// Swift logic for threshold checking</span>
        <span class="hljs-keyword">let</span> tempThreshold: <span class="hljs-type">Float</span> = <span class="hljs-number">25.0</span>
        <span class="hljs-keyword">let</span> humidityThreshold: <span class="hljs-type">Float</span> = <span class="hljs-number">60.0</span>

        <span class="hljs-keyword">return</span> lastTemperature &gt; tempThreshold || lastHumidity &gt; humidityThreshold
    }
}

<span class="hljs-comment">// Main application loop</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Never</span> {
    <span class="hljs-keyword">let</span> sensorController = <span class="hljs-type">SensorController</span>()

    <span class="hljs-keyword">while</span> <span class="hljs-literal">true</span> {
        <span class="hljs-comment">// Read sensors using Swift controller with C driver</span>
        <span class="hljs-keyword">let</span> readings = sensorController.readSensors()

        <span class="hljs-comment">// Process data with Swift's type safety and expressiveness</span>
        <span class="hljs-keyword">if</span> sensorController.checkThresholds() {
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"Warning: Temperature: \(readings.temperature)°C, Humidity: \(readings.humidity)%"</span>)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"Normal: Temperature: \(readings.temperature)°C, Humidity: \(readings.humidity)%"</span>)
        }

        <span class="hljs-comment">// Delay using C driver function</span>
        sensor_delay_ms(<span class="hljs-number">1000</span>) <span class="hljs-comment">// 1 second delay</span>
    }
}
</code></pre>
<p>The <code>func main()</code> is the main event loop standard for embedded systems. It creates the sensor controller, reads sensor data in a loop, checks thresholds, and prints results accordingly. The loop includes a delay (via the C driver) to avoid hammering the sensor continuously.</p>
<p>In an actual embedded context, instead of using <code>print()</code>, you might blink an LED, send UART messages, or log data to memory.</p>
<p>With Embedded Swift and C now working together, let’s explore what lies ahead. The next section outlines ongoing improvements, emerging use cases, and research directions that are shaping the future of Embedded Swift.</p>
<h2 id="heading-future-work">Future Work</h2>
<p>Embedded Swift is still a young but rapidly evolving technology. Its modern language features, type safety, and performance make it an attractive option for embedded development, and ongoing work is expanding its capabilities, reach, and ecosystem.</p>
<h3 id="heading-ongoing-improvements">Ongoing Improvements</h3>
<p><strong>Compiler Optimizations</strong>: The Swift compiler team is actively improving code generation for embedded targets, including:</p>
<ul>
<li><p>Reducing binary size</p>
</li>
<li><p>Minimizing ARC overhead</p>
</li>
<li><p>Improving static dispatch performance</p>
</li>
</ul>
<p><strong>Hardware Support</strong>: Embedded Swift can target a wide variety of ARM and RISC-V microcontrollers, which are popular for building industrial applications. Support for additional architectures is being developed.</p>
<p><strong>Tooling Enhancements</strong>: Tooling support for Embedded Swift is still evolving, but several community-driven and open-source efforts are making development more accessible:</p>
<ul>
<li><p><strong>Build Systems</strong>: The Swift Embedded Working Group provides example projects that adapt Swift Package Manager (SwiftPM) for cross-compilation. Custom linker scripts and build helpers are available for platforms like STM32 and nRF52.</p>
</li>
<li><p><strong>Debugging Support</strong>: Developers can debug Embedded Swift programs using existing tools like GDB or OpenOCD, provided the build includes appropriate debug symbols. While not yet officially streamlined, this approach enables step-through debugging on real hardware.</p>
</li>
<li><p><strong>IDE Integration</strong>: There is no official IDE support yet, but some developers use VSCode with Swift syntax highlighting and external build tasks. These setups are still manual but serve as early prototypes for embedded workflows.</p>
</li>
</ul>
<h3 id="heading-emerging-use-cases">Emerging Use Cases</h3>
<p>There are a number of emerging use cases for embedded Swift. For example, Swift’s memory safety, type guarantees, and protocol-oriented design make it ideal for secure and scalable IoT devices, especially where firmware bugs could affect user safety or privacy.</p>
<p>The automotive sector is also exploring Swift for infotainment systems, driver assistance features, and safety-critical logic (where deterministic execution and safety matter).</p>
<p>Swift’s expressive syntax and compile-time safety make it suitable for industrial automation – think real-time control loops, sensor fusion systems, and edge devices in smart manufacturing.</p>
<p>It’s also useful for medical devices, as it aligns well with strict medical regulations around memory safety, type guarantees, and predictable resource usage.</p>
<h3 id="heading-community-and-ecosystem">Community and Ecosystem</h3>
<h4 id="heading-open-source-projects">Open Source Projects</h4>
<p>The Swift Embedded working group maintains <a target="_blank" href="https://github.com/swiftlang/swift-embedded-examples">example repositories</a> showcasing how to use Embedded Swift on microcontrollers such as STM32, nRF52, and ESP32. Early-stage libraries for UART, GPIO, and basic peripherals are emerging, though the ecosystem is still young compared to C or Rust.</p>
<h4 id="heading-learning-resources">Learning Resources</h4>
<p>While <a target="_blank" href="https://docs.swift.org/embedded/documentation/embedded">Embedded Swift</a> is not yet widely taught in formal curricula, community tutorials and exploratory projects (for example, Swift for Arduino) are lowering the barrier for hobbyists and independent learners. As tooling matures, educational adoption is likely to follow.</p>
<h4 id="heading-industry-interest">Industry Interest</h4>
<p>Embedded Swift is beginning to draw attention from developers and companies looking for safer, more maintainable alternatives to C. Although large-scale adoption remains limited, use cases like rapid prototyping, IoT development, and internal experimentation are gaining traction.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Embedded Swift represents a major step forward in embedded programming. By combining the power and safety of Swift with the low-level control needed for microcontrollers, it offers an exciting alternative to traditional C and C++ development.</p>
<p>While C will remain essential for hardware-level programming and performance-critical paths, Swift brings compelling advantages to many embedded scenarios:</p>
<ul>
<li><p><strong>Memory safety</strong>: Swift eliminates entire categories of bugs such as buffer overflows, use-after-free, and null pointer dereferencing.</p>
</li>
<li><p><strong>Type safety</strong>: Many logic errors are caught at compile time, long before they can cause runtime failures.</p>
</li>
<li><p><strong>Modern language features</strong>: Developers can use functional paradigms, generics, and protocol-oriented design even in embedded code.</p>
</li>
<li><p><strong>C interoperability</strong>: Swift works seamlessly with existing C libraries, allowing gradual adoption without rewriting low-level drivers.</p>
</li>
<li><p><strong>Developer productivity</strong>: Clear syntax, automatic memory management, and strong tooling lead to faster development and easier maintenance.</p>
</li>
</ul>
<p>Government and regulatory bodies are increasingly encouraging or mandating the use of memory-safe programming languages to reduce vulnerabilities in critical software systems. For example:</p>
<ul>
<li><p>In 2022, the <a target="_blank" href="https://media.defense.gov/2025/Jun/23/2003742198/-1/-1/0/CSI_MEMORY_SAFE_LANGUAGES_REDUCING_VULNERABILITIES_IN_MODERN_SOFTWARE_DEVELOPMENT.PDF"><strong>U.S. National Security Agency (NSA)</strong></a> recommended moving away from unsafe languages like C/C++ for new software projects, promoting memory-safe alternatives.</p>
</li>
<li><p>In June 2025, the NSA and CISA released a joint Cybersecurity Information Sheet titled “<a target="_blank" href="https://www.nsa.gov/Press-Room/Press-Releases-Statements/Press-Release-View/Article/4223298/nsa-and-cisa-release-csi-highlighting-importance-of-memory-safe-languages-in-so/">Memory Safe Languages: Reducing Vulnerabilities in Modern Software Development</a>”, which emphasized that memory safety flaws remain a persistent risk, and organizations should develop strategies to adopt memory-safe programming languages in new systems.</p>
</li>
<li><p>The <a target="_blank" href="https://www.trust-in-soft.com/resources/blogs/memory-safety-is-key-the-shift-in-u.s.-cyber-standards"><strong>U.S. Cybersecurity and Infrastructure Security Agency (CISA)</strong></a> and <a target="_blank" href="https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-218.pdf"><strong>NIST</strong></a> have echoed similar guidance in the context of national cybersecurity.</p>
</li>
</ul>
<p>While these documents do not mention Swift explicitly, Swift's strong type system, ARC-based memory model, and compile-time safety guarantees align closely with the goals outlined in these recommendations. As such, it offers a practical, developer-friendly path toward safer embedded development.</p>
<p>Swift may not be the right fit for every embedded system. In applications where every byte of memory or instruction cycle is critical, real-time guarantees are hard requirements, or toolchain maturity is essential (for example, RTOS integration, static analyzers), C or Rust may still be preferred.</p>
<p>But in many modern embedded applications, especially those involving rapid prototyping, fast product iteration, safety-critical or maintainable firmware, and interoperability with existing C codebases, Swift offers a highly productive and safe development experience.</p>
<p>Embedded Swift is still maturing, but its momentum is undeniable. With ongoing compiler work, community-driven examples, and growing interest from developers, it’s poised to play a major role in the future of embedded systems.</p>
<p>Whether you're building an IoT device, a piece of industrial equipment, or a proof-of-concept wearable, Swift can help you write safer, more expressive firmware, without giving up performance or control.</p>
<p>Swift can be especially powerful during the prototyping phase, when the primary goal is to validate functionality quickly and safely. And with its increasing support for multiple hardware platforms, it offers a strong foundation for bringing modern software development practices to the embedded world.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Robust Networking Layers in Swift with OpenAPI ]]>
                </title>
                <description>
                    <![CDATA[ What is the Problem We’re Solving? For many app developers, including me, writing the networking layer of an application is a familiar and tedious process. You write and test your first call and after that, it involves a repetitive cycle of tasks. Th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-robust-networking-layers-in-swift-with-openapi/</link>
                <guid isPermaLink="false">687fd1a603524e3b4e7b77fe</guid>
                
                    <category>
                        <![CDATA[ OpenApi ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ openapi generator ]]>
                    </category>
                
                    <category>
                        <![CDATA[ OpenAPI Specification ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SwiftUI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sravan Karuturi ]]>
                </dc:creator>
                <pubDate>Tue, 22 Jul 2025 18:00:06 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753206547489/dce9a849-1ccd-4cb0-bca8-f879a5aadf5f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-is-the-problem-were-solving"><strong>What is the Problem We’re Solving?</strong></h2>
<p>For many app developers, including me, writing the networking layer of an application is a familiar and tedious process. You write and test your first call and after that, it involves a repetitive cycle of tasks.</p>
<p>This is how it would look in the case of Swift:</p>
<ol>
<li><p>You create a <code>URLSession</code> Instance.</p>
</li>
<li><p>You create a <code>URLRequest</code> Object.</p>
</li>
<li><p>You create the <code>@Codable</code> models to match the expected input and output from the server.</p>
</li>
</ol>
<p>You do the above steps for each API endpoint you have on your backend that your app uses. Not only is this process time-consuming and not challenging for developers, it’s also error prone. </p>
<p>In the above case, if there was a minor change in the backend API – perhaps a renamed field or a new property – this would lead to the app potentially breaking. But you wouldn’t know this until you shipped it to QA or in a worse case, your consumer. This is where the OpenAPI Specification emerges as a modern, robust solution. </p>
<p>In this tutorial, you’ll learn what OpenAPI is and how it can help make your development process better. After that, we’ll implement OpenAPI by creating a small SwiftUI app and using OpenAPI methodologies to interface with the <code>JSONPlaceholder</code> API. Let’s get started.</p>
<h2 id="heading-who-is-this-guide-for"><strong>Who is This Guide For?</strong></h2>
<p>This guide is intended both for new developers looking for best practices and for experienced developers looking to implement or learn more about the OpenAPI Specification. Let’s get into it.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-openapi-and-why-should-you-care">What is OpenAPI and Why Should You Care?</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-benefits-for-swift-ios-developers">Benefits for Swift (iOS) Developers</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-a-practical-guide-to-implementing-this-solution">A Practical Guide to Implementing This Solution</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-create-a-good-openapiyaml-file-the-specification">Step 1: Create a good openapi.yaml file (the specification)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-set-up-your-project">Step 2: Set up your project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-write-a-wrapper">Step 3: Write a wrapper</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-call-the-wrapper-and-display-the-data">Step 4: Call the wrapper and display the data</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-potential-pitfalls">Potential Pitfalls</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-verbose-or-ugly-generated-code">Verbose or ugly generated code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-large-specs-and-performance-issues">Large Specs and Performance Issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-unsupported-spec-features">Unsupported Spec Features</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion-embrace-spec-driven-development">Conclusion: Embrace Spec-Driven Development</a></p>
</li>
</ul>
<h2 id="heading-what-is-openapi-and-why-should-you-care"><strong>What is OpenAPI and Why Should You Care?</strong></h2>
<p>At its core, the OpenAPI Specification provides a <em>standard, language-agnostic interface</em> for describing RESTful APIs. This specification, once populated, allows both humans and computers to discover and understand the capabilities of a service without needing to access the source code or the network requests.</p>
<p>The power of OpenAPI is that it acts as a <em>formal contract between different parts of the system.</em> This contract helps both frontend and backend programmers by removing ambiguity during design process. This also has added benefit of using code generators to generate boiler-plate code both on backend and on the client ( which we will also discuss today ).</p>
<p>Traditionally when you want to create a new API in a team, either the PM, the frontend engineer, or the backend engineer takes it upon themselves to request it. Then the backend team builds it and documents it. This in turn is used by the front end team to use the API. </p>
<p><code>Some Requester → Backend Team → Documentation → Frontend Team</code></p>
<p>If you’re using OpenAPI, when someone makes a request for a new API, it is formalized into a specification after deliberations with both the frontend and the backend team. This then serves as the source of truth and is used to generate the backend and the frontend code without as much interdependence.</p>
<p><code>Some Requester → All Teams → Specification → All Teams.</code></p>
<p>This not only streamlines the process of adding new APIs, but provides a definitive source of truth for each endpoint. This also makes it so that frontend engineers and backend engineers are not misaligned about a provided parameter in the result being an <code>Int</code> or a <code>String</code> and so on. <strong>It’s all in the Spec.</strong></p>
<h3 id="heading-benefits-for-swift-ios-developers"><strong>Benefits for Swift (iOS) Developers</strong></h3>
<p>Adopting OpenAPI and <code>swift-openapi-generator</code> brings a host of tangible benefits to the Swift/App development process. It transforms how applications interact with web services in a few key ways.</p>
<h4 id="heading-reduced-development-time-and-cost">Reduced Development Time and Cost</h4>
<p>The most immediate improvement you will see is the significant reduction in boilerplate code you have to write. The generator automates the creation of what is called boilerplate code or ceremonial code. This is the repetitive logic for network requests, response handling, and data model definitions.</p>
<p>By delegating this work, developers can work on the core features of the application which leads to faster and more interesting development cycles.</p>
<h4 id="heading-compile-time-type-safety">Compile Time Type Safety</h4>
<p>This has been a major improvement for me personally. Instead of relying on the “strongly” typed keys for JSON parsing, we now work with strongly typed models. The generator creates native Swift struct and enum types directly from the schemas defined in the OpenAPI document. This brings the power of a strongly-typed system to the networking and parsing layer.</p>
<p>For example, if the return value of an API is made optional, instead of crashing at runtime, we will fail to compile at build time. This forces us to address this issue right away. </p>
<h4 id="heading-improved-collaboration-and-interoperability">Improved Collaboration and Interoperability</h4>
<p>This makes sure that all the developers are on the same page with regard to a given endpoint. And since this specification is language agnostic, it will serve as a universal language for all teams involved in the project – mobile, web and backend. </p>
<h4 id="heading-other-tooling">Other Tooling</h4>
<p>Once you have a specification, you can use that to power a wide variety of tools. You can generate interactive documentation, create mock servers for frontend development, and run automated tests. </p>
<p>Alright hopefully you’re sold – so now how do you implement this into your project?</p>
<h2 id="heading-a-practical-guide-to-implementing-this-solution">A Practical Guide to Implementing This Solution</h2>
<p>We’ll now take a look at a practical example so you can understand how you can implement this in a project. This involves:</p>
<ul>
<li><p>Creating an openapi.yaml file to describe the API specification.</p>
</li>
<li><p>Configuring and integrating <code>swift-openapi-generator</code> into a SwiftUI application. </p>
</li>
<li><p>Prototyping an app that fetches and displays a list of posts from the <a target="_blank" href="https://jsonplaceholder.typicode.com/">https://jsonplaceholder.typicode.com/</a> </p>
</li>
</ul>
<p>To follow along, you will need Xcode installed and a basic understanding of Swift programming and SwiftUI for App development.</p>
<h3 id="heading-step-1-create-a-good-openapiyaml-file-the-specification">Step 1: Create a good openapi.yaml file (the specification)</h3>
<p>The quality of a specification is really important because it directly determines the quality of the code produced by <code>swift-openapi-generator</code>. If you don’t have a good specification, you might run into several issues that developers often complain about, like confusing and long method names.</p>
<p>For example, it might generate something like <code>get_all_my_meal_recipes_hyphen_detailed</code>. This might happen because the generator is forced to create a new name based on the API path if the identifier is not provided in the spec. So, instead of dealing with these issues one after the other, we will create a <em>good clear specification</em> to start with.</p>
<p>Since we’re using the <code>jsonplaceholder</code> as our backend server, we are limited by what tweaks we can make – but it is a fantastic project that lets us mimic a backend server.</p>
<p>In general, an OpenAPI.yaml file contains:</p>
<ol>
<li><p>OpenAPI Info and servers – This will provide the metadata about the API like the OpenAPI version, which server to point to for calls, and so on. </p>
</li>
<li><p>Paths – This will provide the available endpoints. In our case, it can contain /posts as one of them. We also will have to mention the kind of endpoint (get, post, put, and so on)</p>
</li>
<li><p>OperationID – This field instructs the generator to create a clear method with this name. </p>
</li>
<li><p>Responses – This defines the possible outcomes of an API call. We will specify the structure of a successful 200 OK response or any other errors here. </p>
</li>
<li><p>Components / Schemas – This defines all the reusable components and data models. If we have a Post schema definer here, the generator will use this to create a Post struct in Swift to match this. </p>
</li>
</ol>
<p>Keeping in mind all these elements, I compiled a yaml file for us to use for this tutorial:</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># openapi.yaml</span>
<span class="hljs-attr">openapi:</span> <span class="hljs-string">"3.0.3"</span>
<span class="hljs-attr">info:</span>
  <span class="hljs-attr">title:</span> <span class="hljs-string">"JSONPlaceholder API"</span>
  <span class="hljs-attr">version:</span> <span class="hljs-string">"1.0.0"</span>
<span class="hljs-attr">servers:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">url:</span> <span class="hljs-string">"https://jsonplaceholder.typicode.com"</span>
<span class="hljs-attr">paths:</span>
  <span class="hljs-string">/posts:</span>
    <span class="hljs-attr">get:</span>
      <span class="hljs-attr">summary:</span> <span class="hljs-string">"Get all posts"</span>
      <span class="hljs-attr">operationId:</span> <span class="hljs-string">"getPosts"</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">"200":</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">"A list of posts"</span>
          <span class="hljs-attr">content:</span>
            <span class="hljs-attr">application/json:</span>
              <span class="hljs-attr">schema:</span>
                <span class="hljs-attr">type:</span> <span class="hljs-string">array</span>
                <span class="hljs-attr">items:</span>
                  <span class="hljs-string">$ref:</span> <span class="hljs-string">"#/components/schemas/Post"</span>
<span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">Post:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">required:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">userId</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">id</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">title</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">body</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">userId:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">integer</span>
        <span class="hljs-attr">id:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">integer</span>
        <span class="hljs-attr">title:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">body:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
</code></pre>
<p>The first line here, <code>openapi: “3.0.3”</code>, just tells the generators and parsers that we are using version <code>3.0.3</code>. </p>
<p>Next, we have some more metadata – the name and version of the API. We also have the server we are calling with our APIs.</p>
<p>After defining this metadata, we now define our endpoints. For the sake of this example, let’s assume that we only have one endpoint to call to get posts. We represent this by saying <code>/posts</code> under paths. We then specify which kind it is by specifying <code>get:</code>.</p>
<p>We give a short description of what it does in the <code>summary</code> and then specify an <code>operationId</code> which is what we this function will be called in our generated code. We also specify exactly what structure the response will have, that is, a JSON of an array of <code>Posts</code>.</p>
<p>We then list any components we have across our APIs like the <code>Post</code>. Note that we are using the <code>Post</code> schema in the return response structure before we define it further down. The schemas in components will determine the Model structs we will generate using this yaml file.</p>
<h3 id="heading-step-2-set-up-your-project">Step 2: Set up your project</h3>
<p>Create a new SwiftUI project. For the purpose of this tutorial, we’ll use an iOS app – but you can do this with any app. Select Swift as the language and SwiftUI for the interface.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047209636/75cad7d3-f403-4285-8209-fd2bb65418e5.png" alt="App Creation Screen" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047246793/3491aa5d-c35c-4157-adf2-789fe5e9cd96.png" alt="Basic SwiftUI App after it's created" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p>Add the <code>openapi.yaml</code> file we just created to this project. (You can also create this file in Xcode and copy, paste from the script above.)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047290178/fc31b759-b1c4-4b48-b58b-d90109614cd0.png" alt="Adding the openapi.yaml file to our project" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p>Now, add the following swift packages to the project. (<strong>Note: Please read the entire section about adding packages before you proceed.</strong>)</p>
<ol>
<li><p>Swift OpenAPI Generator – <a target="_blank" href="https://github.com/apple/swift-openapi-generator">https://github.com/apple/swift-openapi-generator</a> – The Core Generator Plugin.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047376776/b1d7b2d0-9b1f-45c8-8c74-4395a4c80dd9.png" alt="Adding Swift OpenAPI Generator to our Project" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047411622/c6eca0c0-538e-40b5-a9b0-9fa044b60694.png" alt="Making sure that no targets are selected for the OpenAPIGenerator" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
</li>
<li><p>Swift OpenAPI Runtime – <a target="_blank" href="https://github.com/apple/swift-openapi-runtime">https://github.com/apple/swift-openapi-runtime</a> – This contains the common types and protocols used by the code generated by the generator plugin.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047457532/846ec488-cfed-4ca5-811b-c38dba0aaf30.png" alt="Adding OpenAPIRuntime to our project" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
</li>
<li><p>Swift OpenAPI URLSession – <a target="_blank" href="https://github.com/apple/swift-openapi-urlsession">https://github.com/apple/swift-openapi-urlsession</a> – This is a transport layer that allows the generated code to use the Apple URLSession to make network requests. </p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753047476699/9556047e-cc33-44b4-9980-0c692d4c1d01.png" alt="Adding OpenAPIURLSession to our Project" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
</li>
</ol>
<p>One major caveat to note here when adding these packages is that <strong>The Swift OpenAPI Generator</strong> should <strong>not</strong> be added to your project target. This is because we’re only using this to generate the code, but we’re not using it in the app.</p>
<p>If you get this error: <code>swift-openapi-generator/Sources/_OpenAPIGeneratorCore/PlatformChecks.swift:21:5 _OpenAPIGeneratorCore is only to be used by swift-openapi-generator itself—your target should not link this library or the command line tool directly.</code> – then you made this mistake.</p>
<p>The easiest way to fix this is removing the package and adding it again. Or you can go to <code>Project → Target → Build Phases → Link Binary with Libraries → Remove Swift OpenAPI Generator</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753048265985/100428a4-e46a-4aa1-8fcf-4c74e26ffed6.png" alt="Where to check if you encounter that error" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p>Now that we added these generator and runtime plugins, we need to give the generator some instructions on what to generate. You can do this with an <code>openapi-generator-config.yaml</code> file. For our project, use the following file. It’s really simple:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">generate:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">types</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">client</span>
</code></pre>
<p>This tells our generator to generate the <strong>types</strong> – the swift structs, enums, and so on from the schema section of the file, and the <strong>client</strong> – the main class which interacts with the networking logic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753048237863/963d6bc0-a368-427b-add3-75dcf4bd3edf.png" alt="openapi-generator-config.yaml file" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p>Save this into an <code>openapi-generator-config.yaml</code> file as shown.</p>
<p>And finally, we want the generator to run whenever we want to build this application/target. We can specify this in the Build Phases tab of the target. Under the “ Target → Build Phases → Run Build Tool Plug-ins” , add the OpenAPIGenerator Plugin.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753048334094/24e20adc-c6e0-4d66-965b-19d476a5ffd3.png" alt="Adding the generator in the build phase" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p>The first time the project is built after setting this, Xcode will display a security dialog. This will let us “Trust and Enable” for this plugin. It’s a one time confirmation that gives this plugin the permission required to run during the build process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753048374405/6ff51ff4-d33a-4920-b95f-9fda0ee0aef4.png" alt="Trust and Enable security dialog for the generator" class="image--center mx-auto" width="1512" height="1012" loading="lazy"></p>
<p>As soon as you build the second time after giving these permissions, you will generate the files. You might not see any changes in the Xcode window itself. But if you’re curious to see the result, go to this folder. </p>
<p><code>DerivedData →  &lt;ProjectName&gt;*identifier → Build → intermediates.noindex → BuildToolPluginIntermediates → &lt;TargetName&gt;.output → &lt;TargetName&gt; → OpenAPIGenerator → GeneratedSources</code></p>
<p>More on derived data folder here: <a target="_blank" href="https://gayeugur.medium.com/derived-data-2e9468c6da9b">https://gayeugur.medium.com/derived-data-2e9468c6da9b</a> if you’re curious.</p>
<p>Keep in mind that this location might vary based on Xcode version, OpenAPI version, and your project settings. But you don’t need to worry about the file location.</p>
<p>You will see three files called Client.swift, Types.swift, and Server.swift.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753048508703/8fcec6bf-ad86-47de-b57c-7dca22256e06.png" alt="Generated Files" class="image--center mx-auto" width="1148" height="710" loading="lazy"></p>
<p>These are the files that the our generator created and populated with the types and functions we need.</p>
<p>In the next section, we discuss how to use these files to make calls to the server.</p>
<h3 id="heading-step-3-write-a-wrapper">Step 3: Write a wrapper</h3>
<p>While it’s certainly possible to make the calls to server using just the generated code (<code>Client</code>) type throughout our application, a more maintainable approach is to use a wrapper around these types. This will provide a stable, clean interface for the rest our our app to use, and it decouples feature code from the generated code.</p>
<p>I can hear you thinking: “Wait a second. Isn’t the entire purpose of generating this code to avoid this boilerplate abstraction?”</p>
<p>While it adds some abstraction on top of the generated code, it’s valuable to have this for number of reasons. Here are but a few of them:</p>
<ol>
<li><p>Better naming. The generated <code>Post</code> struct right now will be called <code>Components.Schemas.Post</code>.</p>
</li>
<li><p>If you ever want to move away from the generator, an abstraction is really helpful.</p>
</li>
<li><p>If you want to Mock this server call, you can do this via the abstraction.</p>
</li>
<li><p>UI Optimization. You might want to flatten the structure of a model to reduce the number of computed variables in there, and so on.</p>
</li>
</ol>
<p>So, we want to wrap this around a file called <code>WebService.swift</code>:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// WebService.swift</span>
<span class="hljs-keyword">import</span> Foundation
<span class="hljs-keyword">import</span> OpenAPIURLSession

<span class="hljs-comment">// A clean, app-specific Post model.</span>
<span class="hljs-comment">// This decouples views from the generated types.</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">AppPost</span>: <span class="hljs-title">Identifiable</span>, <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> body: <span class="hljs-type">String</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebService</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> client: <span class="hljs-type">Client</span>

    <span class="hljs-keyword">init</span>() {
        <span class="hljs-comment">// The server URL and transport are from the generated code.</span>
        <span class="hljs-comment">// `Servers.Server1.url()` corresponds to the first URL in the `servers` array of the spec.</span>
        <span class="hljs-keyword">self</span>.client = <span class="hljs-type">Client</span>(
            serverURL: <span class="hljs-keyword">try</span>! <span class="hljs-type">Servers</span>.<span class="hljs-type">Server1</span>.url(),
            transport: <span class="hljs-type">URLSessionTransport</span>()
        )
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getPosts</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">AppPost</span>] {
        <span class="hljs-comment">// Call the generated method, which was named using `operationId`.</span>
        <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">try</span> await client.getPosts(.<span class="hljs-keyword">init</span>())

        <span class="hljs-comment">// The generated response is a type-safe enum covering all documented status codes.</span>
        <span class="hljs-keyword">switch</span> response {
        <span class="hljs-keyword">case</span>.ok(<span class="hljs-keyword">let</span> okResponse):
            <span class="hljs-comment">// The body is also a type-safe enum for different content types.</span>
            <span class="hljs-keyword">switch</span> okResponse.body {
            <span class="hljs-keyword">case</span>.json(<span class="hljs-keyword">let</span> posts):
                <span class="hljs-comment">// Map the generated `Components.Schemas.Post` to our clean `AppPost` model.</span>
                <span class="hljs-keyword">return</span> posts.<span class="hljs-built_in">map</span> { post <span class="hljs-keyword">in</span>
                    <span class="hljs-type">AppPost</span>(id: post.id, title: post.title, body: post.body)
                }
            }
        <span class="hljs-comment">// The generator forces the handling of other documented responses.</span>
        <span class="hljs-comment">// Our simple spec only has a 200, so any other response is undocumented.</span>
        <span class="hljs-keyword">case</span>.undocumented(statusCode: <span class="hljs-keyword">let</span> statusCode, <span class="hljs-number">_</span>):
            <span class="hljs-keyword">throw</span> <span class="hljs-type">URLError</span>(.badServerResponse, userInfo: [<span class="hljs-string">"statusCode"</span>: statusCode])
        }
    }
}
</code></pre>
<p>Let’s go through this file to understand what we’re doing.</p>
<p>First, we import <code>OpenAPIUrlSession</code> along with <code>Foundation</code>. This allows us to call the server, get a response and parse that response.</p>
<p>Next, we define the new <code>AppPost</code> struct. This is meant to be the representation of a <code>Post</code> in the App. In the generated <code>Types.Swift</code> file, we have the generated <code>Post</code> structure. This is defined as:</p>
<pre><code class="lang-swift"><span class="hljs-comment">/// - Remark: Generated from `#/components/schemas/Post`.</span>
        <span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Post</span>: <span class="hljs-title">Codable</span>, <span class="hljs-title">Hashable</span>, <span class="hljs-title">Sendable</span> </span>{
            <span class="hljs-comment">/// - Remark: Generated from `#/components/schemas/Post/userId`.</span>
            <span class="hljs-keyword">internal</span> <span class="hljs-keyword">var</span> userId: <span class="hljs-type">Swift</span>.<span class="hljs-type">Int</span>
            <span class="hljs-comment">/// - Remark: Generated from `#/components/schemas/Post/id`.</span>
            <span class="hljs-keyword">internal</span> <span class="hljs-keyword">var</span> id: <span class="hljs-type">Swift</span>.<span class="hljs-type">Int</span>
            <span class="hljs-comment">/// - Remark: Generated from `#/components/schemas/Post/title`.</span>
            <span class="hljs-keyword">internal</span> <span class="hljs-keyword">var</span> title: <span class="hljs-type">Swift</span>.<span class="hljs-type">String</span>
            <span class="hljs-comment">/// - Remark: Generated from `#/components/schemas/Post/body`.</span>
            <span class="hljs-keyword">internal</span> <span class="hljs-keyword">var</span> body: <span class="hljs-type">Swift</span>.<span class="hljs-type">String</span>
            <span class="hljs-comment">/// Creates a new `Post`.</span>
            <span class="hljs-comment">///</span>
            <span class="hljs-comment">/// - Parameters:</span>
            <span class="hljs-comment">///   - userId:</span>
            <span class="hljs-comment">///   - id:</span>
            <span class="hljs-comment">///   - title:</span>
            <span class="hljs-comment">///   - body:</span>
            <span class="hljs-keyword">internal</span> <span class="hljs-keyword">init</span>(
                userId: <span class="hljs-type">Swift</span>.<span class="hljs-type">Int</span>,
                id: <span class="hljs-type">Swift</span>.<span class="hljs-type">Int</span>,
                title: <span class="hljs-type">Swift</span>.<span class="hljs-type">String</span>,
                body: <span class="hljs-type">Swift</span>.<span class="hljs-type">String</span>
            ) {
                <span class="hljs-keyword">self</span>.userId = userId
                <span class="hljs-keyword">self</span>.id = id
                <span class="hljs-keyword">self</span>.title = title
                <span class="hljs-keyword">self</span>.body = body
            }
            <span class="hljs-keyword">internal</span> <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">CodingKeys</span>: <span class="hljs-title">String</span>, <span class="hljs-title">CodingKey</span> </span>{
                <span class="hljs-keyword">case</span> userId
                <span class="hljs-keyword">case</span> id
                <span class="hljs-keyword">case</span> title
                <span class="hljs-keyword">case</span> body
            }
        }
</code></pre>
<p>As you can see, our <code>AppPost</code> struct is different from this generated type. We omit the <code>userId</code> since we do not care about it (at least for now).</p>
<p>Back to the <code>WebService</code> class, we see a <code>client</code> attribute. This is a generated type variable that will let us interact with the servers. In the initializer of the <code>WebService</code> class, we create a new <code>Client</code> using the first server URL we specified in the schema and use the <code>URLSessionTransport</code> object for making these calls.</p>
<p>We then define our methods. In this case, our <code>getPosts()</code> function which returns <code>[AppPost]</code> array.</p>
<p><code>let response = try await client.getPosts(.init())</code> will call the function <code>getPosts()</code> on the <code>Client</code> object. The <code>Client.getPosts()</code> function here takes in an input struct called <code>Operations.getPosts.Input</code> which is initialized by the <code>.init()</code> passed here.</p>
<p>This generated response is a type-safe enum covering all documented codes. (Currently only <code>200</code> in our yaml file). So, we use a simple switch to look at both these cases and further use more switch statements to get the proper response. You can see how much easier this is than to parse the response manually.</p>
<p>Once we get the <code>Components.Schemas.Post</code> response, we map and convert it into <code>[AppPost]</code> array and return it.</p>
<p>Now, let’s use this wrapper to display data in our app.</p>
<h3 id="heading-step-4-call-the-wrapper-and-display-the-data">Step 4: Call the wrapper and display the data</h3>
<p>We’re at the final step now. We’ll use the wrapper we created to display the fetched posts. We’ll also use a state variable to store our <code>AppPost</code> array in our <code>ContentView</code> view. We’ll then call <code>getPosts()</code> when the view is first displayed to the user.</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ContentView.swift</span>
<span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView</span>: <span class="hljs-title">View</span> </span>{
    @<span class="hljs-type">State</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> posts: [<span class="hljs-type">AppPost</span>] = []
    @<span class="hljs-type">State</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> errorMessage: <span class="hljs-type">String?</span>

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> webService = <span class="hljs-type">WebService</span>()

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">NavigationStack</span> {
            <span class="hljs-type">List</span>(posts) { post <span class="hljs-keyword">in</span>
                <span class="hljs-type">VStack</span>(alignment:.leading, spacing: <span class="hljs-number">8</span>) {
                    <span class="hljs-type">Text</span>(post.title)
                       .font(.headline)
                    <span class="hljs-type">Text</span>(post.body)
                       .font(.subheadline)
                       .foregroundColor(.secondary)
                }
               .padding(.vertical, <span class="hljs-number">4</span>)
            }
           .navigationTitle(<span class="hljs-string">"Posts"</span>)
           .task {
                await loadPosts()
            }
           .overlay {
                <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> errorMessage {
                    <span class="hljs-type">ContentUnavailableView</span>(<span class="hljs-string">"Error"</span>, systemImage: <span class="hljs-string">"xmark.octagon"</span>, description: <span class="hljs-type">Text</span>(errorMessage))
                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> posts.isEmpty {
                    <span class="hljs-type">ProgressView</span>()
                }
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">loadPosts</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">self</span>.errorMessage = <span class="hljs-literal">nil</span>
        <span class="hljs-keyword">do</span> {
            <span class="hljs-keyword">self</span>.posts = <span class="hljs-keyword">try</span> await webService.getPosts()
        } <span class="hljs-keyword">catch</span> {
            <span class="hljs-keyword">self</span>.errorMessage = error.localizedDescription
        }
    }
}

#<span class="hljs-type">Preview</span> {
    <span class="hljs-type">ContentView</span>()
}
</code></pre>
<p>You can see the dummy posts in the Preview. As you can see, all we had to do was call the <code>webService.getPosts()</code> to populate the variable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753053957409/b89d50e8-ab73-4484-beda-3a328a575144.png" alt="Simulator Run of the app showing the fetched posts" class="image--center mx-auto" width="1179" height="2556" loading="lazy"></p>
<p>You might be thinking that this is a lot of setup for a simple struct like <code>Post</code> for which we had to create a wrapper called <code>AppPost</code> anyway. But if you had ten types like this and twenty endpoints to call? You wouldn’t have to deal with a lot of repetitive, error-prone code.</p>
<h2 id="heading-potential-pitfalls">Potential Pitfalls</h2>
<p>Unfortunately, no process is perfect. You might still face a lot of issues with generated code and this method. I’ve listed some of them here and how to deal with them.</p>
<h3 id="heading-verbose-or-ugly-generated-code">Verbose or ugly generated code</h3>
<p>If you have very verbose or ugly generated code, the problem is almost always the missing <code>operationId</code> for an API path. If you don’t specify one, the generator must create a name from the path and the HTTP method with results in long unwieldy names. Adding a clear <code>operationId</code> will mitigate this issue.</p>
<h3 id="heading-large-specs-and-performance-issues">Large Specs and Performance Issues</h3>
<p>If you have a very large Spec file, generating a client for this entire specification can significantly increase the compile time. It can also result in absolutely massive <code>Types.swift</code> and <code>Client.swift</code> files.</p>
<p>There is a filter option in the <code>openapi-generator-config.yaml</code> file that will allow the generator to include only parts of the spec that are relevant to the application to improve build times and so on. But if you want everything in an API that has hundreds of endpoints, the only way to reduce compile times is to avoid regenerating this every time and decouple this step from the regular build process.</p>
<h3 id="heading-unsupported-spec-features">Unsupported Spec Features</h3>
<p>While the swift package, <code>swift-openapi-generator</code>, is robust, it does not support all the features included in the specification. I had issues with some features of the newer spec version ( <code>3.1.1</code> and had to downgrade to <code>3.0.3</code> to make it work well ).</p>
<p>There are also known issues like lack of support for certain types of recursive schemas. Sometimes, the generator errors out and fails and some other times, it generates incomplete types – which can result in a few hours of debugging (I speak from experience).</p>
<p>In any case, knowing the limits of this generator can be helpful in avoiding issues it might cause. Also keep in mind that it is always getting better thanks to its open source nature.</p>
<h2 id="heading-conclusion-embrace-spec-driven-development">Conclusion: Embrace Spec-Driven Development</h2>
<p>In this guide, you navigated the journey of adopting <code>swift-openapi-generator</code> – from understanding the power of API contracts to building a functional SwiftUI app. You also learned about the real life challenges of this process. While there is an initial learning curve, the benefits of this approach are profound.</p>
<p>The core tenet of this approach is to foster more disciplined and more robust method for building applications. By making the OpenAPI document the single source of truth, you make sure that both the frontend and backend are perfectly in sync in perpetuity.</p>
<p>Using this approach also results in more type-safe, maintainable code. The result is less time spent on writing boilerplate and debugging random integration errors and more time spent creating the app itself.</p>
<p>For developers ready to explore further, please checkout the official <code>swift-openapi-generator</code> repository on Github here: <a target="_blank" href="https://github.com/apple/swift-openapi-generator">https://github.com/apple/swift-openapi-generator</a>.</p>
<p>You can follow me on <a target="_blank" href="https://github.com/sravankaruturi">GitHub</a> and <a target="_blank" href="https://hashnode.com/@sravankaruturi">Hashnode</a> for my other posts and projects.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn the Swift Programming Language ]]>
                </title>
                <description>
                    <![CDATA[ Swift is popular programming language that is often used for creating iOS apps.  We just released a full course on the freeCodeCamp.org YouTube channel that will teach you the Swift programming language. Vandad Nahavandipoor teaches this course. He c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-the-swift-programming-language/</link>
                <guid isPermaLink="false">66b2054beea9870582e16ca1</guid>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 07 Dec 2022 16:51:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/12/swift.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Swift is popular programming language that is often used for creating iOS apps. </p>
<p>We just released a full course on the freeCodeCamp.org YouTube channel that will teach you the Swift programming language.</p>
<p>Vandad Nahavandipoor teaches this course. He currently works as a lead iOS developer and he has created many other popular courses.</p>
<p>In this course you will learn every modern aspect of Swift as a programming language including, variables, constants, functions, structures, classes, protocols. extensions, asynchronous programming, generics and much more. This course will lay the foundation for learning Swift for those who are not familiar with Swift already.</p>
<p>Here are the sections in this course:</p>
<ul>
<li>Variables</li>
<li>Operators</li>
<li>If and else</li>
<li>Functions</li>
<li>Closures</li>
<li>Structures</li>
<li>Enumerations</li>
<li>Classes</li>
<li>Protocols</li>
<li>Extensions</li>
<li>Generics</li>
<li>Optionals</li>
<li>Error Handling</li>
<li>Collections</li>
<li>Equality and Hashing</li>
<li>Custom Operators</li>
<li>Asynchronous Programming</li>
</ul>
<p>Watch the full course <a target="_blank" href="https://youtu.be/8Xg7E9shq0U">on the freeCodeCamp.org YouTube channel</a> (7-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/8Xg7E9shq0U" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Swift Handbook – Learn Swift for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Introduction to Swift The Swift programming language was created by Apple in 2014. It's the official language that works with the whole Apple Operating Systems lineup: iOS, iPadOS, watchOS, macOS, and tvOS. Swift is an open source, general purpose, c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-swift-handbook/</link>
                <guid isPermaLink="false">66bb5ac25a83db22bea98450</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Flavio Copes ]]>
                </dc:creator>
                <pubDate>Mon, 24 Oct 2022 21:04:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/pexels-quang-nguyen-vinh-6131283.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-introduction-to-swift">Introduction to Swift</h2>
<p>The Swift programming language was created by Apple in 2014. It's the official language that works with the whole Apple Operating Systems lineup: iOS, iPadOS, watchOS, macOS, and tvOS.</p>
<p>Swift is an open source, general purpose, compiled programming language that's statically typed.</p>
<p>Every value has a type assigned. The type of a value is always checked when used as an argument or returned, at compile time. If there is a mismatch, the program will not compile.</p>
<p>Swift's compiler is LLVM, and it is included within Xcode, the standard IDE you use for Apple software development.</p>
<p>Swift is a modern programming language that was designed to "fit" in an ecosystem that was previously designed for a different programming language called Objective-C.</p>
<p>Most of the software running on the iPhone and Mac today is based on Objective-C code, even for official Apple apps. But Swift usage is gaining traction year after year. While Objective-C will be used for years to maintain and improve existing apps, new applications are likely going to be created with Swift.</p>
<p>Before Apple introduced Swift, Objective-C was heavily developed to introduce new capabilities and features. But in the recent years this effort has decreased a lot in favor of Swift development.</p>
<p>This does not mean Objective-C is dead or not worth learning: Objective-C is still an essential tool for any Apple developer.</p>
<p>That said, I am not going to cover Objective-C here, because we're focusing on Swift – the present and future of the Apple platform.</p>
<p>In just 6 years, Swift has gone through 5 major versions, and we're now (at the time of writing) at version 5.</p>
<p>Swift is famously Apple's products language, but it is not an Apple-only language. You can use it on several other platforms. </p>
<p>It is open source, so porting the language to other platforms does not require any permission or licensing, and you can find Swift projects to create Web servers and APIs (<a target="_blank" href="https://github.com/vapor/vapor">https://github.com/vapor/vapor</a>) as well as projects to interact with microcontrollers.</p>
<p>Swift is a general-purpose language, built with modern concepts, and it has a bright future.</p>
<h2 id="heading-what-well-cover-here">What We'll Cover Here</h2>
<p>The goal of this book is to get you up and running with Swift, starting from zero.</p>
<p>If you have a Mac or an iPad, I recommend you to download the Playgrounds application made by Apple from the App Store. </p>
<p>This app lets you run snippets of Swift code without having to create a full app first. It's a very handy way to test your code, not just when you start learning, but whenever you need to try some code.</p>
<p>It also contains a series of awesome examples and tutorials to expand your Swift and iOS knowledge.</p>
<p>Note: <a target="_blank" href="https://thevalleyofcode.com/download/swift/">You can get a PDF and ePub version of this Swift Beginner's Handbook</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-introduction-to-swift">Introduction to Swift</a></li>
<li><a class="post-section-overview" href="#heading-variables-in-swift">Variables in Swift</a></li>
<li><a class="post-section-overview" href="#heading-objects-in-swift">Objects in Swift</a></li>
<li><a class="post-section-overview" href="#heading-operators-in-swift">Operators in Swift</a></li>
<li><a class="post-section-overview" href="#heading-conditionals-in-swift">Conditionals in Swift</a></li>
<li><a class="post-section-overview" href="#heading-loops-in-swift">Loops in Swift</a></li>
<li><a class="post-section-overview" href="#heading-how-to-write-comments-in-swift">How to Write Comments in Swift</a></li>
<li><a class="post-section-overview" href="#heading-semicolons-in-swift">Semicolons in Swift</a></li>
<li><a class="post-section-overview" href="#heading-numbers-in-swift">Numbers in Swift</a></li>
<li><a class="post-section-overview" href="#heading-strings-in-swift">Strings in Swift</a></li>
<li><a class="post-section-overview" href="#heading-booleans-in-swift">Booleans in Swift</a></li>
<li><a class="post-section-overview" href="#heading-arrays-in-swift">Arrays in Swift</a></li>
<li><a class="post-section-overview" href="#heading-sets-in-swift">Sets in Swift</a></li>
<li><a class="post-section-overview" href="#heading-dictionaries-in-swift">Dictionaries in Swift</a></li>
<li><a class="post-section-overview" href="#heading-tuples-in-swift">Tuples in Swift</a></li>
<li><a class="post-section-overview" href="#heading-optionals-and-nil-in-swift">Optionals and <code>nil</code> in Swift</a> </li>
<li><a class="post-section-overview" href="#heading-enumerations-in-swift">Enumerations in Swift</a></li>
<li><a class="post-section-overview" href="#heading-structures-in-swift">Structures in Swift</a></li>
<li><a class="post-section-overview" href="#heading-classes-in-swift">Classes in Swift</a></li>
<li><a class="post-section-overview" href="#heading-functions-in-swift">Functions in Swift</a></li>
<li><a class="post-section-overview" href="#heading-protocols-in-swift">Protocols in Swift</a></li>
<li><a class="post-section-overview" href="#heading-where-to-go-from-here">Where to Go From Here</a></li>
</ul>
<h2 id="heading-variables-in-swift">Variables in Swift</h2>
<p>Variables let us assign a value to a label. We define them using the <code>var</code> keyword:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
<span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
</code></pre>
<p>Once a variable is defined, we can change its value:</p>
<pre><code class="lang-swift">age = <span class="hljs-number">9</span>
</code></pre>
<p>Variables that you do not want to change can be defined as constants, using the <code>let</code> keyword:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
<span class="hljs-keyword">let</span> age = <span class="hljs-number">8</span>
</code></pre>
<p>Changing the value of a constant is forbidden.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-01-at-07.51.48.png" alt="Image" width="600" height="400" loading="lazy">
<em>You can't change the value of a constant or you'll get this error</em></p>
<p>When you define a variable and you assign it a value, Swift implicitly infers the type of it.</p>
<p><code>8</code> is an <code>Int</code> value.</p>
<p><code>"Roger"</code> is a <code>String</code> value.</p>
<p>A decimal number like <code>3.14</code> is a <code>Double</code> value.</p>
<p>You can also specify the type at initialization time:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> age: <span class="hljs-type">Int</span> = <span class="hljs-number">8</span>
</code></pre>
<p>But it's typical to let Swift infer it, and it's mostly done when you declare a variable without initializing it.</p>
<p>You can declare a constant, and initialize it later:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> age : <span class="hljs-type">Int</span>

age = <span class="hljs-number">8</span>
</code></pre>
<p>Once a variable is defined, it is bound to that type. You cannot assign to it a different type, unless you explicitly convert it.</p>
<p>You can't do this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
age = <span class="hljs-string">"nine"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-01-at-07.54.25.png" alt="Image" width="600" height="400" loading="lazy">
<em>Cannot assign value of type 'String' to type 'Int' error</em></p>
<p><code>Int</code> and <code>String</code> are just two of the built-in data types provided by Swift.</p>
<h2 id="heading-objects-in-swift">Objects in Swift</h2>
<p>In Swift, everything is an object. Even the <code>8</code> value we assigned to the <code>age</code> variable is an object.</p>
<p>In some languages, objects are a special type. But in Swift, everything is an object and this leads to one particular feature: every value can <em>receive messages</em>.</p>
<p>Each type can have multiple functions associated to it, which we call <strong>methods</strong>.</p>
<p>For example, talking about the <code>8</code> number value, we can call its <code>isMultiple</code> method, to check if the number is a multiple of another number:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-01-at-14.43.49.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>isMultiple</code> method</em></p>
<p>A String value has another set of methods.</p>
<p>A type also has instance variables. For example the String type has the instance variable <code>count</code>, which gives you the number of characters in a string:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-01-at-14.45.39.png" alt="Image" width="600" height="400" loading="lazy">
<em>instance variable <code>count</code></em></p>
<p>Swift has 3 different <strong>object types</strong>, which we'll see more in details later on: <strong>classes</strong>, <strong>structs</strong> and <strong>enums</strong>.</p>
<p>Those are very different, but they have one thing in common: to object type, we can <strong>add methods</strong>, and to any value, of any object type, we can <strong>send messages</strong>.</p>
<h2 id="heading-operators-in-swift">Operators in Swift</h2>
<p>We can use a wide set of operators to operate on values.</p>
<p>We can divide operators in many categories. The first is the number of targets: 1 for <strong>unary operators</strong>, 2 for <strong>binary operators</strong> or 3 for the one and only <strong>ternary operator</strong>.</p>
<p>Then we can divide operators based on the kind of operation they perform:</p>
<ul>
<li>assignment operator</li>
<li>arithmetic operators</li>
<li>compound assignment operators</li>
<li>comparison operators</li>
<li>range operators</li>
<li>logical operators</li>
</ul>
<p>plus some more advanced ones, including nil-coalescing, ternary conditional, overflow, bitwise and pointwise operators.</p>
<p>Note: Swift allows you to create your own operators and define how operators work on your types you define.</p>
<h3 id="heading-assignment-operator-in-swift">Assignment operator in Swift</h3>
<p>You use the assignment operator to assign a value to a variable:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
</code></pre>
<p>Or to assign a variable value to another variable:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
<span class="hljs-keyword">var</span> another = age
</code></pre>
<h3 id="heading-arithmetic-operators-in-swift">Arithmetic operators in Swift</h3>
<p>Swift has a number of binary arithmetic operators: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> (division), <code>%</code> (remainder):</p>
<pre><code class="lang-swift"><span class="hljs-number">1</span> + <span class="hljs-number">1</span> <span class="hljs-comment">//2</span>
<span class="hljs-number">2</span> - <span class="hljs-number">1</span> <span class="hljs-comment">//1</span>
<span class="hljs-number">2</span> * <span class="hljs-number">2</span> <span class="hljs-comment">//4</span>
<span class="hljs-number">4</span> / <span class="hljs-number">2</span> <span class="hljs-comment">//2</span>
<span class="hljs-number">4</span> % <span class="hljs-number">3</span> <span class="hljs-comment">//1</span>
<span class="hljs-number">4</span> % <span class="hljs-number">2</span> <span class="hljs-comment">//0</span>
</code></pre>
<p><code>-</code> also works as a unary minus operator:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> hotTemperature = <span class="hljs-number">20</span>
<span class="hljs-keyword">let</span> freezingTemperature = -<span class="hljs-number">20</span>
</code></pre>
<p>You can also use <code>+</code> to concatenate String values:</p>
<pre><code class="lang-swift"><span class="hljs-string">"Roger"</span> + <span class="hljs-string">" is a good dog"</span>
</code></pre>
<h3 id="heading-compound-assignment-operators-in-swift">Compound assignment operators in Swift</h3>
<p>The compound assignment operators combine the assignment operator with arithmetic operators:</p>
<ul>
<li><code>+=</code></li>
<li><code>-=</code></li>
<li><code>*=</code></li>
<li><code>/=</code></li>
<li><code>%=</code></li>
</ul>
<p>Example:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
age += <span class="hljs-number">1</span>
</code></pre>
<h3 id="heading-comparison-operators-in-swift">Comparison operators in Swift</h3>
<p>Swift defines a few comparison operators:</p>
<ul>
<li><code>==</code></li>
<li><code>!=</code></li>
<li><code>&gt;</code></li>
<li><code>&lt;</code></li>
<li><code>&gt;=</code></li>
<li><code>&lt;=</code></li>
</ul>
<p>You can use those operators to get a boolean value (<code>true</code> or <code>false</code>) depending on the result:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> a = <span class="hljs-number">1</span>
<span class="hljs-keyword">let</span> b = <span class="hljs-number">2</span>

a == b <span class="hljs-comment">//false</span>
a != b <span class="hljs-comment">//true</span>
a &gt; b <span class="hljs-comment">// false</span>
a &lt;= b <span class="hljs-comment">//true</span>
</code></pre>
<h3 id="heading-range-operators-in-swift">Range operators in Swift</h3>
<p>Range operators are used in loops. They allow us to define a range:</p>
<pre><code class="lang-swift"><span class="hljs-number">0</span>...<span class="hljs-number">3</span> <span class="hljs-comment">//4 times</span>
<span class="hljs-number">0</span>..&lt;<span class="hljs-number">3</span> <span class="hljs-comment">//3 times</span>

<span class="hljs-number">0</span>...<span class="hljs-built_in">count</span> <span class="hljs-comment">//"count" times</span>
<span class="hljs-number">0</span>..&lt;<span class="hljs-built_in">count</span> <span class="hljs-comment">//"count-1" times</span>
</code></pre>
<p>Here's a sample usage:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> <span class="hljs-built_in">count</span> = <span class="hljs-number">3</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>...<span class="hljs-built_in">count</span> {
  <span class="hljs-comment">//loop body</span>
}
</code></pre>
<h3 id="heading-logical-operators-in-swift">Logical operators in Swift</h3>
<p>Swift gives us the following logical operators:</p>
<ul>
<li><code>!</code>, the unary operator NOT</li>
<li><code>&amp;&amp;</code>, the binary operator AND</li>
<li><code>||</code>, the binary operator OR</li>
</ul>
<p>Sample usage:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> condition1 = <span class="hljs-literal">true</span>
<span class="hljs-keyword">let</span> condition2 = <span class="hljs-literal">false</span>

!condition1 <span class="hljs-comment">//false</span>

condition1 &amp;&amp; condition2 <span class="hljs-comment">//false</span>
condition1 || condition2 <span class="hljs-comment">//true</span>
</code></pre>
<p>Those are mostly used in the <code>if</code> conditional expression evaluation:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> condition1 &amp;&amp; condition2 {
  <span class="hljs-comment">//if body</span>
}
</code></pre>
<h2 id="heading-conditionals-in-swift">Conditionals in Swift</h2>
<h3 id="heading-if-statements-in-swift"><code>if</code> statements in Swift</h3>
<p><code>if</code> statements are the most popular way to perform a conditional check. We use the <code>if</code> keyword followed by a boolean expression, followed by a block containing code that is run if the condition is true:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> condition = <span class="hljs-literal">true</span>
<span class="hljs-keyword">if</span> condition == <span class="hljs-literal">true</span> {
    <span class="hljs-comment">// code executed if the condition is true</span>
}
</code></pre>
<p>An <code>else</code> block is executed if the condition is false:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> condition = <span class="hljs-literal">true</span>
<span class="hljs-keyword">if</span> condition == <span class="hljs-literal">true</span> {
    <span class="hljs-comment">// code executed if the condition is true</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// code executed if the condition is false</span>
}
</code></pre>
<p>You can optionally wrap the condition validation into parentheses if you prefer:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> (condition == <span class="hljs-literal">true</span>) {
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>And you can also just write:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> condition {
    <span class="hljs-comment">// runs if `condition` is `true`</span>
}
</code></pre>
<p>or</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> !condition {
    <span class="hljs-comment">// runs if `condition` is `false`</span>
}
</code></pre>
<p>One thing that separates Swift from many other languages is that it prevents bugs caused by erroneously doing an assignment instead of a comparison. This means you can't do this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> condition = <span class="hljs-literal">true</span> {
    <span class="hljs-comment">// The program does not compile</span>
}
</code></pre>
<p>The reason is that the assignment operator does not return anything, but the <code>if</code> conditional must be a boolean expression.</p>
<h3 id="heading-switch-statements-in-swift"><code>switch</code> statements in Swift</h3>
<p>Switch statements are a handy way to create a conditional with multiple options:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>

<span class="hljs-keyword">switch</span> name {
<span class="hljs-keyword">case</span> <span class="hljs-string">"Roger"</span>:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello, mr. Roger!"</span>)
<span class="hljs-keyword">default</span>: 
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello, \(name)"</span>)
}
</code></pre>
<p>When the code of a case ends, the switch exits automatically.</p>
<p>A switch in Swift needs to cover all cases. If the <em>tag</em>, <code>name</code> in this case, is a string that can have any value, we need to add a <code>default</code> case, mandatory.</p>
<p>Otherwise with an enumeration, you can simply list all the options:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">case</span> dog
    <span class="hljs-keyword">case</span> cat
}

<span class="hljs-keyword">var</span> animal: <span class="hljs-type">Animal</span> = .dog

<span class="hljs-keyword">switch</span> animal {
<span class="hljs-keyword">case</span> .dog:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello, dog!"</span>)
<span class="hljs-keyword">case</span> .cat:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello, cat!"</span>)
}
</code></pre>
<p>A case can be a Range:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> age = <span class="hljs-number">20</span>

<span class="hljs-keyword">switch</span> age {
<span class="hljs-keyword">case</span> <span class="hljs-number">0</span>..&lt;<span class="hljs-number">18</span>:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"You can't drive!!"</span>)
<span class="hljs-keyword">default</span>: 
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"You can drive"</span>)
}
</code></pre>
<h3 id="heading-ternary-conditional-operator-in-swift">Ternary conditional operator in Swift</h3>
<p>The ternary conditional operator is a shorter version of an <code>if</code> expression. It allows us to execute an expression if a condition is true, and another expression if the condition is false.</p>
<p>Here is the syntax:</p>
<pre><code><span class="hljs-string">`condition`</span> ? <span class="hljs-string">`value if true`</span> : <span class="hljs-string">`value if false`</span>
</code></pre><p>Example:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> num1 = <span class="hljs-number">1</span>
<span class="hljs-keyword">let</span> num2 = <span class="hljs-number">2</span>

<span class="hljs-keyword">let</span> smallerNumber = num1 &lt; num2 ? num1 : num2 

<span class="hljs-comment">// smallerNumber == 1</span>
</code></pre>
<p>The syntax is shorter than an <code>if</code> statement, and sometimes it might make more sense to use it.</p>
<h2 id="heading-loops-in-swift">Loops in Swift</h2>
<h3 id="heading-for-in-loops-in-swift"><code>for-in</code> loops in Swift</h3>
<p>You can use <code>for-in</code> loops to iterate a specific amount of times, using a range operator:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">for</span> index <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>...<span class="hljs-number">3</span> {
  <span class="hljs-comment">//iterate 4 times, `index` is: 0, 1, 2, 3</span>
}
</code></pre>
<p>You can iterate over the elements of an array or set:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> list = [<span class="hljs-string">"a"</span>, <span class="hljs-string">"b"</span>, <span class="hljs-string">"c"</span>]
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> list {
  <span class="hljs-comment">// `item` contains the element value</span>
}
</code></pre>
<p>And on the elements of a dictionary:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> list = [<span class="hljs-string">"a"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"b"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"c"</span>: <span class="hljs-number">2</span>]
<span class="hljs-keyword">for</span> (key, value) <span class="hljs-keyword">in</span> list {
  <span class="hljs-comment">// `key` contains the item key</span>
  <span class="hljs-comment">// `value` contains the item value</span>
}
</code></pre>
<h3 id="heading-while-loops-in-swift"><code>while</code> loops in Swift</h3>
<p>A <code>while</code> loop can be used to iterate on anything, and will run while the condition is <code>true</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">while</span> [condition] {
    <span class="hljs-comment">//statements...</span>
}
</code></pre>
<p>The condition is checked at the start, before the loop block is executed.</p>
<p>Example:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> item = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> item &lt;= <span class="hljs-number">3</span> { <span class="hljs-comment">//repeats 3 times</span>
    <span class="hljs-built_in">print</span>(item)
    item += <span class="hljs-number">1</span>
}
</code></pre>
<h3 id="heading-repeat-while-loops-in-swift"><code>repeat-while</code> loops in Swift</h3>
<p>A <code>repeat-while</code> loop in Swift is similar to the <code>while</code> loop. But in this case the condition is checked at the end, after the loop block, so the loop block is executed at least once. Then the condition is checked, and if it is evaluated as <code>true</code>, the loop block is repeated:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">repeat</span> {
    <span class="hljs-comment">//statements...</span>
} <span class="hljs-keyword">while</span> [condition]
</code></pre>
<p>Example:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> item = <span class="hljs-number">0</span>
<span class="hljs-keyword">repeat</span> { <span class="hljs-comment">//repeats 3 times</span>
    <span class="hljs-built_in">print</span>(item)
    item += <span class="hljs-number">1</span>
} <span class="hljs-keyword">while</span> item &lt; <span class="hljs-number">3</span>
</code></pre>
<h3 id="heading-continue-and-break-statements-in-swift"><code>continue</code> and <code>break</code> statements in Swift</h3>
<p>Swift provides you 2 statements that you can use to control the flow inside a loop: <code>continue</code> and <code>break</code>.</p>
<p>You use <code>continue</code> to stop the current iteration, and run the next iteration of the loop.</p>
<p><code>break</code> ends the loop, not executing any other iteration.</p>
<p>Example:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> list = [<span class="hljs-string">"a"</span>, <span class="hljs-string">"b"</span>, <span class="hljs-string">"c"</span>]
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> list {
  <span class="hljs-keyword">if</span> (item == <span class="hljs-string">"b"</span>) {
    <span class="hljs-keyword">break</span>
  }
  <span class="hljs-comment">//do something</span>
}
</code></pre>
<h2 id="heading-how-to-write-comments-in-swift">How to Write Comments in Swift</h2>
<p>A comment in Swift can take 2 forms: a single-line comment, and a multi-line comment.</p>
<p>A single-line comment looks like this:</p>
<pre><code class="lang-swift"><span class="hljs-comment">//this is a comment</span>
</code></pre>
<p>and and you can put it at the end of a line of code:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> a = <span class="hljs-number">1</span> <span class="hljs-comment">//this is a comment</span>
</code></pre>
<p>A multi-line comment is written using this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-comment">/* this
 is
    a multi-line
 comment
*/</span>
</code></pre>
<p>Swift allows you to nest multi-line comments:</p>
<pre><code class="lang-swift"><span class="hljs-comment">/* this
 is
    a <span class="hljs-comment">/* nested */</span> multi-line
 comment
*/</span>
</code></pre>
<p>This is handy especially when commenting out large portions of code that already contain multi-line comments.</p>
<h2 id="heading-semicolons-in-swift">Semicolons in Swift</h2>
<p>In Swift, semicolons are generally optional.</p>
<p>You can write statements on separate lines, and you don't need to add a semicolon:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> list = [<span class="hljs-string">"a"</span>, <span class="hljs-string">"b"</span>, <span class="hljs-string">"c"</span>]
<span class="hljs-keyword">var</span> a = <span class="hljs-number">2</span>
</code></pre>
<p>You <em>can</em> add a semicolon, but it adds nothing meaningful in this case:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> list = [<span class="hljs-string">"a"</span>, <span class="hljs-string">"b"</span>, <span class="hljs-string">"c"</span>];
<span class="hljs-keyword">var</span> a = <span class="hljs-number">2</span>;
</code></pre>
<p>But if you want to write more than one statement on the same line, then you need to add a semicolon:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> a = <span class="hljs-number">2</span>; <span class="hljs-keyword">let</span> b = <span class="hljs-number">3</span>
</code></pre>
<h2 id="heading-numbers-in-swift">Numbers in Swift</h2>
<p>In Swift, numbers have 2 main types: <code>Int</code> and <code>Double</code>.</p>
<p>An <code>Int</code> is a number without decimal point. A <code>Double</code> is a number with decimal point.</p>
<p>Both use 64 bits, on modern computers that work with 64 bits, and 32 bit on 32-bit platforms.</p>
<p>The range of values they can store depends on the platform used, and can be retrieved using the <code>int</code> property of each type:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-02-at-07.41.09.png" alt="Image" width="600" height="400" loading="lazy">
<em>Range of int values</em></p>
<p>Then, in addition to <code>Int</code> and <code>Double</code>, we have lots of other numeric types. These were mostly used to interact with APIs built in the past and that needed to interact with C or Objective-C, and you must be aware that we have them:</p>
<ul>
<li><code>Int8</code> is an integer with 8 bits</li>
<li><code>Int16</code> is an integer with 16 bits</li>
<li><code>Int32</code> is an integer with 32 bits</li>
<li><code>Int64</code> is an integer with 64 bits</li>
<li><code>UInt8</code> is an unsigned integer with 8 bits</li>
<li><code>UInt16</code> is an unsigned integer with 16 bits</li>
<li><code>UInt32</code> is an unsigned integer with 32 bits</li>
<li><code>UInt64</code> is an unsigned integer with 64 bits</li>
<li><code>UInt</code> is like <code>Int</code>, but unsigned, and it ranges from 0 to <code>Int.max * 2</code>.</li>
<li><code>Float</code> is a decimal number with 32 bits.</li>
</ul>
<p>Then using Cocoa APIs you might use other numeric types like CLong, CGFloat, and more.</p>
<p>You will always use <code>Int</code> or <code>Double</code> in your code, and use those specific types only in particular cases.</p>
<p>Remember that you can always convert any of those types to <code>Int</code> and <code>Double</code> types, instantiating a number passing the value inside parentheses to <code>Double()</code> or <code>Int()</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> age : <span class="hljs-type">UInt8</span> = <span class="hljs-number">3</span>
<span class="hljs-keyword">let</span> intAge = <span class="hljs-type">Int</span>(age)
</code></pre>
<p>You can also convert a number from <code>Double</code> to <code>Int</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> age = <span class="hljs-type">Double</span>(<span class="hljs-number">3</span>)
<span class="hljs-keyword">let</span> <span class="hljs-built_in">count</span> = <span class="hljs-type">Int</span>(<span class="hljs-number">3.14</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-02-at-07.59.19.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to convert a number from <code>Double</code> to <code>Int</code></em></p>
<h2 id="heading-strings-in-swift">Strings in Swift</h2>
<p>Strings are one of the most popular tools in programming.</p>
<p>In Swift, you can define a string using the string literal syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
</code></pre>
<p>We use double quotes. Single quotes are not valid string delimiters.</p>
<p>A string can span over multiple lines using 3 double quotes:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> description = <span class="hljs-string">"""
    a long
      long 
          long description
    """</span>
</code></pre>
<p>You can use string interpolation to embed an expression in a string:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> age = <span class="hljs-number">8</span>

<span class="hljs-keyword">let</span> name = <span class="hljs-string">"""
    Roger, age \(age)
    Next year he will be \(age + 1)
    """</span>
</code></pre>
<p>You can concatenate two strings with the <code>+</code> operator:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
name = name + <span class="hljs-string">" The Dog"</span>
</code></pre>
<p>And you can append text to a string with the <code>+=</code> operator:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
name += <span class="hljs-string">" The Dog"</span>
</code></pre>
<p>Or using the <code>append(_:)</code> method:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
name.append(<span class="hljs-string">" The Dog"</span>)
</code></pre>
<p>You can count the characters in a string using the <code>count</code> string property:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
name.<span class="hljs-built_in">count</span> <span class="hljs-comment">//5</span>
</code></pre>
<p>Any string comes with a set of useful methods, for example:</p>
<ul>
<li><code>removeFirst()</code> to remove the first character</li>
<li><code>removeLast()</code> to remove the last character</li>
<li><code>lowercased()</code> to get a new string, lowercased</li>
<li><code>uppercased()</code> to get a new string, uppercased</li>
<li><code>starts(with:)</code> which returns true if the string starts with a specific substring</li>
<li><code>contains()</code> which returns true if the string contains a specific character</li>
</ul>
<p>and many, many more.</p>
<p>When you need to reference an item in the string, since strings in Swift are unicode, we can't simply reference the letter <code>o</code> in <code>let name = "Roger"</code> using <code>name[1]</code>. You need to work with indexes.</p>
<p>Any string provides the starting index with the <code>startIndex</code> property:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
name.startIndex <span class="hljs-comment">//0</span>
</code></pre>
<p>To calculate a specific index in the string, you calculate it using the <code>index(i:offsetBy:)</code> method:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
<span class="hljs-keyword">let</span> i = name.index(name.startIndex, offsetBy: <span class="hljs-number">2</span>)
name[i] <span class="hljs-comment">//"g"</span>
</code></pre>
<p>You can also use the index to get a substring:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
<span class="hljs-keyword">let</span> i = name.index(name.startIndex, offsetBy: <span class="hljs-number">2</span>)
name.suffix(from: i) <span class="hljs-comment">//"ger"</span>

<span class="hljs-comment">//Or using the subscript:</span>

name[i...] <span class="hljs-comment">//"ger"</span>
</code></pre>
<p>When you get a substring from a string, the type of the result is <code>Substring</code>, not <code>String</code>.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"Roger"</span>
<span class="hljs-keyword">let</span> i = name.index(name.startIndex, offsetBy: <span class="hljs-number">2</span>)
<span class="hljs-built_in">print</span>(type(of: name.suffix(from: i))) 
<span class="hljs-comment">//Substring</span>
</code></pre>
<p>Substrings are more memory efficient, because you do not get a new string, but the same memory structure is used behind the scenes. But you need to be careful when you deal with strings a lot, as there are optimizations you can implement.</p>
<p>Strings are collections, and they can be iterated over in loops.</p>
<h2 id="heading-booleans-in-swift">Booleans in Swift</h2>
<p>Swift provides the <code>Bool</code> type, which can have two values: <code>true</code> and <code>false</code>.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> done = <span class="hljs-literal">false</span>
done = <span class="hljs-literal">true</span>
</code></pre>
<p>Booleans are especially useful with conditional control structures like <code>if</code> statements or the ternary conditional operator:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> done = <span class="hljs-literal">true</span>

<span class="hljs-keyword">if</span> done == <span class="hljs-literal">true</span> {
    <span class="hljs-comment">//code</span>
}
</code></pre>
<h2 id="heading-arrays-in-swift">Arrays in Swift</h2>
<p>We use arrays to create a collection of items.</p>
<p>In this example we create an array holding 3 integers:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
</code></pre>
<p>We can access the first item using the syntax <code>list[0]</code>, the second using <code>list[1]</code>, and so on.</p>
<p>Elements in an array in Swift must have the same type.</p>
<p>The type can be inferred if you initialize the array at declaration time, like in the case above.</p>
<p>Otherwise the type of values an array can include must be declared, in this way:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list: [<span class="hljs-type">Int</span>] = []
</code></pre>
<p>Another shorthand syntax is:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list = [<span class="hljs-type">Int</span>]()
</code></pre>
<p>You can also explicitly declare the type at initialization, like this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list: [<span class="hljs-type">Int</span>] = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
</code></pre>
<p>A quick way to initialize an array is to use the range operator:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list = <span class="hljs-type">Array</span>(<span class="hljs-number">1</span>...<span class="hljs-number">4</span>) <span class="hljs-comment">//[1, 2, 3, 4]</span>
</code></pre>
<p>To get the number of items in the array, use the <code>count</code> property:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.<span class="hljs-built_in">count</span> <span class="hljs-comment">//3</span>
</code></pre>
<p>If an array is empty, its <code>isEmpty</code> property is <code>true</code>.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.isEmpty <span class="hljs-comment">//false</span>
</code></pre>
<p>You can append an item at the end of the array using the <code>append()</code> method:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list: [<span class="hljs-type">Int</span>] = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.append(<span class="hljs-number">4</span>)
</code></pre>
<p>or you can insert an item at any position of the array using <code>insert(newElement: &lt;Type&gt; at: Int)</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list: [<span class="hljs-type">Int</span>] = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.insert(<span class="hljs-number">17</span>, at: <span class="hljs-number">2</span>)
<span class="hljs-comment">//list is [1, 2, 17, 3]</span>
</code></pre>
<p>An array must be declared as <code>var</code> to be modified. If it's declared with <code>let</code>, you cannot modify it by adding or removing elements.</p>
<p>To remove one item from the array, use <code>remove(at:)</code> passing the index of the element to remove:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list: [<span class="hljs-type">Int</span>] = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.remove(<span class="hljs-number">1</span>)
<span class="hljs-comment">//list is [1, 3]</span>
</code></pre>
<p><code>removeLast()</code> and <code>removeFirst()</code> are two handy ways to remove the last and first element.</p>
<p>To remove all items from the array, you can use <code>removeAll()</code> or you can assign an empty array:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list: [<span class="hljs-type">Int</span>] = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.removeAll()
<span class="hljs-comment">//or</span>
list = []
</code></pre>
<p>The <code>sort()</code> method sorts the array:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> list = [<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
list.<span class="hljs-built_in">sort</span>()
<span class="hljs-comment">//list is [1, 2, 3]</span>
</code></pre>
<p>There are a lot more methods, but those are the basic ones.</p>
<p>Arrays are equal when they contain the same elements, of the same type:</p>
<pre><code class="lang-swift">[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>] == [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>] <span class="hljs-comment">//true</span>
</code></pre>
<p>Arrays are passed by value, which means if you pass an array to a function, or return it from a function, the array is copied.</p>
<p>Arrays are collections, and they can be iterated over in loops.</p>
<h2 id="heading-sets-in-swift">Sets in Swift</h2>
<p>You use sets to create collections of non-repeated items.</p>
<p>While an array can contain many times the same item, you only have unique items in a set.</p>
<p>You can declare a set of <code>Int</code> values in this way:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> <span class="hljs-keyword">set</span>: <span class="hljs-type">Set</span>&lt;<span class="hljs-type">Int</span>&gt; = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
</code></pre>
<p>or you can initialize it from an array:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
</code></pre>
<p>You can add items to the set using <code>insert()</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-keyword">set</span>.insert(<span class="hljs-number">17</span>)
</code></pre>
<p>Unlike arrays, there is no order or position in a set. Items are retrieved and inserted randomly.</p>
<p>The way to print the content of a set so it's ordered is to transform it into an array using the <code>sorted()</code> method:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>])
<span class="hljs-keyword">let</span> orderedList = <span class="hljs-keyword">set</span>.sorted()
</code></pre>
<p>To check if a set contains an element, use the <code>contains()</code> method:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-keyword">set</span>.<span class="hljs-built_in">contains</span>(<span class="hljs-number">2</span>) <span class="hljs-comment">//true</span>
</code></pre>
<p>To get the number of items in the set, use the <code>count</code> property:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-keyword">set</span>.<span class="hljs-built_in">count</span> <span class="hljs-comment">//3</span>
</code></pre>
<p>If a set is empty, its <code>isEmpty</code> property is <code>true</code>.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-keyword">set</span>.isEmpty <span class="hljs-comment">//false</span>
</code></pre>
<p>To remove one item from the array, use <code>remove()</code> passing the value of the element:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> <span class="hljs-keyword">set</span> = <span class="hljs-type">Set</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-keyword">set</span>.remove(<span class="hljs-number">1</span>)
<span class="hljs-comment">//set is [2, 3]</span>
</code></pre>
<p>To remove all items from the set, you can use <code>removeAll()</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">set</span>.removeAll()
</code></pre>
<p>Sets, like arrays, are passed by value. This means that if you pass it to a function, or return it from a function, the set is copied.</p>
<p>Sets are great to perform set math operations like intersection, union, subtracting, and more.</p>
<p>These methods help with this:</p>
<ul>
<li><code>intersection(_:)</code></li>
<li><code>symmetricDifference(_:)</code></li>
<li><code>union(_:)</code></li>
<li><code>subtracting(_:)</code></li>
<li><code>isSubset(of:)</code></li>
<li><code>isSuperset(of:)</code></li>
<li><code>isStrictSubset(of:)</code></li>
<li><code>isStrictSuperset(of:)</code></li>
<li><code>isDisjoint(with:)</code></li>
</ul>
<p>Sets are collections, and they can be iterated over in loops.</p>
<h2 id="heading-dictionaries-in-swift">Dictionaries in Swift</h2>
<p>We use dictionaries to create a collection of key-value pairs.</p>
<p>Here is how to create a dictionary with 1 key-value pair, where the key is a String and the value is an Int:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> dict = [<span class="hljs-string">"Roger"</span>: <span class="hljs-number">8</span>, <span class="hljs-string">"Syd"</span>: <span class="hljs-number">7</span>]
</code></pre>
<p>In this case the type is inferred. You can also explicitly set the type at declaration time:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> dict: [<span class="hljs-type">String</span>: <span class="hljs-type">Int</span>] = [<span class="hljs-string">"Roger"</span>: <span class="hljs-number">8</span>, <span class="hljs-string">"Syd"</span>: <span class="hljs-number">7</span>]
</code></pre>
<p>In this example we create an empty dictionary of Int keys and String values:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> dict = [<span class="hljs-type">String</span>: <span class="hljs-type">Int</span>]()

<span class="hljs-comment">//or</span>

<span class="hljs-keyword">var</span> dict: [<span class="hljs-type">String</span>: <span class="hljs-type">Int</span>] = [:]
</code></pre>
<p>You can access the value assigned to a key using this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> dict = [<span class="hljs-string">"Roger"</span>: <span class="hljs-number">8</span>, <span class="hljs-string">"Syd"</span>: <span class="hljs-number">7</span>]

dict[<span class="hljs-string">"Roger"</span>] <span class="hljs-comment">//8</span>
dict[<span class="hljs-string">"Syd"</span>] <span class="hljs-comment">//7</span>
</code></pre>
<p>You can change the value assigned to a key in this way:</p>
<pre><code class="lang-swift">dict[<span class="hljs-string">"Roger"</span>] = <span class="hljs-number">9</span>
</code></pre>
<p>A dictionary must be declared as <code>var</code> to be modified. If it's declared with <code>let</code>, you cannot modify it by adding or removing elements.</p>
<p>Use the same syntax to add a new key/value pair:</p>
<pre><code class="lang-swift">dict[<span class="hljs-string">"Tina"</span>] = <span class="hljs-number">4</span>
</code></pre>
<p>To remove a key/value pair, assign the value to <code>nil</code>:</p>
<pre><code class="lang-swift">dict[<span class="hljs-string">"Tina"</span>] = <span class="hljs-literal">nil</span>
</code></pre>
<p>Or call the <code>removeValue(forKey:)</code> method:</p>
<pre><code class="lang-swift">dict.removeValue(forKey: <span class="hljs-string">"Tina"</span>)
</code></pre>
<p>To get the number of items in the dictionary, use the <code>count</code> property:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> dict = [<span class="hljs-string">"Roger"</span>: <span class="hljs-number">8</span>, <span class="hljs-string">"Syd"</span>: <span class="hljs-number">7</span>]
dict.<span class="hljs-built_in">count</span> <span class="hljs-comment">//2</span>
</code></pre>
<p>If a dictionary is empty, its <code>isEmpty</code> property is <code>true</code>.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> dict = [<span class="hljs-type">String</span>: <span class="hljs-type">Int</span>]()
dict.isEmpty <span class="hljs-comment">//true</span>
</code></pre>
<p>There are a lot of methods related to dictionaries, but those are the basic ones.</p>
<p>Dictionaries are passed by value, which means if you pass it to a function, or return it from a function, the dictionary is copied.</p>
<p>Dictionaries are collections, and they can be iterated over in loops.</p>
<h2 id="heading-tuples-in-swift">Tuples in Swift</h2>
<p>You use tuples to group multiple values into a single collection. For example you can declare a variable <code>dog</code> containing a String and an Int value:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> dog : (<span class="hljs-type">String</span>, <span class="hljs-type">Int</span>)
</code></pre>
<p>And you can initialize them with a name and an age</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> dog : (<span class="hljs-type">String</span>, <span class="hljs-type">Int</span>) = (<span class="hljs-string">"Roger"</span>, <span class="hljs-number">8</span>)
</code></pre>
<p>But as with any other variable, the type can be inferred during initialization:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> dog = (<span class="hljs-string">"Roger"</span>, <span class="hljs-number">8</span>)
</code></pre>
<p>You can use named elements:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> dog = (name: <span class="hljs-string">"Roger"</span>, age: <span class="hljs-number">8</span>)

dog.name <span class="hljs-comment">//"Roger"</span>
dog.age <span class="hljs-comment">//8</span>
</code></pre>
<p>Once a tuple is defined, you can decompose it to individual variables in this way:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> dog = (<span class="hljs-string">"Roger"</span>, <span class="hljs-number">8</span>)
<span class="hljs-keyword">let</span> (name, age) = dog
</code></pre>
<p>and if you need to just get one of the values, you can use the special underscore keyword to ignore the other ones:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> dog = (<span class="hljs-string">"Roger"</span>, <span class="hljs-number">8</span>)
<span class="hljs-keyword">let</span> (name, <span class="hljs-number">_</span>) = dog
</code></pre>
<p>Tuples are an awesome tool for various needs.</p>
<p>The most obvious one is that they're a short way to group similar data.</p>
<p>Another one of those needs is returning multiple items from a function. A function can only return a single item, so a tuple is a convenient structure for that.</p>
<p>Another handy functionality allowed by tuples is swapping elements:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> a = <span class="hljs-number">1</span>
<span class="hljs-keyword">var</span> b = <span class="hljs-number">2</span>

(a, b) = (b, a)

<span class="hljs-comment">//a == 2</span>
<span class="hljs-comment">//b == 1</span>
</code></pre>
<h2 id="heading-optionals-and-nil-in-swift">Optionals and <code>nil</code> in Swift</h2>
<p>Optionals are one key feature of Swift.</p>
<p>When you don't know if a value will be present or absent, you declare the type as an optional.</p>
<p>The optional wraps another value with its own type. Or maybe not.</p>
<p>We declare an optional by adding a question mark after its type, like this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> value: <span class="hljs-type">Int?</span> = <span class="hljs-number">10</span>
</code></pre>
<p>Now <code>value</code> is not an Int value. It's an optional wrapping an Int value.</p>
<p>To find out if the optional wraps a value, you must <strong>unwrap</strong> it.</p>
<p>You do so using an exclamation mark:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> value: <span class="hljs-type">Int?</span> = <span class="hljs-number">10</span>
<span class="hljs-built_in">print</span>(value!) <span class="hljs-comment">//10</span>
</code></pre>
<p>Swift methods often return an optional. For example the <code>Int</code> type initializer accepts a string, and returns an Int optional:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-02-at-18.08.48.png" alt="Image" width="600" height="400" loading="lazy">
<em>Int type initializer takes in a string and returns an int optional</em></p>
<p>This is because it does not know if the string can be converted to a number.</p>
<p>If the optional does not contain a value, it evaluates as <code>nil</code>, and you cannot unwrap it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-02-at-18.12.13.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evaluating to <code>nil</code></em></p>
<p><code>nil</code> is a special value that cannot be assigned to a variable. Only to an optional:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-02-at-18.14.21.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2020-11-02-at-18.13.56-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>You can only assign <code>nil</code> to an optional (not an int)</em></p>
<p>You typically use <code>if</code> statements to unwrap values in your code, like this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> value: <span class="hljs-type">Int?</span> = <span class="hljs-number">2</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> age = value {
    <span class="hljs-built_in">print</span>(age)
}
</code></pre>
<h2 id="heading-enumerations-in-swift">Enumerations in Swift</h2>
<p>Enumerations are a way to group a set of different options under a common name.</p>
<p>Example:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">case</span> dog
    <span class="hljs-keyword">case</span> cat
    <span class="hljs-keyword">case</span> mouse
    <span class="hljs-keyword">case</span> horse
}
</code></pre>
<p>This <code>Animal</code> enum is now a <strong>type</strong>.</p>
<p>A type whose value can only be one of the cases listed.</p>
<p>If you define a variable of type <code>Animal</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> animal: <span class="hljs-type">Animal</span>
</code></pre>
<p>you can later decide which value to assign it using this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> animal: <span class="hljs-type">Animal</span>
animal = .dog
</code></pre>
<p>We can use enumerations in control structures like switches:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">case</span> dog
    <span class="hljs-keyword">case</span> cat
    <span class="hljs-keyword">case</span> mouse
    <span class="hljs-keyword">case</span> horse
}

<span class="hljs-keyword">let</span> animal = <span class="hljs-type">Animal</span>.dog

<span class="hljs-keyword">switch</span> animal {
<span class="hljs-keyword">case</span> .dog: <span class="hljs-built_in">print</span>(<span class="hljs-string">"dog"</span>)
<span class="hljs-keyword">case</span> .cat: <span class="hljs-built_in">print</span>(<span class="hljs-string">"cat"</span>)
<span class="hljs-keyword">default</span>: <span class="hljs-built_in">print</span>(<span class="hljs-string">"another animal"</span>)
}
</code></pre>
<p>Enumeration values can be strings, characters, or numbers.</p>
<p>You can also define an enum on a single line:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">case</span> dog, cat, mouse, horse
}
</code></pre>
<p>And you can also add type declaration to the enumeration, and each case has a value of that type assigned:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Animal</span>: <span class="hljs-title">Int</span> </span>{
    <span class="hljs-keyword">case</span> dog = <span class="hljs-number">1</span>
    <span class="hljs-keyword">case</span> cat = <span class="hljs-number">2</span>
    <span class="hljs-keyword">case</span> mouse = <span class="hljs-number">3</span>
    <span class="hljs-keyword">case</span> horse = <span class="hljs-number">4</span>
}
</code></pre>
<p>Once you have a variable, you can get this value using its <code>rawValue</code> property:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Animal</span>: <span class="hljs-title">Int</span> </span>{
    <span class="hljs-keyword">case</span> dog = <span class="hljs-number">1</span>
    <span class="hljs-keyword">case</span> cat = <span class="hljs-number">2</span>
    <span class="hljs-keyword">case</span> mouse = <span class="hljs-number">3</span>
    <span class="hljs-keyword">case</span> horse = <span class="hljs-number">4</span>
}

<span class="hljs-keyword">var</span> animal: <span class="hljs-type">Animal</span>
animal = .dog

animal.rawValue <span class="hljs-comment">//1</span>
</code></pre>
<p>Enumerations are a value type. This means they are copied when passed to a function, or when returned from a function. And when we assign a variable pointing to an enumeration to another variable.</p>
<h2 id="heading-structures-in-swift">Structures in Swift</h2>
<p>Structures are an essential Swift concept.</p>
<p>Structures are everywhere in Swift. Even the built-in types are structures.</p>
<p>We can create instances of structures, which we call <strong>objects</strong>.</p>
<p>In most languages, objects can only be created from classes. Swift has classes, too, but you can create objects also from structures. The official documentation actually advises that you should prefer structures because they are easier to use.</p>
<p>Structures are a light versions of classes.</p>
<p>A struct can:</p>
<ul>
<li>have properties</li>
<li>have methods (functions)</li>
<li>define subscripts</li>
<li>define initializers</li>
<li>conform to protocols</li>
<li>be extended</li>
</ul>
<p>One important thing classes allow is inheritance, so if you need that, you have classes.</p>
<p>A struct is defined using this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span> </span>{

}
</code></pre>
<p>Inside a structure you can define <strong>stored properties</strong>:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
    <span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
}
</code></pre>
<p>This structure definition defines a <strong>type</strong>. To create a new instance with this type, we use this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> roger = <span class="hljs-type">Dog</span>()
</code></pre>
<p>Once you have an instance, you can access its properties using the dot syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> roger = <span class="hljs-type">Dog</span>()
roger.age
roger.name
</code></pre>
<p>The same dot syntax is used to update a property value:</p>
<pre><code class="lang-swift">roger.age = <span class="hljs-number">9</span>
</code></pre>
<p>You can also create a struct instance by passing the values of the properties:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> syd = <span class="hljs-type">Dog</span>(age: <span class="hljs-number">7</span>, name: <span class="hljs-string">"Syd"</span>)
syd.age
syd.name
</code></pre>
<p>To do so, properties must be defined variables with <code>var</code>, not as constants (with <code>let</code>). It's also important to respect the order those properties are defined.</p>
<p>Structures can have <strong>instance methods</strong>: functions that belong to an instance of a structure.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
    <span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"\(name): wof!"</span>)
    }
}
</code></pre>
<p>And we also have <strong>type methods</strong>:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
    <span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"\(name): wof!"</span>)
    }
    <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">hello</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello I am the Dog struct"</span>)
    }
}
</code></pre>
<p>This is invoked as <code>Dog.hello()</code>.</p>
<p>Structures are a value type. This means they are copied when passed to a function, or when returned from a function. And when we assign a variable pointing to a structure to another variable.</p>
<p>This also means that if we want to update the properties of a structure we must define it using <code>var</code> and not <code>let</code>.</p>
<p>All types in Swift are defined as structures: Int, Double, String, arrays and dictionaries, and more are structures.</p>
<h2 id="heading-classes-in-swift">Classes in Swift</h2>
<p>Classes are a bit similar to structures, but they have some key differences.</p>
<p>A class is defined using this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> </span>{

}
</code></pre>
<p>Inside a class you can define stored properties:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">0</span>
}
</code></pre>
<p>A class definition defines a <strong>type</strong>. To create a new instance with this type, we use this syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> roger = <span class="hljs-type">Dog</span>()
</code></pre>
<p>Once you have an instance, you can access its properties using the dot syntax:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> roger = <span class="hljs-type">Dog</span>()
roger.age
</code></pre>
<p>You use the same dot syntax to update a property value:</p>
<pre><code class="lang-swift">roger.age = <span class="hljs-number">9</span>
</code></pre>
<p>One big difference is that classes are reference types. Structures (and enumerations) are value types.</p>
<p>This means that assigning a class instance to another variable does not copy the instance. Both variables point to the same instance:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">0</span>
}

<span class="hljs-keyword">let</span> roger = <span class="hljs-type">Dog</span>()
<span class="hljs-keyword">let</span> syd = roger

roger.age = <span class="hljs-number">9</span>
<span class="hljs-comment">//syd.age == 9</span>
</code></pre>
<p>This also means we can define a reference to a class using <code>let</code>, and we can change its properties, as you saw in the example above.</p>
<p>We can create instances of classes, and we call them <strong>objects</strong>.</p>
<p>As with structs, classes can have properties, methods, and more.</p>
<p>Contrary to structs, we <strong>must</strong> define an initializer in order to initialize the values when we create an instance:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age : <span class="hljs-type">Int</span>

    <span class="hljs-keyword">init</span>(age: <span class="hljs-type">Int</span>) {
        <span class="hljs-keyword">self</span>.age = age
    }
}

<span class="hljs-keyword">let</span> roger = <span class="hljs-type">Dog</span>(age: <span class="hljs-number">9</span>)
</code></pre>
<p>You can only declare properties without initializing them if you have an initializer.</p>
<p>See the use of <code>self</code>. We need it because <code>age</code> is both an instance property and the <code>init(age:)</code> method parameter. <code>self.age</code> references the <code>age</code> instance property.</p>
<p>Classes can have <strong>instance methods</strong>: functions that belong to an instance of a class.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
    <span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> {
      <span class="hljs-built_in">print</span>(<span class="hljs-string">"\(name): wof!"</span>)
    }
}
</code></pre>
<p>And we also have <strong>type methods</strong>:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> </span>{
    <span class="hljs-keyword">var</span> age = <span class="hljs-number">8</span>
    <span class="hljs-keyword">var</span> name = <span class="hljs-string">"Roger"</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"\(name): wof!"</span>)
    }
    <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">hello</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello I am the Dog struct"</span>)
    }
}
</code></pre>
<p>Invoked as <code>Dog.hello()</code>.</p>
<p>One important thing classes allow is inheritance.</p>
<p>A class can inherit all the properties and methods from another class.</p>
<p>Say we have a class <code>Animal</code>. Every animal has an age:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">var</span> age: <span class="hljs-type">Int</span>
}
</code></pre>
<p>Not every animal has a name. Dogs have a name. So we create a <code>Dog</code> class extending from <code>Animal</code>:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span>: <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">var</span> name: <span class="hljs-type">String</span>
}
</code></pre>
<p>Now we must add an initializer for both classes. In the Dog case, after we do the class-specific initialization, we can call the parent class initializer using <code>super.init()</code>:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">var</span> age: <span class="hljs-type">Int</span>

    <span class="hljs-keyword">init</span>(age: <span class="hljs-type">Int</span>) {
        <span class="hljs-keyword">self</span>.age = age
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span>: <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-keyword">var</span> name: <span class="hljs-type">String</span>

    <span class="hljs-keyword">init</span>(age: <span class="hljs-type">Int</span>, name: <span class="hljs-type">String</span>) {
        <span class="hljs-keyword">self</span>.name = name
        <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>(age: age)
    }
}

<span class="hljs-keyword">var</span> horse = <span class="hljs-type">Animal</span>(age: <span class="hljs-number">8</span>)
<span class="hljs-keyword">var</span> roger = <span class="hljs-type">Dog</span>(age: <span class="hljs-number">8</span>, name: <span class="hljs-string">"Roger"</span>)
</code></pre>
<p><code>Animal</code> is now a <strong>superclass</strong>, and <code>Dog</code> is a <strong>subclass</strong>.</p>
<p>There's more to say about classes, but this is a good introduction.</p>
<h2 id="heading-functions-in-swift">Functions in Swift</h2>
<p>Your program's code is organized into functions.</p>
<p>You can declare a function using the <code>func</code> keyword:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"woof!"</span>)
}
</code></pre>
<p>Functions can be assigned to structures, classes and enumerations, and in this case we call them methods.</p>
<p>A function is invoked using its name:</p>
<pre><code class="lang-swift">bark()
</code></pre>
<p>A function can return a value:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">String</span> {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"woof!"</span>)
      <span class="hljs-keyword">return</span> <span class="hljs-string">"barked successfully"</span>
}
</code></pre>
<p>And you can assign it to a variable:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> result = bark()
</code></pre>
<p>A function can accept parameters. Each parameter has a name and a type:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">(times: Int)</span></span> {
    <span class="hljs-keyword">for</span> index <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..&lt;times {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"woof!"</span>)
    }
}
</code></pre>
<p>The name of a parameter is internal to the function.</p>
<p>We use the name of the parameter when we call the function to pass in its value:</p>
<pre><code class="lang-swift">bark(times: <span class="hljs-number">3</span>)
</code></pre>
<p>When we call the function we must pass all the parameters defined.</p>
<p>Here is a function that accepts multiple parameters:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">(times: Int, repeatBark: Bool)</span></span> {
    <span class="hljs-keyword">for</span> index <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..&lt;times {
        <span class="hljs-keyword">if</span> repeatBark == <span class="hljs-literal">true</span> {
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"woof woof!"</span>)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"woof!"</span>)
        }            
    }
}
</code></pre>
<p>In this case you call it in this way:</p>
<pre><code class="lang-swift">bark(times: <span class="hljs-number">3</span>, <span class="hljs-keyword">repeat</span>: <span class="hljs-literal">true</span>)
</code></pre>
<p>When we talk about this function, we don't call it <code>bark()</code>. We call it <code>bark(times:repeat:)</code>.</p>
<p>This is because we can have multiple functions with the same name, but different set of parameters.</p>
<p>You can avoid using labels by using the <code>_</code> keyword:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">(<span class="hljs-number">_</span> times: Int, repeatBark: Bool)</span></span> {
    <span class="hljs-comment">//...the function body</span>
}
</code></pre>
<p>So you can invoke it in this way:</p>
<pre><code class="lang-swift">bark(<span class="hljs-number">3</span>, <span class="hljs-keyword">repeat</span>: <span class="hljs-literal">true</span>)
</code></pre>
<p>It's common in Swift and iOS APIs to have the first parameter with no label, and the other parameters labeled.</p>
<p>It makes for a nice and expressive API, when you design the names of the function and the parameters nicely.</p>
<p>You can only return one value from a function. If you need to return multiple values, it's common to return a tuple:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span></span> -&gt; (<span class="hljs-type">String</span>, <span class="hljs-type">Int</span>) {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"woof!"</span>)
      <span class="hljs-keyword">return</span> (<span class="hljs-string">"barked successfully"</span>, <span class="hljs-number">1</span>)
}
</code></pre>
<p>And you can assign the result to a tuple:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> (result, num) = bark()

<span class="hljs-built_in">print</span>(result) <span class="hljs-comment">//"barked successfully"</span>
<span class="hljs-built_in">print</span>(num) <span class="hljs-comment">//1</span>
</code></pre>
<p>You can nest functions inside other functions. When this happens, the inner function is invisible to outside the outer function.</p>
<h2 id="heading-protocols-in-swift">Protocols in Swift</h2>
<p>A protocol is a way to have different objects, of different types, have a common set of functionalities.</p>
<p>You define a protocol like this:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">Mammal</span> </span>{

}
</code></pre>
<p>Structs and classes can <strong>adopt a protocol</strong> in this way:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span>: <span class="hljs-title">Mammal</span> </span>{

}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span>: <span class="hljs-title">Mammal</span> </span>{

}
</code></pre>
<p>A protocol can define properties and methods, without providing values and implementations, and a struct/class must implement them:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">Mammal</span> </span>{
    <span class="hljs-keyword">var</span> age: <span class="hljs-type">Int</span> { <span class="hljs-keyword">get</span> <span class="hljs-keyword">set</span> }
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">walk</span><span class="hljs-params">()</span></span>
}
</code></pre>
<p>The property can be defined as <code>get</code> or <code>get set</code>. If it's <code>get</code>, the property must be implemented as read only, with a getter.</p>
<p>Any type that adopts the protocol must <strong>conform</strong> to the protocol by implementing those methods or providing those properties:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span>: <span class="hljs-title">Mammal</span> </span>{
    <span class="hljs-keyword">var</span> age: <span class="hljs-type">Int</span> = <span class="hljs-number">0</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">walk</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"The dog is walking"</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span>: <span class="hljs-title">Mammal</span> </span>{
    <span class="hljs-keyword">var</span> age: <span class="hljs-type">Int</span> = <span class="hljs-number">0</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">walk</span><span class="hljs-params">()</span></span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"The cat is walking"</span>)
    }
}
</code></pre>
<p>Structs and classes can adopt multiple protocols:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Dog</span>: <span class="hljs-title">Mammal</span>, <span class="hljs-title">Animal</span> </span>{

}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span>: <span class="hljs-title">Mammal</span>, <span class="hljs-title">Animal</span> </span>{

}
</code></pre>
<p>Notice that for classes, this is the same syntax used to define a superclass. If there is a superclass, list it as the first item in the list, after the colon.</p>
<h2 id="heading-where-to-go-from-here">Where to Go From Here</h2>
<p>I hope this little handbook was useful in shining a light on how to get started with Swift. And I hope you are now interested to learn more about it!</p>
<p>I can now point you to a few places to learn more:</p>
<ul>
<li><a target="_blank" href="https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html">The official Swift Language Guide</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/swift/swift-standard-library/">The Swift Standard Library</a></li>
<li><a target="_blank" href="https://developer.apple.com/videos/swift">WWDC Swift videos</a></li>
</ul>
<p><a target="_blank" href="https://thevalleyofcode.com/download/swift/">You can get a PDF and ePub version of this Swift Beginner's Handbook here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement a GameKit Leaderboard in SwiftUI ]]>
                </title>
                <description>
                    <![CDATA[ By Saamer Mansoor In this article we will talk about why and how to implement the GameCenter's Leaderboard within your app.  Why GameCenter is Making a Huge Revival You can make iPhone games without a scoreboard, but leaderboards can help make the ga... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-implement-a-leaderboard-in-swiftui/</link>
                <guid isPermaLink="false">66d460c537bd2215d1e245bb</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Games ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SwiftUI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 19 Aug 2022 21:00:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/IMG_45B142A26F90-1-copy.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Saamer Mansoor</p>
<p>In this article we will talk about why and how to implement the <a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines/technologies/game-center/leaderboards/">GameCenter's Leaderboard</a> within your app. </p>
<h2 id="heading-why-gamecenter-is-making-a-huge-revival">Why GameCenter is Making a Huge Revival</h2>
<p>You can make iPhone games without a scoreboard, but leaderboards can help make the game feel more competitive, like people are competing against one another around the World. </p>
<p>Instead of creating and managing your own backend, the GameCenter Leaderboard allows you to scale with traffic infinitely, skip an entire login page for authorization, get the Image, Name, and friends playing the same game – all without your users having to enter anything. </p>
<p>Especially with iOS 16, <a target="_blank" href="https://developer.apple.com/game-center/">Apple is investing more in improving it</a>, and driving more app usage, like through Push Notifications when your friend beats your score in the game.</p>
<p>In my journey of learning SwiftUI, I have been creating and publishing apps, because IMO that's the best way to learn. </p>
<p>There wasn't much updated documentation on how to do a lot of this, especially none with SwiftUI nor with the <a target="_blank" href="https://www.freecodecamp.org/news/make-rest-api-call-in-swiftui-in-2-minutes/">advent of async and await in Swift</a>. So I consolidated and simplified it for everyone to build amazing apps. So feel free to invite me to test your apps too!</p>
<h3 id="heading-pre-requisites">Pre-Requisites:</h3>
<ul>
<li>You'll need to have an <a target="_blank" href="https://developer.apple.com/programs/">Apple Developer</a> paid account</li>
<li>You have to create the <a target="_blank" href="https://support.magplus.com/hc/en-us/articles/203808708-iOS-Creating-App-IDs">App Id for your app</a> in the provisioning profiles section of the Apple Developer Portal</li>
<li>You have to <a target="_blank" href="https://support.staffbase.com/hc/en-us/articles/115003481992-Creating-an-App-Profile-in-App-Store-Connect">create the App in the iTunes Connect Connect</a> portal</li>
</ul>
<h2 id="heading-how-to-implement-your-ios-leaderboard-in-6-steps">How to Implement Your iOS Leaderboard in 6 Steps</h2>
<p>Most of the code logic for the leaderboard is in <a target="_blank" href="https://github.com/StairMasterClimber/mobile/blob/main/StairStepperMaster/StairStepperMaster/Views/LeadersTileView.swift">this file if you want to skip ahead</a>. Here's the steps as follows:</p>
<h3 id="heading-1-how-to-create-the-app-store-connect-leaderboard">1. How to Create the App Store Connect Leaderboard</h3>
<p><img src="https://user-images.githubusercontent.com/8262287/180824532-2e27ca8a-c1c0-4676-b439-f3ab09887271.png" alt="image" width="1348" height="754" loading="lazy">
<em>Screenshot from the Apple iTunes Connect Portal</em></p>
<p>Once you have created the app in the App Store Connect portal successfully, go to the Services tab for the app -&gt; and make sure you're in the GameCenter page.</p>
<p>Then add a new leaderboard using the "+" sign, which can either be "Classic" (scores never reset) or "Recurring" (scores reset based on your frequency settings).</p>
<p>Most games prefer a recurring leaderboard so that the leaderboard isn't cluttered with older impossible to reach high scores.</p>
<p>The LeaderboardID you input there is the one that you need to use in all the places in the code that ask for it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-122.png" alt="Image" width="600" height="400" loading="lazy">
<em>Details required to create a new Leaderboard</em></p>
<h3 id="heading-2-how-to-set-up-gamecenter-authentication">2. How to Set Up GameCenter Authentication</h3>
<p>First, you'll need to authenticate users to GameCenter in order for any of this functionality to work.</p>
<p>So we'll use this code to do that, which basically makes sure that you (GKLocalPlayer.local) are authenticated, or prints an error if there is one:</p>
<pre><code>func authenticateUser() {
    GKLocalPlayer.local.authenticateHandler = { vc, error <span class="hljs-keyword">in</span>
        guard error == nil <span class="hljs-keyword">else</span> {
            print(error?.localizedDescription ?? <span class="hljs-string">""</span>)
            <span class="hljs-keyword">return</span>
        }
    }
}
</code></pre><p>If the user is authenticated, you will see a little popup in the UI. If not, the user will be taken to a page to login to their GameCenter account.</p>
<p><img src="https://user-images.githubusercontent.com/8262287/180823235-cafefcfa-3d25-46e5-8524-d7f475b9a000.png" alt="image" width="464" height="94" loading="lazy">
<em>A sign that displays when a user is logged in</em></p>
<h3 id="heading-3-how-to-display-leaderboard-items-in-the-ui">3. How to Display Leaderboard Items in the UI</h3>
<p>In order to get the data away from the GameCenter ViewController leaderboards (GKLeaderboard), you need to use the <code>loadLeaderboards</code> . </p>
<p>You can switch up the <code>loadEntries</code> function from <code>.global</code> to <code>.friends</code> in order to only pull your friends. </p>
<p>You can also retrieve the image for each player by iterating over each player and performing a <code>loadPhoto</code>. </p>
<p>Using <code>NSRang(1...5)</code>, you can choose how many players to display. This pulls the users with the highest 5 scores from the leaderboard and returns none if there's no users, such as in the case when the cycle refreshes for a recurring Leaderboard.</p>
<p>This is what pulling data from a leaderboard could look like if you take advantage of async-await:</p>
<pre><code>func loadLeaderboard() <span class="hljs-keyword">async</span> {
    playersList.removeAll()
    Task{
        <span class="hljs-keyword">var</span> playersListTemp : [Player] = []
        <span class="hljs-keyword">let</span> leaderboards = <span class="hljs-keyword">try</span> <span class="hljs-keyword">await</span> GKLeaderboard.loadLeaderboards(IDs: [leaderboardIdentifier])
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> leaderboard = leaderboards.filter ({ $<span class="hljs-number">0.</span>baseLeaderboardID == self.leaderboardIdentifier }).first {
            <span class="hljs-keyword">let</span> allPlayers = <span class="hljs-keyword">try</span> <span class="hljs-keyword">await</span> leaderboard.loadEntries(<span class="hljs-keyword">for</span>: .global, <span class="hljs-attr">timeScope</span>: .allTime, <span class="hljs-attr">range</span>: NSRange(<span class="hljs-number">1.</span>.<span class="hljs-number">.5</span>))
            <span class="hljs-keyword">if</span> allPlayers<span class="hljs-number">.1</span>.count &gt; <span class="hljs-number">0</span> {
                <span class="hljs-keyword">try</span> <span class="hljs-keyword">await</span> allPlayers<span class="hljs-number">.1</span>.asyncForEach { leaderboardEntry <span class="hljs-keyword">in</span>
                    <span class="hljs-keyword">var</span> image = <span class="hljs-keyword">try</span> <span class="hljs-keyword">await</span> leaderboardEntry.player.loadPhoto(<span class="hljs-keyword">for</span>: .small)
                    playersListTemp.append(Player(name: leaderboardEntry.player.displayName, <span class="hljs-attr">score</span>:leaderboardEntry.formattedScore, <span class="hljs-attr">image</span>: image))
                                print(playersListTemp)
                    playersListTemp.sort{
                        $<span class="hljs-number">0.</span>score &lt; $<span class="hljs-number">1.</span>score
                    }
                }
            }
        }
        playersList = playersListTemp            
    }
}
</code></pre><p><img src="https://user-images.githubusercontent.com/8262287/180823292-2dee4f9a-4894-4442-9241-2ad1c84b1cf7.png" alt="image" width="622" height="240" loading="lazy">
<em>You can get leaderboard data into your app</em></p>
<h3 id="heading-4-how-to-call-functionality-in-swiftui-as-the-viewpage-appears">4. How to Call Functionality in SwiftUI as the View/Page Appears</h3>
<p>You can take advantage of the <code>onAppear</code> <a target="_blank" href="https://www.hackingwithswift.com/quick-start/swiftui/how-to-respond-to-view-lifecycle-events-onappear-and-ondisappear">lifecycle function of the view</a> to actually make the calls to authenticate and load, but you can also do it on the tap of a button if you prefer that:</p>
<pre><code>.onAppear(){
    <span class="hljs-keyword">if</span> !GKLocalPlayer.local.isAuthenticated {
        authenticateUser()
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> playersList.count == <span class="hljs-number">0</span> {
        Task{
            <span class="hljs-keyword">await</span> loadLeaderboard()
        }
    }
}
</code></pre><h3 id="heading-5-how-to-load-the-submitted-scores">5. How to Load the Submitted Scores</h3>
<p>In order to load the scores, you need to submit them as well. The <code>submitScore</code> function can help you with that.</p>
<ul>
<li>The <code>flightsClimbed</code> variable should contain the score that you would like to submit.</li>
<li>GameKit makes sure to only display your best score for the life of the leaderboard.</li>
<li>The <code>leaderboardId</code> contains the value that you manually enter in your App Store Connect account:</li>
</ul>
<pre><code>func leaderboard() <span class="hljs-keyword">async</span>{
    Task{
        <span class="hljs-keyword">try</span> <span class="hljs-keyword">await</span> GKLeaderboard.submitScore(
            flightsClimbed,
            <span class="hljs-attr">context</span>: <span class="hljs-number">0</span>,
            <span class="hljs-attr">player</span>: GKLocalPlayer.local,
            <span class="hljs-attr">leaderboardIDs</span>: [<span class="hljs-string">"com.tfp.stairsteppermaster.flights"</span>]
        )
    }
    calculateAchievements()
}
</code></pre><h3 id="heading-6-how-to-display-the-gamecenter-viewcontroller-portal">6. How to display the GameCenter ViewController Portal</h3>
<p>When you're logged into GameCenter, a little annoying icon appears in the top right of your screen. When you tap on it, you are taken to the GameCenter ViewController. Luckily you can hide it if it's not part of your design, using <code>GKAccessPoint.shared.isActive = false</code>. </p>
<p>Since the GameCenter UI is a UIKit <code>ViewController</code> and not a simple SwiftUI <code>View</code>, you need to create this <a target="_blank" href="https://www.hackingwithswift.com/books/ios-swiftui/wrapping-a-uiviewcontroller-in-a-swiftui-view">UIViewControllerRepresentable</a> first (as you can <a target="_blank" href="https://github.com/StairMasterClimber/mobile/blob/main/StairStepperMaster/StairStepperMaster/Views/GameCenterView.swift">see here</a>), to launch GameCenter using a different button, </p>
<p>Once you add that file to your project, you can display the GameCenter portal simply using this: <code>GameCenterView(format: gameCenterViewControllerState)</code> where gameCenterViewControllerState can be help you go to a detail page in GameCenter.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Frame-3-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>GameCenter's Leaderboard View</em></p>
<h2 id="heading-things-to-keep-in-mind-while-using-gamecenters-leaderboards">Things to Keep in Mind While using GameCenter's Leaderboards:</h2>
<ul>
<li>Simulator Debugging – For some reason the authenticate to GameCenter is extremely slow on a simulator, so it might make sense to even create a mock of data when using the simulator.</li>
<li>Challenges – You can't programmatically issue GameKit Challenges to your friends anymore <a target="_blank" href="https://developer.apple.com/documentation/gamekit/gkscore/1520610-issuechallenge">due to deprecation</a>. Instead, you have to do those manually within the user's GameCenter dashboard against GameKit Achievements. Also, there's no way to view challenges you have sent. </li>
<li>Achievements – Leaderboards are different from the GameKit Achievements, which is calculated and displayed differently, but a <a target="_blank" href="https://github.com/StairMasterClimber/mobile/blob/18283a68e1c5cac4e270a85b03853887b3950156/StairStepperMaster/StairStepperMaster/Views/AchievementTileView.swift#L113">lot easier</a>. Those can also be pulled into the app as well, as you can see below:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Frame-2-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>GameKit Challenges and Achievements</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>You can try out the free open-source <a target="_blank" href="https://stairmasterclimber.com/app">Stair Master Climber iPhone Health &amp; Fitness app</a> that I shared above. I would love to know what you think so that we can learn together. </p>
<p>Feel free to reach out to me on <a target="_blank" href="https://twitter.com/StairMasterApp">social media</a> or by <a target="_blank" href="mailto:hi@stairmasterclimber.com">email</a> if you have any questions.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use UISearchController in iOS Apps ]]>
                </title>
                <description>
                    <![CDATA[ By Sai Balaji K Hello everyone! In this article we are going to learn how to use UISearchController in iOS Apps. What are we going to build? We are going to build a movie search application which uses the TMDB API to fetch movie info and display it u... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-to-use-uisearchcontroller-in-ios-apps/</link>
                <guid isPermaLink="false">66d460c7b3016bf139028d85</guid>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ios app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Xcode ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 24 Mar 2022 15:55:58 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-21-at-8.11.31-PM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sai Balaji K</p>
<p>Hello everyone! In this article we are going to learn how to use UISearchController in iOS Apps.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We are going to build a movie search application which uses the <a target="_blank" href="https://www.themoviedb.org/">TMDB</a> API to fetch movie info and display it using a UICollectionView based on a user's search query.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Open up Xcode and create a new blank iOS App project – make sure you select UIKit and not SwiftUI.</p>
<p>In this app we are going to use the MVC Pattern so organise the project by creating the following groups and Swift files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-21-at-8.16.02-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now close your Xcode project. Open up the terminal and move to your project directory. Here we need to add <a target="_blank" href="https://cocoapods.org/pods/SDWebImage">SD WebImage</a> Cocoa Pods to asynchronously download and cache the movie poster images.</p>
<p>Type the following command in the terminal:</p>
<pre><code>pod init
</code></pre><p>Now when you list the contents of the directory, you can see that there is a new Podfile. Open the file using any text editor (here I've used Vim). Edit your Podfile so that it looks similar to the below image. Save and close the Podfile.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-21-at-8.20.28-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now that we have specified the SD WebImage, we can install the dependencies by running the below command:</p>
<pre><code>pod install
</code></pre><p>As you can see, we have successfully added the SD WebImage pod in our iOS project. Now run the below command to open our project in Xcode.</p>
<pre><code>open PROJECT_NAME.xcworkspace
</code></pre><p>After opening Xcode, make sure you build your project by hitting Command+B.</p>
<h2 id="heading-how-to-design-the-user-interface-using-uikit-and-programmatic-ui"><strong>How to Design the User Interface using UIKit and Programmatic UI</strong></h2>
<p>Our app needs three UIElements navigation bars to hold the search bar, UISearchBarController for actual search, and a UICollectionView to display the search results.</p>
<p>Open up your Scenedelegate.swift file and add the following code inside it which will connect to the session method:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">scene</span><span class="hljs-params">(<span class="hljs-number">_</span> scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)</span></span> {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> scene = (scene <span class="hljs-keyword">as</span>? <span class="hljs-type">UIWindowScene</span>) <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
        window = <span class="hljs-type">UIWindow</span>(windowScene: scene)       window?.rootViewController=<span class="hljs-type">UINavigationController</span>(rootViewController:<span class="hljs-type">HomeVC</span>())
        window?.makeKeyAndVisible()
    }
</code></pre>
<p>Since we are using a programatic UI, first we need to mention our Root View controller – that is, the first screen which will be displayed when the user launches the app. </p>
<p>Here in this app we're using only one View Controller, so we wrap it inside a UINavigationController. This provides a navigation bar where we can place our UISearchController.</p>
<p>Open up the HomeVC.swift file and add the following properties:</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> <span class="hljs-type">SearchBar</span>: <span class="hljs-type">UISearchController</span> = {
        <span class="hljs-keyword">let</span> sb = <span class="hljs-type">UISearchController</span>()
        sb.searchBar.placeholder = <span class="hljs-string">"Enter the movie name"</span>
        sb.searchBar.searchBarStyle = .minimal
        <span class="hljs-keyword">return</span> sb
    }()

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> <span class="hljs-type">MovieCollectionView</span>: <span class="hljs-type">UICollectionView</span> = {
        <span class="hljs-keyword">let</span> layout = <span class="hljs-type">UICollectionViewFlowLayout</span>()
        layout.scrollDirection = .vertical
        layout.itemSize = <span class="hljs-type">CGSize</span>(width: <span class="hljs-type">UIScreen</span>.main.bounds.width/<span class="hljs-number">3</span> - <span class="hljs-number">10</span>, height: <span class="hljs-number">200</span>)
        <span class="hljs-keyword">let</span> cv = <span class="hljs-type">UICollectionView</span>(frame: .zero, collectionViewLayout: layout)
        cv.register(<span class="hljs-type">MovieCell</span>.<span class="hljs-keyword">self</span>, forCellWithReuseIdentifier: <span class="hljs-type">MovieCell</span>.<span class="hljs-type">ID</span>)
        <span class="hljs-keyword">return</span> cv
    }()
</code></pre>
<p>First we create our UISearchController and configure its properties such as placeholder text and style. </p>
<p>Then we create a UICollectionView and specify the type of layout our collection view should use. In this case it is UICollectionViewFlowLayout and other properties such as scroll direction, item size, and specifying a custom CollectionView cell class which we will create later in our project.</p>
<p>Inside the HomeVC class create a new function and add the following code to configure auto-layout constraints programmatically for our UICollectionView:</p>
<pre><code class="lang-swift">    <span class="hljs-comment">//MARK: - HELPERS</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">configureUI</span><span class="hljs-params">()</span></span>{
        <span class="hljs-type">MovieCollectionView</span>.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
        <span class="hljs-type">MovieCollectionView</span>.topAnchor.constraint(equalTo: view.topAnchor).isActive = <span class="hljs-literal">true</span>
        <span class="hljs-type">MovieCollectionView</span>.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = <span class="hljs-literal">true</span>
        <span class="hljs-type">MovieCollectionView</span>.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = <span class="hljs-literal">true</span>
        <span class="hljs-type">MovieCollectionView</span>.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = <span class="hljs-literal">true</span>
    }
</code></pre>
<p>First we say that we don't need to convert the auto resizing mask into the constraints. Then we pin our collection view to all four sides of our View Controller.</p>
<p>Inside the <code>viewDidLoad()</code> method add the following lines of code:</p>
<pre><code class="lang-swift">  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">viewDidLoad</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">super</span>.viewDidLoad()

        navigationItem.title  = <span class="hljs-string">"Movie Search"</span>
        view.backgroundColor = .systemBackground
        <span class="hljs-type">SearchBar</span>.searchResultsUpdater = <span class="hljs-keyword">self</span>
        navigationItem.searchController = <span class="hljs-type">SearchBar</span>
        view.addSubview(<span class="hljs-type">MovieCollectionView</span>)
        <span class="hljs-type">MovieCollectionView</span>.delegate = <span class="hljs-keyword">self</span>
        <span class="hljs-type">MovieCollectionView</span>.dataSource = <span class="hljs-keyword">self</span>
        configureUI()
    }
</code></pre>
<p>Here we first specify the title for our ViewController followed by the background color which is the systemBackground color. If the device is in light mode it shows a white background. If it is in dark mode, then it shows a dark background. </p>
<p>Then we set current the view controller as the search result updater, then add our SearchController to the navigation bar, add the UICollectionView to the ViewController, and setup delegate and datasource. Finally we pin the UICollectionView by using auto-layout.</p>
<p>Create an extension for HomeVC and implement the UISearchResultsUpdating protocol and its stub method updateSearchResults.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">HomeVC</span>: <span class="hljs-title">UISearchResultsUpdating</span></span>{

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateSearchResults</span><span class="hljs-params">(<span class="hljs-keyword">for</span> searchController: UISearchController)</span></span> {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> query = searchController.searchBar.text <span class="hljs-keyword">else</span>{<span class="hljs-keyword">return</span>}

        }

    }


}
</code></pre>
<p>The <code>updateSearchResults()</code> method will be called whenever the text entered in the search bar changes or when the user taps the search button on their keyboard.</p>
<p>Next we need to create that custom UICollectionView cell. Inside the MovieCell.swift file, add the following code:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-keyword">import</span> UIKit
<span class="hljs-keyword">import</span> SDWebImage

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MovieCell</span>: <span class="hljs-title">UICollectionViewCell</span></span>{

    <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> <span class="hljs-type">ID</span> = <span class="hljs-string">"MovieCell"</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> <span class="hljs-type">MoviePosterImageView</span>: <span class="hljs-type">UIImageView</span> = {
        <span class="hljs-keyword">let</span> imageView = <span class="hljs-type">UIImageView</span>()
        imageView.contentMode = .scaleAspectFit
      <span class="hljs-comment">//  imageView.image = UIImage(systemName: "house")</span>
        <span class="hljs-keyword">return</span> imageView
    }()

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">init</span>(frame: <span class="hljs-type">CGRect</span>) {
        <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>(frame: frame)
        addSubview(<span class="hljs-type">MoviePosterImageView</span>)
        configureUI()
    }

    <span class="hljs-keyword">required</span> <span class="hljs-keyword">init</span>?(coder: <span class="hljs-type">NSCoder</span>) {
        <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"init(coder:) has not been implemented"</span>)
    }

}

<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">MovieCell</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">configureUI</span><span class="hljs-params">()</span></span>{
        <span class="hljs-type">MoviePosterImageView</span>.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
        <span class="hljs-type">MoviePosterImageView</span>.topAnchor.constraint(equalTo: topAnchor).isActive = <span class="hljs-literal">true</span>
        <span class="hljs-type">MoviePosterImageView</span>.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = <span class="hljs-literal">true</span>
        <span class="hljs-type">MoviePosterImageView</span>.leftAnchor.constraint(equalTo: leftAnchor).isActive = <span class="hljs-literal">true</span>
        <span class="hljs-type">MoviePosterImageView</span>.rightAnchor.constraint(equalTo: rightAnchor).isActive = <span class="hljs-literal">true</span>
    }
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateCell</span><span class="hljs-params">(posterURL: String?)</span></span>{
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> posterURL = posterURL {
            <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-type">CompleteURL</span> = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"https://image.tmdb.org/t/p/w500/\(posterURL)"</span>) <span class="hljs-keyword">else</span> {<span class="hljs-keyword">return</span>}
            <span class="hljs-keyword">self</span>.<span class="hljs-type">MoviePosterImageView</span>.sd_setImage(with: <span class="hljs-type">CompleteURL</span>)
        }

    }
}
</code></pre>
<p>Here we create our custom collection view cell by sub-classing the UICollectionView class and implementing the <code>init()</code> functions. </p>
<p>We create a UIImageView to display the movie poster image and setup auto-layout constraints for it. Then we create a user defined function which takes the Movie poster URL string a parameter and downloads it asynchronously without affecting the UI Thread/Main thread. It does this by using the SD WebImage CocoaPod which we added earlier.</p>
<h2 id="heading-how-to-set-up-our-api">How to Set Up Our API</h2>
<p>Before moving on, you'll need to get your API key for the <a target="_blank" href="https://www.themoviedb.org/">TMDB</a> API by creating an account (it's free). We are going to use the Movie Search end point of the API which takes the API Key and movie name as parameters.</p>
<pre><code class="lang-url">https://api.themoviedb.org/3/search/movie?api_key=API_KEY_HERE&amp;query=batman
</code></pre>
<p>You can examine the API response by running it in Postman.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/Screenshot-2022-03-22-at-8.52.57-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-create-a-model-for-the-api-response">How to Create a Model for the API Response</h2>
<p>Now we get a JSON response from the API. We need to decode them to Swift which we can do by creating a model struct that implements the Codable protocol.</p>
<p>WE can generate the model struct for our JSON response easily by using JSON to Swift websites. Here is the model code for the API response – you can just copy and paste it inside the Model.swift file:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TrendingTitleResponse</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> results: [<span class="hljs-type">Title</span>]
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Title</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> media_type: <span class="hljs-type">String?</span>
    <span class="hljs-keyword">let</span> original_name: <span class="hljs-type">String?</span>
    <span class="hljs-keyword">let</span> original_title: <span class="hljs-type">String?</span>
    <span class="hljs-keyword">let</span> poster_path: <span class="hljs-type">String?</span>
    <span class="hljs-keyword">let</span> overview: <span class="hljs-type">String?</span>
    <span class="hljs-keyword">let</span> vote_count: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> release_date: <span class="hljs-type">String?</span>
    <span class="hljs-keyword">let</span> vote_average: <span class="hljs-type">Double</span>
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">YoutubeSearchResponse</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> items: [<span class="hljs-type">VideoElement</span>]
}


<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">VideoElement</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">IdVideoElement</span>
}


<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">IdVideoElement</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> kind: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> videoId: <span class="hljs-type">String</span>
}
</code></pre>
<h2 id="heading-how-to-perform-http-requests-using-swift">How to Perform  HTTP Requests Using Swift</h2>
<p>Now we need to write some Swift code to perform HTTP GET requests which return the JSON response of the API. </p>
<p>Swift provides a URLSession class which makes it easier to write networking code without needing any third party libraries like AFNetworking, AlamoFire, and so on.</p>
<p>Open APIService.swift and add the following code:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">APIService</span></span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> shared = <span class="hljs-type">APIService</span>()
    <span class="hljs-keyword">let</span> session = <span class="hljs-type">URLSession</span>(configuration: .<span class="hljs-keyword">default</span>)

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getMovies</span><span class="hljs-params">(<span class="hljs-keyword">for</span> Query: String,completion:@escaping<span class="hljs-params">([Title]?,Error?)</span></span></span>-&gt;<span class="hljs-type">Void</span>){
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-type">FormatedQuery</span> = <span class="hljs-type">Query</span>.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)  <span class="hljs-keyword">else</span>{<span class="hljs-keyword">return</span>}

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span>  <span class="hljs-type">SEARCH_URL</span> = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"https://api.themoviedb.org/3/search/movie?api_key=API_KEY_HERE&amp;query=\(FormatedQuery)"</span>) <span class="hljs-keyword">else</span> {<span class="hljs-built_in">print</span>(<span class="hljs-string">"INVALID"</span>)
            <span class="hljs-keyword">return</span>}



        <span class="hljs-keyword">let</span> task = session.dataTask(with: <span class="hljs-type">SEARCH_URL</span>) { data, response, error <span class="hljs-keyword">in</span>
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> error = error {
                <span class="hljs-built_in">print</span>(error.localizedDescription)
                completion(<span class="hljs-literal">nil</span>,error)
            }
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> data = data {
                <span class="hljs-keyword">do</span>{
                    <span class="hljs-keyword">let</span> decodedData = <span class="hljs-keyword">try</span> <span class="hljs-type">JSONDecoder</span>().decode(<span class="hljs-type">TrendingTitleResponse</span>.<span class="hljs-keyword">self</span>, from: data)
                 <span class="hljs-comment">//   print(decodedData)</span>
                    completion(decodedData.results,<span class="hljs-literal">nil</span>)
                }
                <span class="hljs-keyword">catch</span>{
                    <span class="hljs-built_in">print</span>(error)
                }
            }
        }
        task.resume()
    }
}
</code></pre>
<p>Here we created a class named API Service with the singleton pattern so we need an instance for this class as a static member of the class. Then we created a session for our networking task with the default configuration, followed by a user defined method getMovies(). </p>
<p>Then we created our networking task – in this case we need to perform HTTP GET requests which can be performed using the <code>dataTask()</code> method of the URLSession class. It takes the URL as a parameter and gives a completion handler which contains data returned from the API, error data if any error has occurred, and a response which has HTTP Response information such as status codes and their corresponding messages. </p>
<p>If there is any error, then we escape out of this function with error data. If not, then we decode our JSON data based on our Swift Model and escape out of this function with the decoded data.</p>
<h2 id="heading-how-to-display-the-search-results-on-the-uicollectionview">How to Display the Search Results on the UICollectionView</h2>
<p>In HomeVC.swift, create a private property which is an array of Title objects. These will hold each movie's info returned by the API.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> <span class="hljs-type">Movies</span> = [<span class="hljs-type">Title</span>]()
</code></pre>
<p>In HomeVC.swift create an extension for the HomeVC class and implement the UIColletionViewDelegate and UICollectionViewDatasource protocols. Then implement numberOfItemsInSection (which is equal to the number of movies returned by the API) and cellForItemAt (which actually populates the cell with API responses, like download and set the poster image).</p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, numberOfItemsInSection section: Int)</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-type">Movies</span>.<span class="hljs-built_in">count</span>
    }
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)</span></span> -&gt; <span class="hljs-type">UICollectionViewCell</span> {
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> cell = collectionView.dequeueReusableCell(withReuseIdentifier: <span class="hljs-type">MovieCell</span>.<span class="hljs-type">ID</span>, <span class="hljs-keyword">for</span>: indexPath) <span class="hljs-keyword">as</span>? <span class="hljs-type">MovieCell</span>{
           <span class="hljs-comment">// cell.backgroundColor = .systemBackground</span>

            cell.updateCell(posterURL: <span class="hljs-type">Movies</span>[indexPath.row].poster_path)
            <span class="hljs-keyword">return</span> cell
        }
        <span class="hljs-keyword">return</span> <span class="hljs-type">UICollectionViewCell</span>()

    }
</code></pre>
<p>Finally we need to make actual API call which we do inside the <code>updateSearchResults()</code> delegate method which we have implemented previously. Inside that method add the following code:</p>
<pre><code class="lang-swift">    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateSearchResults</span><span class="hljs-params">(<span class="hljs-keyword">for</span> searchController: UISearchController)</span></span> {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> query = searchController.searchBar.text <span class="hljs-keyword">else</span>{<span class="hljs-keyword">return</span>}
        <span class="hljs-type">APIService</span>.shared.getMovies(<span class="hljs-keyword">for</span>:query.trimmingCharacters(<span class="hljs-keyword">in</span>: .whitespaces)) { titles, error <span class="hljs-keyword">in</span>
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> titles = titles {
                <span class="hljs-keyword">self</span>.<span class="hljs-type">Movies</span> = titles
                <span class="hljs-type">DispatchQueue</span>.main.async {
                    <span class="hljs-keyword">self</span>.<span class="hljs-type">MovieCollectionView</span>.reloadData()
                }

            }
        }

    }
</code></pre>
<p>Here, whenever the user types in the search bar or presses the search button, we make an HTTP GET request to fetch a movie (based on the name entered in the search bar). Then we reload the CollectionView which updates the collection view cells with the movie poster. </p>
<p>Note that we need to do this in the Main Thread/UI Thread, because by default iOS automatically makes HTTP request in background thread. This means that we need to use UI/Main Thread to update our UI elements. </p>
<p>Now run your app in the simulator to see the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/ezgif.com-gif-maker--3-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Congratulations! You have learned to use UISearchController in iOS apps.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn iOS Development by Building a Netflix Clone ]]>
                </title>
                <description>
                    <![CDATA[ Swift is one of the main languages used for iOS development. What better way to learn how to build an iOS app than to recreate a popular app? We just published a 5-hour course on the freeCodeCamp.org YouTube channel that will teach you how to use Swi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-ios-development-by-building-a-netflix-clone/</link>
                <guid isPermaLink="false">66b20496712508eb16067887</guid>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 15 Feb 2022 22:02:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/maxresdefault-1.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Swift is one of the main languages used for iOS development. What better way to learn how to build an iOS app than to recreate a popular app?</p>
<p>We just published a 5-hour course on the freeCodeCamp.org YouTube channel that will teach you how to use Swift 5, UIKit, and Xcode to develop iOS apps by building a Netflix clone.</p>
<p>Amr created this course. Amr is an iOS developer who has created many popular tutorials.</p>
<p>In this course you will learn how to implement the MVVM design pattern and create the app from scratch in Xcode. The Netflix code will play videos using the YouTube API.</p>
<p>Here are the sections in this course:</p>
<ul>
<li>Introduction and App Demo</li>
<li>Creating new Xcode Project</li>
<li>Creating MainTabBarViewController</li>
<li>Setting HomeViewController TableView</li>
<li>Setting home TableViewCell and it’s CollectionView</li>
<li>Creating Table’s HeaderView</li>
<li>Customizing the navigation bar</li>
<li>Setting Tableview sections titles</li>
<li>Sending URL Requests and Parsing JSON response</li>
<li>Using Extensions</li>
<li>Consuming API To Fetch Data for each Section</li>
<li>Refactoring Models</li>
<li>Creating Custom CollectionViewCell</li>
<li>Passing data to the CollectionView </li>
<li>Viewing poster images inside CollectionViewCell</li>
<li>Creating Upcoming TableView inside Upcoming Tab</li>
<li>Creating custom TableViewCell from the upcoming table</li>
<li>Creating TitleViewModel</li>
<li>Creating Top Search TableView inside TopSearch tab</li>
<li>Creating SearchResultsViewController to display search results</li>
<li>Querying database for individual movie</li>
<li>Using YouTube API</li>
<li>Parsing YouTube API Response</li>
<li>Handling selections of cells (Tapping on cells)</li>
<li>Creating TitlePreviewViewController</li>
<li>Refactoring TableViewHeader Hero title</li>
<li>Handling Tapping across all ViewControllers</li>
<li>Core Data (Best Practices)</li>
<li>Using Notification Center to update ViewControllers</li>
</ul>
<p>Watch the full course below or on <a target="_blank" href="https://youtu.be/KCgYDCKqato">the freeCodeCamp.org YouTube channel</a> (5-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KCgYDCKqato" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make a Simple Async GET REST API call in SwiftUI ]]>
                </title>
                <description>
                    <![CDATA[ By Saamer Mansoor In this tutorial for beginners, you will learn the basics of using SwiftUI to make API calls using the popular Internet Chuck Norris DataBase (ICNDB) as an example. It will display a joke quickly and easily using Swift and SwiftUI. ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/make-rest-api-call-in-swiftui-in-2-minutes/</link>
                <guid isPermaLink="false">66d460c7d7a4e35e384349ab</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SwiftUI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 02 Dec 2021 18:32:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/Frame-12-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Saamer Mansoor</p>
<p>In this tutorial for beginners, you will learn the basics of using SwiftUI to make API calls using the popular Internet Chuck Norris DataBase (ICNDB) as an example. It will display a joke quickly and easily using Swift and SwiftUI. </p>
<p>You'll see how the cross-platform framework SwiftUI lets us use the exact same code across iOS, iPadOS, macOS, watchOS, App Clips and tvOS, which otherwise would have been impossible.</p>
<p>Along with that, you will use <a target="_blank" href="https://developer.apple.com/documentation/swift/swift_standard_library/concurrency/updating_an_app_to_use_swift_concurrency">async-await</a> that was introduced in Swift 5.5, which works for newer operating systems including iPhones running iOS &gt; v15.0. This really simplifies our work of making data network calls asynchronously on click of a button without freezing the UI thread. </p>
<p>I will share the code changes you'll need to make first. Then in the following section, I will share a brief analysis of the code so beginners can understand what's going on as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/Group-1-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>tvOS app running the code displays a button that retrieves the joke on click</em></p>
<h2 id="heading-how-to-make-api-calls-in-swift-and-swiftui">How to Make API Calls in Swift and SwiftUI</h2>
<p>First, you'll need a Mac to install Xcode. Once it's installed, open Xcode and create a new project. Then select "App" for iOS, macOS, tvOS, or watchOS.</p>
<h3 id="heading-contentview">ContentView</h3>
<p>Just update your existing ContentView SwiftUI file to add a Button and use the <em>State</em> variable to refresh the text displayed as the joke returns from ICNDB API:</p>
<pre><code class="lang-swiftui">import Foundation
import SwiftUI
struct ContentView: View {
    @State private var joke: String = ""
    var body: some View {
        Text(joke)
        Button {
            Task {
                let (data, _) = try await URLSession.shared.data(from: URL(string:"https://api.chucknorris.io/jokes/random")!)
                let decodedResponse = try? JSONDecoder().decode(Joke.self, from: data)
                joke = decodedResponse?.value ?? ""
            }
        } label: {
            Text("Fetch Joke")
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
struct Joke: Codable {
    let value: String
}
</code></pre>
<h3 id="heading-fetch-a-joke">Fetch a joke!</h3>
<p>If you press build/play, the app will build in whatever platform you selected above:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/Screen-Shot-2021-12-01-at-4.42.11-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshots of watchOS, macOS, and iOS apps running the same exact code</em></p>
<h2 id="heading-code-analysis">Code Analysis</h2>
<p>If you go to the random joke URL, you'll notice that the data is in JSON format. You can copy that and use a JSON Linter to view its structure to figure out what property of the Joke object is needed. </p>
<p>Based on that, you determine the code above. You use the Codable protocol (aka interfaces) to go from a JSON data object to an actual Swift class or struct, and you create properties for the data you want to store (value in our case). </p>
<p>JSONDecoder helps us parse the JSON string using the Codable object. This works regardless of platform because the page that loads on launching the app has the same name <em>ContentView</em> regardless of platform.</p>
<h3 id="heading-app-clips">App Clips</h3>
<p><a target="_blank" href="https://developer.apple.com/app-clips/">App Clips</a> are Apple's latest way of using native app functionality using an "App Clip Code" without having to download the whole application from the App Store.</p>
<p>App Clips work similar to an iOS app – the only difference is that you don't create a new App Clip project. You just need to add the App Clip as a target to an existing iOS app by going to File-&gt;New-&gt;Target-&gt;iOS-&gt;App Clip when an existing iOS app is open in Xcode. </p>
<p>If you you wondering about iPhone/iPad <a target="_blank" href="https://support.apple.com/en-us/HT207122">Widgets</a>, well they don't animate. So button clicks will just open the corresponding app and can't update text through an external API independently. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned how to make RESTful GET API calls from SwiftUI in the simplest possible way! </p>
<p>Feel free to reach out to me if you have any questions. I figured this out using another article and I thought of simplifying it further. So for more details and ways to make this code more complex, check out that article:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.raywenderlich.com/25013447-async-await-in-swiftui">https://www.raywenderlich.com/25013447-async-await-in-swiftui</a></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Optional Types in Swift – How to Use and Unwrap Optionals ]]>
                </title>
                <description>
                    <![CDATA[ By Prajwal Kulkarni If you're coming from Java, C++, or other object-oriented languages, chances are that you've never come across optional types or "optionals". And you might be quite surprised to know that such a concept exists in Swift. Optionals ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/optional-types-in-swift/</link>
                <guid isPermaLink="false">66d4609333b83c4378a51824</guid>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 06 May 2021 16:06:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/maxwell-nelson-taiuG8CPKAQ-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Prajwal Kulkarni</p>
<p>If you're coming from Java, C++, or other object-oriented languages, chances are that you've never come across optional types or "optionals". And you might be quite surprised to know that such a concept exists in Swift.</p>
<p>Optionals are a fundamental topic that you need to thoroughly understand to code in Swift. If you're just getting started with Swift and you're learning about optional types for the first time, make sure to read this article until the end.</p>
<p>To understand what optional types are, let's quickly brush up on <strong>constants</strong> and <strong>variables.</strong></p>
<h2 id="heading-constants-and-variables-in-swift">Constants and Variables in Swift</h2>
<p>A constant is a data item whose value, once assigned, cannot be mutated (modified or changed) throughout the scope of the program. </p>
<p>On the other hand, a variable is a data item whose value can be changed limitlessly. </p>
<p>There are some nuances in how declare constants and variables in Swift. Let's look at that syntax:</p>
<p><code>&lt;data-item-type&gt; &lt;var-name&gt;:&lt;data-type&gt; = &lt;value&gt;</code></p>
<p><strong>Here's an example of a constant:</strong></p>
<p><code>let pi:Double = 3.1415</code></p>
<p><strong>And here's an example of a variable:</strong></p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> message:<span class="hljs-type">String</span> = <span class="hljs-string">"Hello, this is prajwal"</span>
message = <span class="hljs-string">"Coding in swift is awesome"</span> <span class="hljs-comment">//variable value changed.</span>
</code></pre>
<p>Notice that of the keywords we've used here for declaring constants and variables, you use <strong>let</strong> to declare a constant, and <strong>var</strong> to declare a variable.</p>
<p>The keyword is then followed by the constant/variable name, a colon and its data type, and then the assigning value.</p>
<p>Swift is a type-safety language, which means that you can assign variables and constants values without specifying the data type. It can make appropriate assumptions based on the assigned value, for example:</p>
<p><code>let const:String = "String"</code></p>
<p>can also be written as,</p>
<p><code>let const = "String"</code></p>
<p>And,</p>
<p><code>var speed:Int = 20</code></p>
<p>can be written as,</p>
<p><code>var speed = 35</code></p>
<p>You might be wondering, if you can omit the data type then what's the need to specify it anyway? Well, you're right to wonder that – but you need to specify the data type once you're working with optional types, which are different from conventional data types.</p>
<h2 id="heading-optional-types-or-optionals-in-swift">Optional types or Optionals in Swift</h2>
<p>Coming to the main point, what are optional types in Swift?</p>
<p>Let's see what the <a target="_blank" href="https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html">docs</a> have to say about it:</p>
<blockquote>
<p>You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn’t a value at all.</p>
</blockquote>
<p>That's a pretty straightforward definition. So optionals are basically used to handle null values at compile-time to ensure that no crashes occur at runtime.</p>
<p>Any operations on the optional variable are performed only if it contains non-null values.</p>
<p>An optional type can be of any data type, like a String, Integer, Double, Float, or any user defined non-primitive data type (object). </p>
<p>But, it is important to note that the Optional data type is not equivalent to its base data type. For instance, an Optional String is not the same as a string, an Optional integer is not the same as an integer, and so forth. This is because primitive data types cannot handle <code>nil</code> values, but Optional types can. </p>
<h2 id="heading-optional-types-syntax-and-usage-in-swift">Optional Types Syntax and Usage in Swift</h2>
<p>Here's the syntax for an optional type:</p>
<p><code>&lt;data-item&gt; &lt;var-name&gt;:&lt;data-type&gt;?</code></p>
<p>The declaration is similar to declaring regular variables, except that you add a question mark (?) beside the data type which makes it an Optional type.</p>
<p>Fire up your XCode playground and try running these snippets:</p>
<pre><code><span class="hljs-keyword">let</span> someVal:Double?
someVal = <span class="hljs-number">5.6324</span>

print(someVal)
<span class="hljs-comment">//Output : Optional(someVal)</span>

<span class="hljs-keyword">var</span> str:<span class="hljs-built_in">String</span>? = nil

str = <span class="hljs-string">"Hello, World!"</span>
print(str)
<span class="hljs-comment">//Output : Optional("Hello, World!")</span>
</code></pre><p>You can see that the outputs are not regular values. Instead, they're optional values.</p>
<h2 id="heading-how-to-unwrap-optional-types-in-swift">How to Unwrap Optional Types in Swift</h2>
<p>You won't use optional types upfront for any operations or tasks, as they should be cast in their primitives or user-defined instances before using it elsewhere (an optional string should be cast to a string, an optional integer should be cast to an integer, and so on). </p>
<p>This casting is what's known as <strong>unwrapping.</strong> You can better understand this concept by thinking about Schrödinger's cat. </p>
<p>In this thought experiment, a cat is placed in a closed box along with a vial of poison. Unless you open the box, you can't assure whether the cat is dead or alive ( nil or non-nil). This means that it is both dead and alive at the same time (nil and non-nil) according to your perception.</p>
<p>Only when you open the box (unwrapping) can you learn if the cat is alive or not (nil or not). </p>
<p>Unwrapping in Swift is essentially verifying if the Optional value is nil or not, and then it performs a task only if it's not nil.</p>
<p>You can perform unwrapping in the following ways:</p>
<ol>
    <li>Using an if else block</li>
    <li>Using Forced unwrapping</li>
    <li>Using Optional binding</li>
    <li>Using Optional chaining</li>
    <li>Using a nil coalescing operator</li>
</ol>

<h3 id="heading-unwrap-an-optional-type-with-an-if-else-block">Unwrap an optional type with an if-else block</h3>
<p>Unwrapping means to make sure that the Optional value is not nil. You can do this by using a simple if-else block like this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> variable:<span class="hljs-type">String?</span> <span class="hljs-comment">//evaluates to nil</span>

<span class="hljs-keyword">if</span> variable != <span class="hljs-literal">nil</span>{
 <span class="hljs-built_in">print</span>(<span class="hljs-string">"Not nil"</span>)
}
<span class="hljs-keyword">else</span>{
 <span class="hljs-built_in">print</span>(<span class="hljs-string">"Nil"</span>)
}
<span class="hljs-comment">//Output : Nil</span>
</code></pre>
<h3 id="heading-unwrap-an-optional-type-with-forced-unwrapping">Unwrap an optional type with forced unwrapping</h3>
<p>Forced unwrapping is quite contradictory because you're accessing the optional value regardless of its value (nil or not nil). If a nil optional is unwrapped, an error is thrown saying "<strong>Unexpectedly found nil while unwrapping an Optional value</strong>." </p>
<p>You're supposed to use forced unwrapping only in a pre-defined environment where you're certain that the optional value won't be nil.</p>
<p>You can forcefully unwrap an optional using the exclamatory(!) operator like this:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> color:<span class="hljs-type">String?</span>;

<span class="hljs-built_in">print</span>(color!) <span class="hljs-comment">// Unexpectedly found nil while unwrapping an Optional value</span>

color = <span class="hljs-string">"Black"</span>;

<span class="hljs-built_in">print</span>(color!) <span class="hljs-comment">// Black</span>
</code></pre>
<h3 id="heading-unwrap-an-optional-type-with-optional-binding">Unwrap an optional type with optional binding</h3>
<p>Optional binding is similar to using an if-else block. The only subtle difference is that if the optional value is not nil, the unwrapped value is assigned to a new constant and further operations are performed on the constant. </p>
<p>You can do this using the <strong>if-let</strong> statement:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> password:<span class="hljs-type">String?</span> = <span class="hljs-string">"$tr0ngp@$$w0rd"</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> unwrappedpass = password {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Password is \(unwrappedpass)"</span>) <span class="hljs-comment">//Password is $tr0ngp@$$w0rd</span>
}
</code></pre>
<p>An optional string <code>password</code> is assigned the value <code>$tr0ngp@$$w0rd</code>. Then in the if-let block, the optional value <code>password</code> is unwrapped and assigned to the variable <code>unwrappedpass</code> only if the optional value <code>password</code> is not nil. <code>unwrappedpass</code> now contains the unwrapped value and can be used within the block's scope.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> password:<span class="hljs-type">String?</span>

<span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> unwrap = password{ <span class="hljs-comment">// Block unexecuted, as optional password is nil.</span>
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"value is not nil"</span>)
}
</code></pre>
<h3 id="heading-unwrap-an-optional-type-with-optional-chaining">Unwrap an optional type with optional chaining</h3>
<p>You use optional chaining in places where you're dealing with multiple optional values at once. You use it to access and mutate or assign far-fetched attributes whose value depends on other constraints.</p>
<p>For example, we get our food from plants, which in turn get their food from sunlight and water.</p>
<p>This means that there is a chained dependency of events – we are dependent on plants for our food, and plants themselves are dependent on water and light for their food.</p>
<p>Optional chaining involves verifying at each dependency if the instance is nil or not.</p>
<p>Let's see how this works with a code example:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ShipmentCar</span></span>{
    <span class="hljs-keyword">var</span> seats:<span class="hljs-type">Int?</span>
    <span class="hljs-keyword">var</span> quality:<span class="hljs-type">String?</span>

    <span class="hljs-keyword">init</span>(seatQty:<span class="hljs-type">Int</span>){
        seats = seatQty
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">displaySeatQuality</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> seatQuality = quality{
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"The seat covering is made of:\(seatQuality)"</span>)
        }
    }



}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckSeats</span></span>{
    <span class="hljs-keyword">var</span> seatExists:<span class="hljs-type">ShipmentCar?</span>

}


<span class="hljs-keyword">var</span> obj = <span class="hljs-type">ShipmentCar</span>(seatQty:<span class="hljs-number">4</span>)
<span class="hljs-keyword">var</span> obj2:<span class="hljs-type">CheckSeats?</span>
obj2 = <span class="hljs-type">CheckSeats</span>()
obj2?.seatExists = obj
obj2?.seatExists?.quality = <span class="hljs-string">"Leather"</span> <span class="hljs-comment">//Optional chaining, set leather quality of seats, only if seats exist.</span>
obj.displaySeatQuality()
<span class="hljs-comment">//Output: The seat covering is made of: Leather</span>
</code></pre>
<p>In the above example, we have two classes, <code>ShipmentCar</code> which is cargo, and <code>CheckSeats</code> to check if there are any seats in the vehicle.</p>
<p>We first create an instance of the class <code>ShipmentCar</code> and pass the argument as 4 for the number of seats – meaning that there are 4 seats in the vehicle. </p>
<p>Further, we create an optional instance of the class <code>CheckSeats</code> and instantiate it. The attribute <code>seatExists</code> of the class <code>CheckSeats</code> is of the type optional <code>ShipmentCar</code>. </p>
<p>Next, we perform optional chaining on the instance <code>obj2</code>, which we write as <code>obj2?.seatExists?.quality = "Leather"</code>. This means that we check if seats exist in the car, and if the seats exist, we define the quality of the seat cover which is <code>Leather</code>. Then we verify by calling the <code>displaySeatQuality</code> and get the desired result.</p>
<p><strong>Here's a small caveat</strong>: in the above example, if you set the value of <code>seatQty</code> as 0 instead of 4, it'd still output the same result. This implies that the seat covers are made of leather even though there are 0 seats, which would make no sense. </p>
<p>So, I'd like to mention that this is just an example and the main objective here is to emphasize that the attributes are assigned values only if the dependent attributes are not-nil.</p>
<h3 id="heading-unwrap-an-optional-type-with-the-nil-coalescing-operator">Unwrap an optional type with the nil coalescing operator</h3>
<p>The nil coalescing operator works as shorthand notation for the regular if-else block. If a nil value is found when an optional value is unwrapped, an additional default value is supplied which will be used instead.</p>
<pre><code><span class="hljs-keyword">var</span> text:<span class="hljs-built_in">String</span>?

<span class="hljs-keyword">var</span> output = text ?? <span class="hljs-string">"Default value"</span>

print(output) <span class="hljs-comment">// Default value</span>

text = <span class="hljs-string">"This is a string"</span>

output = text ?? <span class="hljs-string">"Default String"</span>

print(output) <span class="hljs-comment">// This is a string</span>
</code></pre><p>You can also write default values in terms of objects.</p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>There you have it! In this article, you've learned all about optional types and how to use them.</p>
<p>I'd like to thank you for reading this far and I hope this article has helped you understand optional types in Swift.</p>
<p>If you've any queries, feel free to contact me on <a target="_blank" href="https://twitter.com/prajwalinbizz">Twitter</a> and/or <a target="_blank" href="https://www.linkedin.com/in/prajwal-kulkarni">LinkedIn</a>. I'll be happy to help you. Cheers!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add the Realm Database to an iOS CRUD App using Swift ]]>
                </title>
                <description>
                    <![CDATA[ By Sai Balaji K Hello, everyone! In this article we are going to learn how to add the Realm database to an iOS app.  We'll create a simple ToDo app so you can learn how to perform CRUD (Create, Read, Update, Delete) operations in the Realm database. ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/add-realm-database-to-ios-crud-app-with-with-swift/</link>
                <guid isPermaLink="false">66d460c5230dff0166905863</guid>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ios app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 27 Apr 2021 18:21:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/605aa5a8687d62084bf6b611.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sai Balaji K</p>
<p>Hello, everyone! In this article we are going to learn how to add the Realm database to an iOS app. </p>
<p>We'll create a simple ToDo app so you can learn how to perform CRUD (Create, Read, Update, Delete) operations in the Realm database.</p>
<h2 id="heading-what-is-realm">What is Realm?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-8.09.31-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Realm is an open-source mobile database which is developer friendly and easy to use. You can also use it as an alternative to Core Data in iOS apps. </p>
<p>Realm is a cross platform mobile database, which means that you can use it in native Android and iOS apps and also in cross platform apps like those created using React Native. It supports Objective-C, Swift, Java, Kotlin, C#, and JavaScript.</p>
<h2 id="heading-how-to-set-up-realm-in-your-ios-project">How to Set Up Realm in Your iOS Project</h2>
<p>We can add Realm to our iOS project using SPM (the Swift Package Manager), Cocoa Pods, or Carthage. Here, we are going to use Cocoa Pods to add Realm Pod to our iOS project.</p>
<ol>
<li>Open up Xcode and create a blank iOS app project with UIKit and Swift without using Core Data.</li>
<li>Now close Xcode and open up the terminal. Navigate to your project directory using the terminal.</li>
<li>Run the following command to create a PodFile.</li>
</ol>
<pre><code class="lang-command">pod init
</code></pre>
<ol start="4">
<li>Now when you list the contents of the directory you can see that there is a new Podfile. Open the file using any text editor (here I've used Vim). Edit your Podfile so that it looks similar to the below image. Save and close the Podfile.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-8.23.07-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now that we have specified the dependence for Realm DB, we can install the dependencies by running the below command:</p>
<pre><code class="lang-command">pod install
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-8.26.21-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we have successfully added the Realm DB dependency in our iOS project. Now run the below command to open our project in Xcode.</p>
<pre><code class="lang-command">open YOUR_APP_NAME.xcworkspace
</code></pre>
<p>Note: after opening Xcode, make sure you build your project by pressing Command+B.</p>
<h2 id="heading-how-to-design-your-user-interface-in-realm">How to Design Your User Interface in Realm</h2>
<p>We are going to keep our app's UI simple. Open up Main.storyboard and create a simple UI as shown below by adding a table view with a prototype cell. Then embed a navigation controller and create the IBOutlets for the tableview in the ViewController.swift file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-8.32.42-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-create-a-data-model-in-realm">How to Create a Data Model in Realm</h2>
<p>In our ToDo app, each task has a task name and a task id. We are going to create a Model class to represent the todo task. In the project navigator right click and create a new Swift file, and add the below code.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-keyword">import</span> RealmSwift


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ToDoTask</span>:<span class="hljs-title">Object</span>
</span>{
    <span class="hljs-meta">@objc</span> <span class="hljs-keyword">dynamic</span> <span class="hljs-keyword">var</span> tasknote: <span class="hljs-type">String?</span>
    <span class="hljs-meta">@objc</span> <span class="hljs-keyword">dynamic</span> <span class="hljs-keyword">var</span> taskid: <span class="hljs-type">String?</span>
}
</code></pre>
<p>Her we created our model class named ToDoTask. It inherits the Object class which is a class that comes with RealmDB. This class handles all the under the hood processes of saving the data created using this model class in the database.</p>
<p>We also added two properties: <code>tasknote</code>, which is the task to be done, and <code>taskid</code> – both of type string. <code>@objc</code> means that your Swift code is visible to Objective C and <code>dynamic</code> means you want to use Objective C dynamic dispatch.</p>
<h2 id="heading-basic-crud-app-functions">Basic CRUD App functions</h2>
<p>Our app will perform the following functions:</p>
<ol>
<li>Get input from the user using AlertViewController.</li>
<li>Add the input to the database and also to the table view.</li>
<li>Allow the user to edit their input.</li>
<li>Swipe to delete a row to remove the data from both the table view and the database.</li>
<li>Fetch all the data (if present) from the database and display it in the table view.</li>
</ol>
<h3 id="heading-how-to-get-input-from-the-user-using-alertviewcontroller">How to get input from the user using AlertViewController</h3>
<p>Open up <code>ViewController.swift</code> and add the below code inside the <code>ViewDidLoad()</code> method. And create a new function called <code>addTask()</code> and add the code to display the alert view controller with a text box to get input from the user. </p>
<p>Now when the right bar button is pressed it will call the <code>addTask()</code> function which will display the <code>alertviewcontroller</code> with a text field to get user input.</p>
<pre><code class="lang-swift">navigationItem.rightBarButtonItem = <span class="hljs-type">UIBarButtonItem</span>(image: .add, style: .done, target: <span class="hljs-keyword">self</span>, action: #selector(addTask))

navigationController?.navigationBar.prefersLargeTitles = <span class="hljs-literal">true</span>

title = <span class="hljs-string">"RealmDB"</span>
</code></pre>
<pre><code class="lang-swift"><span class="hljs-meta">@objc</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addTask</span><span class="hljs-params">()</span></span>
    { 
        <span class="hljs-keyword">let</span> ac = <span class="hljs-type">UIAlertController</span>(title: <span class="hljs-string">"Add Note"</span>, message: <span class="hljs-literal">nil</span>, preferredStyle: .alert)

        ac.addTextField(configurationHandler: .<span class="hljs-keyword">none</span>)

        ac.addAction(<span class="hljs-type">UIAlertAction</span>(title: <span class="hljs-string">"Add"</span>, style: .<span class="hljs-keyword">default</span>, handler: { (<span class="hljs-type">UIAlertAction</span>) <span class="hljs-keyword">in</span>

              <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> text = ac.textFields?.first?.text
            {
                <span class="hljs-built_in">print</span>(text)
            }

        }))
        ac.addAction(<span class="hljs-type">UIAlertAction</span>(title: <span class="hljs-string">"Cancel"</span>, style: .cancel, handler: <span class="hljs-literal">nil</span>))
        present(ac, animated: <span class="hljs-literal">true</span>, completion: <span class="hljs-literal">nil</span>)
    }
</code></pre>
<h3 id="heading-how-to-add-the-input-to-the-database-and-table-view">How to add the input to the database and table view</h3>
<p>To save data into Realm, first we need obtain an instance for Realm through which we can access all the methods needed for CRUD operations. Create a property of type Realm in the <code>ViewController.swift</code> file and initialise it in the <code>viewDidLoad()</code> method.</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> realmDB: <span class="hljs-type">Realm!</span>
</code></pre>
<pre><code class="lang-swift"> <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">viewDidLoad</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">super</span>.viewDidLoad()

        navigationItem.rightBarButtonItem = <span class="hljs-type">UIBarButtonItem</span>(image: .add, style: .done, target: <span class="hljs-keyword">self</span>, action: #selector(addTask))
        navigationController?.navigationBar.prefersLargeTitles = <span class="hljs-literal">true</span>
        title = <span class="hljs-string">"RealmDB"</span>

        realmDB = <span class="hljs-keyword">try</span>! <span class="hljs-type">Realm</span>()

    }
</code></pre>
<p>Create an empty array of type our DataModel (ToDoTask). This array will hold all the tasks which need to be added to the table view and database. </p>
<p>Now inside the <code>addTask()</code> function modify the Add action closure so that it gets the user input and creates a random ID for that input. Then append it to our array and save it to the database.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> tasks = [<span class="hljs-type">ToDoTask</span>]()
</code></pre>
<pre><code class="lang-swift"> <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> text = ac.textFields?.first?.text
            {
                <span class="hljs-comment">//Add data to data model array</span>
                <span class="hljs-keyword">let</span> t = <span class="hljs-type">ToDoTask</span>()
                t.taskid = <span class="hljs-type">UUID</span>().uuidString
                t.tasknote = text
                <span class="hljs-keyword">self</span>.tasks.append(t)

                <span class="hljs-comment">//Add data to database</span>
                <span class="hljs-keyword">try</span>! <span class="hljs-keyword">self</span>.realmDB.write {
                    <span class="hljs-keyword">self</span>.realmDB.add(t)
                }
                <span class="hljs-comment">//Update table view UI</span>
                <span class="hljs-keyword">self</span>.tasktv.reloadData()
            }
</code></pre>
<p>Now when you run the app, the data will be saved in the database. But it will not show in table view because we have not implemented the delegate methods. </p>
<p>Make the ViewController class implement the <code>UITableViewDelegate</code> and <code>UITableViewDataSource</code> protocols and add the protocol stubs. </p>
<p>Now inside the <code>numberOfRowsInSection</code> method, return the count of our tasks array which gives the number of rows to be added to the table view. This is equal to the number of elements in tasks array.</p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">tableView</span><span class="hljs-params">(<span class="hljs-number">_</span> tableView: UITableView, numberOfRowsInSection section: 
 Int)</span></span> -&gt; <span class="hljs-type">Int</span> 
 {
        <span class="hljs-keyword">return</span> tasks.<span class="hljs-built_in">count</span>;
 }
</code></pre>
<p>The next thing we need to do is specify the content in each row. We can do this using the <code>cellForRowAt</code> delegate method. Here we dequeue a cell using the identifier which we have mentioned in storyboard and specify the label text as the tasks array element tasknote property.</p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">tableView</span><span class="hljs-params">(<span class="hljs-number">_</span> tableView: UITableView, cellForRowAt indexPath: IndexPath)</span></span> -&gt; <span class="hljs-type">UITableViewCell</span> {
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> cell = tableView.dequeueReusableCell(withIdentifier: <span class="hljs-string">"cell"</span>)
        {
            cell.textLabel?.text = tasks[indexPath.row].tasknote
            <span class="hljs-keyword">return</span> cell
        }
        <span class="hljs-keyword">return</span> <span class="hljs-type">UITableViewCell</span>()
    }
</code></pre>
<h3 id="heading-how-to-allow-users-to-edit-their-input">How to allow users to edit their input</h3>
<p>Now we have to allow the user to edit their entered tasks and update the changes in both the database and UI. We can do this using similar methods of getting input from the user. Implement the <code>didSelectRowAt</code> delegate method which will be called when user taps the table view row. </p>
<p>Add the below code which displays an <code>AlertViewController</code> with a text view. Then update the content of the cell with the entered text, and at the same time update the database contents.</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">tableView</span><span class="hljs-params">(<span class="hljs-number">_</span> tableView: UITableView, didSelectRowAt indexPath: IndexPath)</span></span> {

        <span class="hljs-keyword">let</span> tasktomodify = tasks[indexPath.row]
        <span class="hljs-keyword">let</span> ac = <span class="hljs-type">UIAlertController</span>(title: <span class="hljs-string">"Update task"</span>, message: <span class="hljs-literal">nil</span>, preferredStyle: .alert)

        ac.addTextField(configurationHandler: .<span class="hljs-keyword">none</span>)
        ac.addAction(<span class="hljs-type">UIAlertAction</span>(title: <span class="hljs-string">"Ok"</span>, style: .<span class="hljs-keyword">default</span>, handler: { (<span class="hljs-type">UIAlertAction</span>) <span class="hljs-keyword">in</span>
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> text = ac.textFields?.first?.text
            {
                <span class="hljs-keyword">if</span>(!text.isEmpty)
                {
                <span class="hljs-keyword">try</span>! <span class="hljs-keyword">self</span>.realmDB.write({
                    tasktomodify.tasknote = text
                })
                <span class="hljs-keyword">self</span>.tasktv.reloadData()
                }
            }
        }))

        present(ac, animated: <span class="hljs-literal">true</span>, completion: <span class="hljs-literal">nil</span>)
    }
</code></pre>
<h3 id="heading-how-to-swipe-to-delete-a-row-amp-remove-the-data-from-both-the-table-view-and-database">How to swipe to delete a row &amp; remove the data from both the table view and database</h3>
<p>Here we are going to implement a swipe to delete feature in our table view so that users can delete their tasks. But under the hood when the user swipe deletes a table view row then it should delete the data from database, data model array, and update the UI of the table view. </p>
<p>We can do this by implementing the <strong>commit editingStyle</strong> delegate method and adding the following code:</p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">tableView</span><span class="hljs-params">(<span class="hljs-number">_</span> tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)</span></span> {
        <span class="hljs-keyword">if</span> editingStyle == .delete
        {
            <span class="hljs-keyword">let</span> tasktoDelete = tasks[indexPath.row]
            <span class="hljs-keyword">try</span>! realmDB.write({
                realmDB.delete(tasktoDelete)
                <span class="hljs-keyword">self</span>.tasks.remove(at: indexPath.row)
                <span class="hljs-keyword">self</span>.tasktv.deleteRows(at: [indexPath], with: .fade)
            })
        }
    }
</code></pre>
<h3 id="heading-how-to-fetch-all-the-data-if-present-from-the-database-and-display-it-in-the-table-view">How to fetch all the data (if present) from the database and display it in the table view</h3>
<p>Now we are going to implement our last operation, Read. Whenever the user launches the app, it should fetch data from the database (if data is present) and display it in the table view. </p>
<p>We can do this by creating a function <code>getTodo</code> in the view controller swift file and adding the following code inside it:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>
    {
       <span class="hljs-comment">//Get all the data from the database</span>
        <span class="hljs-keyword">let</span> notes = realmDB.objects(<span class="hljs-type">ToDoTask</span>.<span class="hljs-keyword">self</span>)

        <span class="hljs-comment">//Clear the model data array to prevent duplicates</span>
        <span class="hljs-keyword">self</span>.tasks.removeAll()

        <span class="hljs-comment">/*If the fetched data is not empty then add it to model data array and update the UI */</span>
        <span class="hljs-keyword">if</span>(!notes.isEmpty)
        {
        <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> notes
        {

            <span class="hljs-keyword">self</span>.tasks.append(n)

        }
            <span class="hljs-keyword">self</span>.tasktv.reloadData()
        }


    }
</code></pre>
<h2 id="heading-bonus-tip-how-to-view-your-database-content-in-an-ios-simulator">Bonus Tip: How to View Your Database Content in an iOS Simulator</h2>
<p>Now when you run your app, you can see that it works as expected. But how can we check if the data is really stored in the database? We can use an app called MongoDB Realm Studio through which we can view our data stored in the Realm database of the simulator.</p>
<blockquote>
<p>Note that this method works only when you test the app using iOS simulator</p>
</blockquote>
<p>In the <code>viewDidLoad()</code> method, add the below line of code which will print the real file path of our app:</p>
<pre><code class="lang-swift"> <span class="hljs-built_in">print</span>(realmDB.configuration.fileURL!)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-9.48.59-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now copy the file path printed in the console, open up the terminal, and run the following command:</p>
<pre><code class="lang-command">open REALM_FILE_PATH_HERE
</code></pre>
<blockquote>
<p>Make sure you have downloaded MongoDB Realm Studio from the browser before running the above command.</p>
</blockquote>
<p>Now it will open the RealmFile of the app in MongoDB Realm Studio. This will display the data stored in the database in a table format. </p>
<p>If you make changes to your data by editing or deleting the task, the changes will be reflected in the MongoDB Realm Studio app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-9.55.29-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Congratulations! You have made a simple app which implements CRUD operations in iOS apps.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to programmatically build a Spotify clone for iOS using AutoLayout: adding photos and updating the UI ]]>
                </title>
                <description>
                    <![CDATA[ By Said Hayani This is the second part of an article on building a Spotify UI clone with autoLayout programmatically. If you missed the first part, no worries - just please go and check it now.  In this article, we are going to add some mocked pictur... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-spotify-clone-for-ios-with-autolayout-programmatically-part-2/</link>
                <guid isPermaLink="false">66d460d2868774922c885008</guid>
                
                    <category>
                        <![CDATA[ 100DaysOfCode ]]>
                    </category>
                
                    <category>
                        <![CDATA[ app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ autolayout ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS13 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iphone ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                    <category>
                        <![CDATA[ User Interface ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 10 Dec 2019 03:44:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/12/featured_image-4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Said Hayani</p>
<p>This is the second part of an article on building a Spotify UI clone with autoLayout programmatically. If you missed the first part, no worries - just please go and <a target="_blank" href="https://www.freecodecamp.org/news/autolayout-programmatically-spotify-clone-in-swift/">check it now</a>. </p>
<p>In this article, we are going to add some mocked pictures and try to make the UI look the same as Spotify's.</p>
<p>This is what we are going to do today ?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/Screen-Shot-2019-12-09-at-9.55.19-PM-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is were we left off in the first part:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/complet-layout-demo1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The next step is to create customized cells. So let's start by creating one with the name  <code>SubCustomCell</code>.</p>
<p>First, create a new Swift file inside the project folder and name it <code>SubCustomCell.swift</code>. This file will contain our custom cell that will represent the Playlist. After creating the file, try to add in the code below and initialize the cell, maybe with <code>backgroundColor</code>,  to see the UI changes when we register the cell with the <code>collectionView</code>. </p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> UIKit

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SubCustomCell</span>: <span class="hljs-title">UICollectionViewCell</span> </span>{
        <span class="hljs-keyword">override</span> <span class="hljs-keyword">init</span>(frame: <span class="hljs-type">CGRect</span>) {
        <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>(frame: frame)
        backgroundColor = .red
    }

    <span class="hljs-keyword">required</span> <span class="hljs-keyword">init</span>?(coder aDecoder: <span class="hljs-type">NSCoder</span>) {
        <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"init(coder:) has not been implemented"</span>)
    }
}
</code></pre>
<p>Then we register the <code>SubCustomCell</code>  inside <code>CustomCell.swift</code> within the <code>init</code> block. Replace <code>UICollectionViewCell.self</code> with  <code>SubCustomCell</code> like below.</p>
<pre><code class="lang-swift"> collectionView.register(<span class="hljs-type">SubCustomCell</span>.<span class="hljs-keyword">self</span>, forCellWithReuseIdentifier: cellId)
</code></pre>
<p>Also we need to make a modification on the <code>cellForItemAt</code> method and make it conform to  <code>SubCustomCell</code> like the following.</p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)</span></span> -&gt; <span class="hljs-type">UICollectionViewCell</span> {
        <span class="hljs-keyword">let</span> cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, <span class="hljs-keyword">for</span>: indexPath) <span class="hljs-keyword">as</span>! <span class="hljs-type">SubCustomCell</span>
        <span class="hljs-comment">// cell.backgroundColor = .yellow</span>

        <span class="hljs-keyword">return</span> cell
    }
</code></pre>
<p>You should see the <code>backgroundColor</code> changed to <code>red</code> .</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/Screen-Shot-2019-12-03-at-1.10.25-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Swift CustomCell</em></p>
<p>Up until this point everything should be straightforward and clear.</p>
<p>Now we're going to fill the cells with some mocked pictures and create an <code>ImageView</code> inside each cell. I already downloaded some random pictures from <a target="_blank" href="https://www.pexels.com/">pexels.com,</a> but feel free to use any pictures you like (including these). You can find them in the <a target="_blank" href="https://github.com/hayanisaid/autoLayout-programmatically-in-swift">project files on Github</a>.</p>
<p>Let's create the <code>UIImageView</code> inside <code>SubCustomCell.swift</code> and make some constraints.</p>
<pre><code class="lang-swift">    <span class="hljs-keyword">let</span> <span class="hljs-type">ImageView</span> : <span class="hljs-type">UIImageView</span> = {
       <span class="hljs-keyword">let</span> iv = <span class="hljs-type">UIImageView</span>()
        iv.backgroundColor = .yellow
        <span class="hljs-keyword">return</span> iv

    }()
</code></pre>
<p>And add it to the <code>view</code> within the <code>init</code> block using <code>addSubView</code>.</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">override</span> <span class="hljs-keyword">init</span>(frame: <span class="hljs-type">CGRect</span>) {
        <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>(frame: frame)
        addSubview(<span class="hljs-type">ImageView</span>)

    }
</code></pre>
<p>Now let's make the <code>ImageView</code> take up all the space within the cell with the constraints below.</p>
<pre><code class="lang-swift"> <span class="hljs-type">ImageView</span>.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
            <span class="hljs-type">ImageView</span>.topAnchor.constraint(equalTo: topAnchor).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.leftAnchor.constraint(equalTo: leftAnchor).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.rightAnchor.constraint(equalTo: rightAnchor).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = <span class="hljs-literal">true</span>
</code></pre>
<ul>
<li><code>LeftAnchor</code> represents the left anchor of the cell</li>
<li><code>rightAnchor</code> represents the right anchor of the cell</li>
<li><code>bottomAnchor</code> represents the bottom anchor of the cell </li>
<li><code>topAnchor</code> represents the top anchor of the cell</li>
</ul>
<p>And by making <code>ImageView</code> 's top anchor equal to the cell's top anchor (and doing the same for <code>ImageView</code> 's left, right, and bottom anchor) it makes the <code>ImageView</code> take up all the space of the <code>SubCustomCell</code> (cell).</p>
<p>Note: first you need to use <code>translatesAutoresizingMaskIntoConstraints</code> to be able to apply the constraints to the elements. Also don't forget to call <code>isActive</code> property and assign it to <code>true</code> – without doing that the constraints won't work and nothing will change.</p>
<p>The <code>ImageView</code> should have an image, so let's add one.</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">let</span> <span class="hljs-type">ImageView</span> : <span class="hljs-type">UIImageView</span> = {
       <span class="hljs-keyword">let</span> iv = <span class="hljs-type">UIImageView</span>()
        iv.backgroundColor = .yellow
        <span class="hljs-comment">// we have &gt;image1&lt; file inside the project </span>
        iv.image = <span class="hljs-type">UIImage</span>(named: <span class="hljs-string">"image1"</span>)
        iv.contentMode = .scaleAspectFill
        iv.clipsToBounds = <span class="hljs-literal">true</span>

        <span class="hljs-keyword">return</span> iv

    }()
</code></pre>
<p>And if you build and run the app, you should see the results and picture we added to the <code>SubCustomCell</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/Screen-Shot-2019-12-03-at-1.37.51-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Cool ?. Now there is an element we should add to the <code>SubCustomCell</code> to finish up. We need a title that will represent the title of the playlist:  <code>UILabel</code>.</p>
<p>For the title it will be like this:</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">let</span> <span class="hljs-type">TitleLabel</span> : <span class="hljs-type">UILabel</span> = {
        <span class="hljs-keyword">let</span> lb = <span class="hljs-type">UILabel</span>()
        lb.textColor = <span class="hljs-type">UIColor</span>.lightGray
        lb.font = <span class="hljs-type">UIFont</span>.systemFont(ofSize: <span class="hljs-number">16</span>)
        lb.font = <span class="hljs-type">UIFont</span>.boldSystemFont(ofSize: <span class="hljs-number">20</span>)
        lb.text = <span class="hljs-string">"Evening Music"</span>

        <span class="hljs-keyword">return</span> lb
    }()
</code></pre>
<p>I just put some random text there – you can put whatever you like. The next step is to add the element to the view and give it some constraints. The title will be placed at the bottom of the <code>ImageView</code>.</p>
<h3 id="heading-add-to-view">Add to view:</h3>
<pre><code class="lang-swift">addSubview(<span class="hljs-type">TitleLabel</span>)
</code></pre>
<h3 id="heading-applying-the-constraints-for-both-the-imageview-and-the-titlelabel">Applying the constraints for both the <code>ImageView</code> and the <code>TitleLabel</code></h3>
<pre><code class="lang-swift"> <span class="hljs-type">ImageView</span>.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
            <span class="hljs-type">ImageView</span>.topAnchor.constraint(equalTo: topAnchor).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.leftAnchor.constraint(equalTo: leftAnchor).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.rightAnchor.constraint(equalTo: rightAnchor).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.heightAnchor.constraint(equalToConstant: <span class="hljs-number">240</span>).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">ImageView</span>.bottomAnchor.constraint(equalTo: <span class="hljs-type">TitleLabel</span>.topAnchor).isActive = <span class="hljs-literal">true</span>



            <span class="hljs-type">TitleLabel</span>.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
            <span class="hljs-type">TitleLabel</span>.topAnchor.constraint(equalTo: <span class="hljs-type">ImageView</span>.bottomAnchor,constant: <span class="hljs-number">10</span>).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">TitleLabel</span>.leftAnchor.constraint(equalTo: leftAnchor, constant: <span class="hljs-number">5</span>).isActive = <span class="hljs-literal">true</span>
            <span class="hljs-type">TitleLabel</span>.rightAnchor.constraint(equalTo: rightAnchor, constant: -<span class="hljs-number">5</span>).isActive = <span class="hljs-literal">true</span>
</code></pre>
<p>And here we go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/Screen-Shot-2019-12-06-at-1.45.10-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We made the picture take up most of the space in the cell, and the rest is taken up by the title. As you can see, you can scroll horizontally in each section and also vertically in the entire screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/demo2.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now we are put some mock data into the cells to make it feel like it's real. For that I created a <code>JSON</code> file that contains some random data for sections and playlists.</p>
<p>First let's create a two structs, <code>Section</code> and <code>Playlist</code> . We create a separate file for each struct. </p>
<p> <code>section.swift</code> </p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Section</span> </span>{
    <span class="hljs-keyword">var</span> title : <span class="hljs-type">String</span>
    <span class="hljs-keyword">var</span> playlists : <span class="hljs-type">NSArray</span>
    <span class="hljs-keyword">init</span>(dictionary:[<span class="hljs-type">String</span> : <span class="hljs-type">Any</span>]) {
        <span class="hljs-keyword">self</span>.title = dictionary[<span class="hljs-string">"title"</span>] <span class="hljs-keyword">as</span>? <span class="hljs-type">String</span> ?? <span class="hljs-string">""</span>
        <span class="hljs-keyword">self</span>.playlists = dictionary[<span class="hljs-string">"playlists"</span>] <span class="hljs-keyword">as</span>? <span class="hljs-type">NSArray</span> ?? []

}
}
</code></pre>
<p><code>playlist.swift</code></p>
<pre><code class="lang-swift"><span class="hljs-comment">//</span>
<span class="hljs-comment">//  playlist.swift</span>
<span class="hljs-comment">//  spotifyAutoLayout</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">//  Created by admin on 12/6/19.</span>
<span class="hljs-comment">//  Copyright © 2019 Said Hayani. All rights reserved.</span>
<span class="hljs-comment">//</span>

<span class="hljs-keyword">import</span> Foundation
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">PlayList</span> </span>{
    <span class="hljs-keyword">var</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">var</span> image : <span class="hljs-type">String</span>
    <span class="hljs-keyword">init</span>(dictionary : [<span class="hljs-type">String</span> : <span class="hljs-type">Any</span>]) {
        <span class="hljs-keyword">self</span>.title = dictionary[<span class="hljs-string">"title"</span>] <span class="hljs-keyword">as</span>? <span class="hljs-type">String</span> ?? <span class="hljs-string">""</span>
        <span class="hljs-keyword">self</span>.image = dictionary[<span class="hljs-string">"image"</span>] <span class="hljs-keyword">as</span>? <span class="hljs-type">String</span> ?? <span class="hljs-string">""</span>
    }

}
</code></pre>
<p>And then inside <code>ViewController.swift</code> we create a function that fetches the JSON for us and stores the results in an array.</p>
<pre><code class="lang-swift">
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"attempt to fetch Json"</span>)
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> path = <span class="hljs-type">Bundle</span>.main.path(forResource: <span class="hljs-string">"test"</span>, ofType: <span class="hljs-string">"json"</span>) {
            <span class="hljs-keyword">do</span> {
                  <span class="hljs-keyword">let</span> data = <span class="hljs-keyword">try</span> <span class="hljs-type">Data</span>(contentsOf: <span class="hljs-type">URL</span>(fileURLWithPath: path), options: .mappedIfSafe)
                  <span class="hljs-keyword">let</span> jsonResult = <span class="hljs-keyword">try</span> <span class="hljs-type">JSONSerialization</span>.jsonObject(with: data, options: .mutableLeaves)
                <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> jsonResult = jsonResult <span class="hljs-keyword">as</span>? [ <span class="hljs-type">Any</span>] {
                            <span class="hljs-comment">// do stuff</span>
                    jsonResult.forEach { (item) <span class="hljs-keyword">in</span>

                        <span class="hljs-keyword">let</span> section = <span class="hljs-type">Section</span>(dictionary: item <span class="hljs-keyword">as</span>! [<span class="hljs-type">String</span> : <span class="hljs-type">Any</span>])
                       <span class="hljs-comment">// print("FEtching",section.playlists)</span>
                        <span class="hljs-keyword">self</span>.sections.append(section)
                    }


                  <span class="hljs-keyword">self</span>.collectionView.reloadData()
                  }
              } <span class="hljs-keyword">catch</span> {
                   <span class="hljs-comment">// handle error</span>
              }
        }
    }
</code></pre>
<p>The <code>fetchJson</code> function is called within the <code>ViewDidLoad</code> method. We also have a variable called <code>sections</code> where we store the results:</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> sections = [<span class="hljs-type">Section</span>]()
</code></pre>
<p>The next step is to pass the data from <code>ViewController</code> to <code>CustomCell</code>. For that we create a variable inside <code>CustomCell</code> which will receive the data for each section: </p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> section : <span class="hljs-type">Section?</span>{
        <span class="hljs-keyword">didSet</span>{
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"section ✅"</span>,<span class="hljs-keyword">self</span>.section)
        }
    }
</code></pre>
<p>We use <code>cellForItemAt</code>  inside the <code>ViewController</code> method to pass the data directly to the <code>CustomCell</code> .</p>
<pre><code class="lang-swift"><span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)</span></span> -&gt; <span class="hljs-type">UICollectionViewCell</span> {
        <span class="hljs-keyword">let</span> cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, <span class="hljs-keyword">for</span>: indexPath) <span class="hljs-keyword">as</span>! <span class="hljs-type">CustomCell</span>

        cell.section = sections[indexPath.item]

        <span class="hljs-keyword">return</span> cell
    }
</code></pre>
<p>Note: we always call <strong><code>self</code></strong><code>.collectionView.reloadData()</code> every-time <code>fetchJson</code> is called so the block below, inside <code>CustomCell</code>, will be called as well. Check the console, <code>shift</code> + command + C:</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> section : <span class="hljs-type">Section?</span> {
        <span class="hljs-keyword">didSet</span>{
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"section ✅"</span>,<span class="hljs-keyword">self</span>.section)
        }
    }
</code></pre>
<p>The first thing we change is to set the the section title:</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> section : <span class="hljs-type">Section?</span> {
        <span class="hljs-keyword">didSet</span>{
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"section ✅"</span>,<span class="hljs-keyword">self</span>.section)
            <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> section = <span class="hljs-keyword">self</span>.section <span class="hljs-keyword">else</span> {<span class="hljs-keyword">return</span>}
            <span class="hljs-keyword">self</span>.titleLabel.text = section.title
        }
    }
</code></pre>
<p>And then you should see that each section has a specific title on the screen ?.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/Screen-Shot-2019-12-06-at-3.23.32-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now it's time to pass the data down to <code>SubCustomCell</code>. We do the same thing as we did above. We need to pass the <code>playlists</code> array, so we create a variable named <code>playlists</code> inside <code>CustomCell</code>.</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> playlists : [<span class="hljs-type">PlayList</span>]() <span class="hljs-comment">//empty</span>
</code></pre>
<p>First, we map through the <code>playlists</code>  from the <code>JSON</code>. Then we add each playlist with the <code>playlists</code> var.</p>
<pre><code class="lang-swift"> <span class="hljs-keyword">var</span> section : <span class="hljs-type">Section?</span> {
        <span class="hljs-keyword">didSet</span>{
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"section ✅"</span>,<span class="hljs-keyword">self</span>.section)
            <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> section = <span class="hljs-keyword">self</span>.section <span class="hljs-keyword">else</span> {<span class="hljs-keyword">return</span>}
            <span class="hljs-keyword">self</span>.titleLabel.text = section.title
            <span class="hljs-comment">// append to playlists array</span>
             <span class="hljs-keyword">self</span>.section?.playlists.forEach({ (item) <span class="hljs-keyword">in</span>
                <span class="hljs-keyword">let</span> playlist = <span class="hljs-type">PlayList</span>(dictionary: item <span class="hljs-keyword">as</span>! [<span class="hljs-type">String</span> : <span class="hljs-type">Any</span>])
                <span class="hljs-keyword">self</span>.playlists.append(playlist)

            })
            <span class="hljs-keyword">self</span>.collectionView.reloadData()
        }
    }
</code></pre>
<p>Attention! If you try to run the app it may crash. This is because we forgot to set the number of sections. Since we are now receiving the data from JSON, the number should be dynamic based on the number of sections we have. The number of sections should be equal to the number of sections inside the <code>JSON</code>, so we need to modify <code>numberOfItemsInSection</code> inside <code>ViewController</code> to the below :</p>
<pre><code class="lang-swift">   <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, numberOfItemsInSection section: Int)</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">return</span> sections.<span class="hljs-built_in">count</span>
    }
</code></pre>
<p>We do the same thing with the same method inside <code>CustomCell.swift</code> – but here we consider the number of the <code>playlists</code> instead.</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, numberOfItemsInSection section: Int)</span></span> -&gt; <span class="hljs-type">Int</span> {
        <span class="hljs-keyword">return</span>  <span class="hljs-keyword">self</span>.playlists.<span class="hljs-built_in">count</span>
    }
</code></pre>
<p>The last step we have to complete is to pass each single playlist <code>Object</code> to <code>SubCustomCell</code> within <code>cellForItemAt</code> in <code>CustomCell.swift</code>. </p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)</span></span> -&gt; <span class="hljs-type">UICollectionViewCell</span> {
        <span class="hljs-keyword">let</span> cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, <span class="hljs-keyword">for</span>: indexPath) <span class="hljs-keyword">as</span>! <span class="hljs-type">SubCustomCell</span>
        <span class="hljs-comment">// here ?</span>
        cell.playlist = playlists[indexPath.item]
        <span class="hljs-keyword">return</span> cell
    }
</code></pre>
<p>And we are going to get that data inside <code>SubCustomCell</code> via the <code>playlist</code> variable and finally display the title and image of the playlist.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">var</span> playlist : <span class="hljs-type">PlayList?</span> {
           <span class="hljs-keyword">didSet</span>{
               <span class="hljs-built_in">print</span>(<span class="hljs-string">"Playlist ?"</span>,<span class="hljs-keyword">self</span>.playlist)
            <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> playlist = <span class="hljs-keyword">self</span>.playlist <span class="hljs-keyword">else</span> {<span class="hljs-keyword">return</span>}
            <span class="hljs-comment">// The Image ?</span>
            <span class="hljs-keyword">self</span>.<span class="hljs-type">ImageView</span>.image = <span class="hljs-type">UIImage</span>(named: playlist.image)
            <span class="hljs-comment">// the playlist title ?</span>
            <span class="hljs-keyword">self</span>.<span class="hljs-type">TitleLabel</span>.text = <span class="hljs-keyword">self</span>.playlist?.title

           }
       }
</code></pre>
<p>I think everything should work fine now, just as below ?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/demo3.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p> One last update to the UI: we have to add some padding and margins to the <code>section</code>  and <code>playlist</code> titles and make the playlist a little bit smaller.</p>
<p>Let's first add some padding for the section titles. To do that, we need just to give the <code>constant</code> property some number value inside the section cell <code>CustomCell</code> and within <code>setupSubCells</code>: </p>
<pre><code class="lang-swift"> collectionView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor,constant: <span class="hljs-number">15</span>).isActive = <span class="hljs-literal">true</span>
</code></pre>
<p>And if you see the entire <code>collectionView</code> come in at the bottom of the <code>titleLabel</code>, all we need to do is add more space by adding <code>15</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/paddingForTitles-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next we come to the title of the <code>playlist</code>. This will be inside <code>SubCustomCell</code>, and we just need to add more space at the bottom of the ImageView.</p>
<pre><code class="lang-swift"> <span class="hljs-type">ImageView</span>.bottomAnchor.constraint(equalTo: <span class="hljs-type">TitleLabel</span>.topAnchor,constant: -<span class="hljs-number">15</span>).isActive = <span class="hljs-literal">true</span>
</code></pre>
<p>We already have the constant there. In order for it to work, the value should be <code>-15</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/demo4.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Finally the playlist needs to be a little bit smaller. This is easy: we just make the <code>playlist</code> cell's height and width equal to the <code>section</code> cell's height divided by 2, just like below:</p>
<p><code>CustomCell.swift</code></p>
<pre><code class="lang-swift"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">collectionView</span><span class="hljs-params">(<span class="hljs-number">_</span> collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath)</span></span> -&gt; <span class="hljs-type">CGSize</span> {

        <span class="hljs-keyword">let</span> width = frame.height / <span class="hljs-number">2</span>
        <span class="hljs-keyword">let</span> height = frame.height / <span class="hljs-number">2</span>

        <span class="hljs-keyword">return</span> <span class="hljs-type">CGSize</span>(width: width, height: height)

    }
</code></pre>
<p>Make the ImageView's height equal to <code>150</code> as well.</p>
<pre><code class="lang-swift">  <span class="hljs-comment">//SubCutomCell.swift</span>
  <span class="hljs-type">ImageView</span>.heightAnchor.constraint(equalToConstant: <span class="hljs-number">150</span>).isActive = <span class="hljs-literal">true</span>
</code></pre>
<p>And here we go ?.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/12/Screen-Shot-2019-12-09-at-9.55.19-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Perfect! I think that's enough for today – I don't want to make this article too long. So we will have another part where we will add the <code>TabBar</code> and the description, as well as some icons for the playlist.</p>
<p><strong>View the</strong> <a target="_blank" href="https://github.com/hayanisaid/autoLayout-programmatically-in-swift"><strong>Full source code on GitHub</strong></a><strong>?.</strong></p>
<p>Thanks for your time. I hope I haven't missed anything. If I did please @mention me on <a target="_blank" href="https://twitter.com/SaidHYN">Twitter</a>, or if you have any questions or an addition to this post the doors are always open to anyone. Thanks??.</p>
<p><strong><a target="_blank" href="https://webege.us16.list-manage.com/subscribe?u=311846a57d1e1a666287ad128&amp;id=2b386b2ebb">Subscribe</a></strong> <em>to my email list to be notified when the third part of this tutorial is published.</em> </p>
<blockquote>
<p>By the way, I’ve recently worked with a strong group of software engineers for one of my mobile applications. The organization was great, and the product was delivered very quickly, much faster than other firms and freelancers I’ve worked with, and I think I can honestly recommend them for other projects out there. Shoot me an email if you want to get in touch — <a target="_blank" href="mailto:said@devsdata.com">said@devsdata.com</a>.</p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to make an API call in Swift ]]>
                </title>
                <description>
                    <![CDATA[ By Ai-Lyn Tang If you are looking to become an iOS developer, there are some fundamental skills worth knowing. First, it's important to be familiar with creating table views. Second, you should know how to populate those table views with data. Third,... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-your-first-api-call-in-swift/</link>
                <guid isPermaLink="false">66d45d5e230dff0166905799</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 29 Nov 2019 11:49:45 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9ef3740569d1a4ca4004.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ai-Lyn Tang</p>
<p>If you are looking to become an iOS developer, there are some fundamental skills worth knowing. First, it's important to be familiar with creating table views. Second, you should know how to populate those table views with data. Third, it's great if you can fetch data from an API and use this data in your table view.</p>
<p>The third point is what we'll cover in this article. Since the introduction of <code>Codable</code> in Swift 4, making API calls is much easier. Previously most people used pods like Alamofire and SwiftyJson (you can read about how to do that <a target="_blank" href="https://code.likeagirl.io/3-steps-to-make-your-first-api-call-836e43ed702c">here</a>). Now the Swift way is much nicer out of the box, so there's no reason to download a pod.</p>
<p>Let's go through some building blocks that are often used to make an API call. We'll cover these concepts first, as they are important parts to understanding how to make an API call.</p>
<ul>
<li>Completion handlers</li>
<li><code>URLSession</code></li>
<li><code>DispatchQueue</code></li>
<li>Retain cycles</li>
</ul>
<p>Finally we'll put it all together. I'll be using the open source <a target="_blank" href="https://www.swapi.co/">Star Wars API</a> to build this project. You can see my full project code on <a target="_blank" href="https://github.com/ailyntang/starwars/">GitHub</a>.</p>
<p><em>Disclaimer alert: I am new to coding and am largely self-taught. Apologies if I misrepresent some concepts.</em></p>
<h2 id="heading-completion-handlers">Completion handlers</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/10/pheobe.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Poor patient Pheobe</em></p>
<p>Remember the episode of Friends where Pheobe is glued to the phone for days waiting to speak with customer service? Imagine if at the very start of that phone call, a lovely person called Pip said: "Thanks for calling. I have no idea how long you'll need to wait on hold, but I'll call you back when we're ready for you." It wouldn't have been as funny, but Pip is offering to be a completion handler for Pheobe.</p>
<p>You use a completion handler in a function when you know that function will take a while to complete. You don't know how long, and you don't want to pause your life waiting for it to finish. So you ask Pip to tap you on the shoulder when she's ready to give you the answer. That way you can go about your life, run some errands, read a book, and watch TV. When Pip taps on you on the shoulder with the answer, you can take her answer and use it.</p>
<p>This is what happens with API calls. You send a URL request to a server, asking it for some data. You hope the server returns the data quickly, but you don't know how long it will take. Instead of making your user wait patiently for the server to give you the data, you use a completion handler. This means you can tell your app to go off and do other things, such as loading the rest of the page.</p>
<p>You tell the completion handler to tap your app on the shoulder once it has the information you want. You can specify what that information is. That way, when your app gets tapped on the shoulder, it can take the information from the completion handler and do something with it. Usually what you'll do is reload the table view so the data appears to the user.</p>
<p>Here's an example of what a completion handler looks like. The first example is setting up the API call itself:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchFilms</span><span class="hljs-params">(completionHandler: @escaping <span class="hljs-params">([Film])</span></span></span> -&gt; <span class="hljs-type">Void</span>) {
  <span class="hljs-comment">// Setup the variable lotsOfFilms</span>
  <span class="hljs-keyword">var</span> lotsOfFilms: [<span class="hljs-type">Film</span>]

  <span class="hljs-comment">// Call the API with some code</span>

  <span class="hljs-comment">// Using data from the API, assign a value to lotsOfFilms  </span>

  <span class="hljs-comment">// Give the completion handler the variable, lotsOfFilms</span>
  completionHandler(lotsOfFilms)
}
</code></pre>
<p>Now we want to call the function <code>fetchFilms</code>. Some things to note:</p>
<ul>
<li>You don't need to reference <code>completionHandler</code> when you call the function. The only time you reference <code>completionHandler</code> is inside the function declaration.</li>
<li>The completion handler will give us back some data to use. Based on the function we've written above, we know to expect data which is of type <code>[Film]</code>. We need to name the data so that we can refer to it. Below I'm using the name <code>films</code>, but it could be <code>randomData</code>, or any other variable name I'd like.</li>
</ul>
<p>The code will look something like this: </p>
<pre><code class="lang-swift">fetchFilms() { (films) <span class="hljs-keyword">in</span>
  <span class="hljs-comment">// Do something with the data the completion handler returns </span>
  <span class="hljs-built_in">print</span>(films)
}
</code></pre>
<h2 id="heading-urlsession">URLSession</h2>
<p><code>URLSession</code> is like the manager of a team. The manager doesn't do anything on her own. Her job is to share the work with the people in her team, and they'll get the job done. Her team are <code>dataTasks</code>. Every time you need some data, write to the boss and use <code>URLSession.shared.dataTask</code>.  </p>
<p>You can give the <code>dataTask</code> different types of information to help you achieve your goal. Giving information to <code>dataTask</code> is called initialization. I initialism my <code>dataTasks</code> with URLs. <code>dataTasks</code> also use completion handlers as part of their initialization. Here's an example:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"https://www.swapi.co/api/films"</span>)

<span class="hljs-keyword">let</span> task = <span class="hljs-type">URLSession</span>.shared.dataTask(with: url, completionHandler: { (data, response, error) <span class="hljs-keyword">in</span> 
  <span class="hljs-comment">// your code here</span>
})

task.resume()
</code></pre>
<p><code>dataTasks</code> use completion handlers, and they always return the same types of information: <code>data</code>, <code>response</code> and <code>error</code>. You can give these data types different names, like <code>(data, res, err)</code> or <code>(someData, someResponse, someError)</code>. For the sake of convention, it's best to stick to something obvious rather than go rogue with new variable names.</p>
<p>Let's start with <code>error</code>. If the <code>dataTask</code> returns an <code>error</code>, you'll  want to know that upfront. It means you can direct your code to handle the error gracefully. It also means you won't bother trying to read the data and do something with it as there is an error in returning the data. </p>
<p>Below I am handling the error really simply by printing an error to the console and exiting the function. There are many other ways you could handle the error if you wanted to. Think about how fundamental this data is to your app. For example, if you have a banking app and this API call shows users their balance, then you may want to handle the error by presenting a modal to the user that says, "Sorry, we're experiencing a problem right now. Please try again later."</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> error = error {
  <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error accessing swapi.co: /(error)"</span>)
  <span class="hljs-keyword">return</span>
}
</code></pre>
<p>Next we look at the response. You can cast the response to be an <code>httpResponse</code>. That way you can look at the status codes and make some decisions based on the code. For example, if the status code is 404, then you know the page was not found. </p>
<p>The code below uses a <code>guard</code> to check that two things exist. If both exist, then it allows the code to continue to the next statement after the <code>guard</code> clause. If either of the statements fail, then we exit the function. This is a typical use case of a <code>guard</code> clause. You expect the code after a guard clause to be the happy days flow (i.e. the easy flow with no errors).</p>
<pre><code class="lang-swift">  <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> httpResponse = response <span class="hljs-keyword">as</span>? <span class="hljs-type">HTTPURLResponse</span>,
            (<span class="hljs-number">200</span>...<span class="hljs-number">299</span>).<span class="hljs-built_in">contains</span>(httpResponse.statusCode) <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error with the response, unexpected status code: \(response)"</span>)
    <span class="hljs-keyword">return</span>
  }
</code></pre>
<p>Finally you handle the data itself. Notice that we haven't used the completion handler for the <code>error</code> or the <code>response</code>. That's because the completion handler is waiting for data from the API. If it doesn't get to the data part of the code, there's no need to invoke the handler.</p>
<p>For the data, we are using the <code>JSONDecoder</code> to parse the data in a nice way. This is pretty nifty, but requires that you have established a model. Our model is called <code>FilmSummary</code>. If <code>JSONDecoder</code> is new to you, then have a look online for how to use it and how to use <code>Codable</code>. It's really simple in Swift 4 and above compared to the Swift 3 days.</p>
<p>In the code below, we are first checking that the data exists. We are pretty sure it should exist, because there are no errors and no strange HTTP responses. Second, we check that we can parse the data we receive in the way we expect. If we can, then we return the film summary to the completion handler. Just in case there is no data to return from the API, we have a fall back plan of the empty array.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> data = data,
        <span class="hljs-keyword">let</span> filmSummary = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSONDecoder</span>().decode(<span class="hljs-type">FilmSummary</span>.<span class="hljs-keyword">self</span>, from: data) {
        completionHandler(filmSummary.results ?? [])
      }
</code></pre>
<p>So the full code for API call looks like this:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchFilms</span><span class="hljs-params">(completionHandler: @escaping <span class="hljs-params">([Film])</span></span></span> -&gt; <span class="hljs-type">Void</span>) {
    <span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: domainUrlString + <span class="hljs-string">"films/"</span>)!

    <span class="hljs-keyword">let</span> task = <span class="hljs-type">URLSession</span>.shared.dataTask(with: url, completionHandler: { (data, response, error) <span class="hljs-keyword">in</span>
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> error = error {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error with fetching films: \(error)"</span>)
        <span class="hljs-keyword">return</span>
      }

      <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> httpResponse = response <span class="hljs-keyword">as</span>? <span class="hljs-type">HTTPURLResponse</span>,
            (<span class="hljs-number">200</span>...<span class="hljs-number">299</span>).<span class="hljs-built_in">contains</span>(httpResponse.statusCode) <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error with the response, unexpected status code: \(response)"</span>)
        <span class="hljs-keyword">return</span>
      }

      <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> data = data,
        <span class="hljs-keyword">let</span> filmSummary = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSONDecoder</span>().decode(<span class="hljs-type">FilmSummary</span>.<span class="hljs-keyword">self</span>, from: data) {
        completionHandler(filmSummary.results ?? [])
      }
    })
    task.resume()
  }
</code></pre>
<h2 id="heading-retain-cycles">Retain cycles</h2>
<p><em>NB: I am extremely new to understanding retain cycles! Here's the gist of what I researched online.</em></p>
<p>Retain cycles are important to understand for memory management. Basically you want your app to clean up bits of memory that it doesn't need anymore. I assume this makes the app more performant. </p>
<p>There are lots of ways that Swift helps you do this automatically. However there are many ways that you can accidentally code retain cycles into your app. A retain cycle means that your app will always hold on to the memory for a certain piece of code. Generally it happens when you have two things that have strong pointers to each other. </p>
<p>To get around this, people often use <code>weak</code>. When one side of the code is <code>weak</code>, you don't have a retain cycle and your app will be able to release the memory. </p>
<p>For our purpose, a common pattern is to use <code>[weak self]</code> when calling the API. This ensures that once the completion handler returns some code, the app can release the memory.</p>
<pre><code class="lang-swift">fetchFilms { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] (films) <span class="hljs-keyword">in</span>
  <span class="hljs-comment">// code in here</span>
}
</code></pre>
<h2 id="heading-dispatchqueue">DispatchQueue</h2>
<p>Xcode uses different threads to execute code in parallel. The advantage of multiple threads means you aren't stuck waiting on one thing to finish before you can move on to the next. Hopefully you can start to see the links to completion handlers here.</p>
<p>These threads seem to be also called dispatch queues. API calls are handled on one queue, typically a queue in the background. Once you have the data from your API call, most likely you'll want to show that data to the user. That means you'll want to refresh your table view.</p>
<p>Table views are part of the UI, and all UI manipulations should be done in the main dispatch queue. This means somewhere in your view controller file, usually as part of the <code>viewDidLoad</code> function, you should have a bit of code that tells your table view to refresh. </p>
<p>We only want the table view to refresh once it has some new data from the API. This means we'll use a completion handler to tap us on the shoulder and tell us when that API call is finished. We'll wait until that tap before we refresh the table.</p>
<p>The code will look something like:</p>
<pre><code class="lang-swift">fetchFilms { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] (films) <span class="hljs-keyword">in</span>
  <span class="hljs-keyword">self</span>.films = films

  <span class="hljs-comment">// Reload the table view using the main dispatch queue</span>
  <span class="hljs-type">DispatchQueue</span>.main.async {
    tableView.reloadData()
  }
}
</code></pre>
<h2 id="heading-viewdidload-vs-viewdidappear">viewDidLoad vs viewDidAppear</h2>
<p>Finally you need to decide where to call your <code>fetchfilms</code> function. It will be inside a view controller that will use the data from the API. There are two obvious places you could make this API call. One is inside <code>viewDidLoad</code> and the other is inside <code>viewDidAppear</code>.</p>
<p>These are two different states for your app. My understanding is <code>viewDidLoad</code> is called the first time you load up that view in the foreground. <code>viewDidAppear</code> is called every time you come back to that view, for example when you press the back button to come back to the view.</p>
<p>If you expect your data to change in between the times that the user will navigate to and from that view, then you may want to put your API call in <code>viewDidAppear</code>. However I think for almost all apps, <code>viewDidLoad</code> is sufficient. Apple recommends <code>viewDidAppear</code> for all API calls, but that seems like overkill. I imagine it would make your app less performant as it's making many more API calls that it needs to.</p>
<h2 id="heading-combining-all-the-steps">Combining all the steps</h2>
<p>First: write the function that calls the API. Above, this is <code>fetchFilms</code>. This will have a completion handler, which will return the data you are interested in. In my example, the completion handler returns an array of films.</p>
<p>Second: call this function in your view controller. You do this here because you want to update the view based on the data from the API. In my example, I am refreshing a table view once the API returns the data.</p>
<p>Third: decide where in your view controller you would like to call the function. In my example, I call it in <code>viewDidLoad</code>.</p>
<p>Fourth: decide what to do with the data from the API. In my example, I am refreshing a table view.</p>
<p>Inside <code>NetworkManager.swift</code> (this function can be defined in your view controller if you'd like, but I am using the MVVM pattern).</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchFilms</span><span class="hljs-params">(completionHandler: @escaping <span class="hljs-params">([Film])</span></span></span> -&gt; <span class="hljs-type">Void</span>) {
    <span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: domainUrlString + <span class="hljs-string">"films/"</span>)!

    <span class="hljs-keyword">let</span> task = <span class="hljs-type">URLSession</span>.shared.dataTask(with: url, completionHandler: { (data, response, error) <span class="hljs-keyword">in</span>
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> error = error {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error with fetching films: \(error)"</span>)
        <span class="hljs-keyword">return</span>
      }

      <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> httpResponse = response <span class="hljs-keyword">as</span>? <span class="hljs-type">HTTPURLResponse</span>,
            (<span class="hljs-number">200</span>...<span class="hljs-number">299</span>).<span class="hljs-built_in">contains</span>(httpResponse.statusCode) <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error with the response, unexpected status code: \(response)"</span>)
        <span class="hljs-keyword">return</span>
      }

      <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> data = data,
        <span class="hljs-keyword">let</span> filmSummary = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSONDecoder</span>().decode(<span class="hljs-type">FilmSummary</span>.<span class="hljs-keyword">self</span>, from: data) {
        completionHandler(filmSummary.results ?? [])
      }
    })
    task.resume()
  }
</code></pre>
<p>Inside <code>FilmsViewController.swift</code>:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FilmsViewController</span>: <span class="hljs-title">UIViewController</span> </span>{
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> films: [<span class="hljs-type">Film</span>]?

  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">viewDidLoad</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">super</span>.viewDidLoad()

    <span class="hljs-type">NetworkManager</span>().fetchFilms { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] (films) <span class="hljs-keyword">in</span>
      <span class="hljs-keyword">self</span>?.films = films
      <span class="hljs-type">DispatchQueue</span>.main.async {
        <span class="hljs-keyword">self</span>?.tableView.reloadData()
      }
    }
  }

  <span class="hljs-comment">// other code for the view controller</span>
}
</code></pre>
<p>Gosh, we made it! Thanks for sticking with me.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
