<?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[ Apple - 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[ Apple - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 08 May 2026 14:35:03 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/apple/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Smart HomeKit Virtual Light in Go ]]>
                </title>
                <description>
                    <![CDATA[ Recently, I wanted to understand how smart home devices actually work. When you scan a QR code and a light appears in your Home app, what's really happening? When you tap "on", what bytes travel across your network? The best way I know to understand... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-smart-homekit-virtual-light-in-go/</link>
                <guid isPermaLink="false">69449f453cbff85be8965f37</guid>
                
                    <category>
                        <![CDATA[ HAP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Go Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ homekit ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Matter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ protocols ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rez Moss ]]>
                </dc:creator>
                <pubDate>Fri, 19 Dec 2025 00:41:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766104866742/8d8c0158-95d0-493b-a311-cd99189654e1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Recently, I wanted to understand how smart home devices actually work. When you scan a QR code and a light appears in your Home app, what's really happening? When you tap "on", what bytes travel across your network?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765414117210/e65d5768-792d-4aae-8669-db0ac7a9c60d.png" alt="Virtual HomeKit Light QR code" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The best way I know to understand something is to build it, so I created a virtual HomeKit light in Go. And in this tutorial, I’ll walk you through how I went about it. We’ll pull back the curtain on smart home protocols so you understand how they work, in depth. Let’s dive in.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-homekit-actually-is">What HomeKit Actually Is</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-smart-home-protocol-landscape">The Smart Home Protocol Landscape</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-homekit-discovery-works">How HomeKit Discovery Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-pairing-process-what-happens-when-you-scan-the-qr-code">The Pairing Process: What Happens When You Scan the QR Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-setup-uri-whats-in-that-qr-code">The Setup URI: What's in That QR Code?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-happens-when-you-toggle-the-light">What Happens When You Toggle the Light</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-accessory-database-model">The Accessory Database Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-persisting-pairing-data">Persisting Pairing Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-event-notifications">Event Notifications</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-complete-implementation">The Complete Implementation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-i-learned">What I Learned</a></p>
</li>
</ol>
<h2 id="heading-what-youll-need">What You'll Need</h2>
<p>Before we start building, let's make sure you have the right setup. This project requires two things:</p>
<ol>
<li><p><strong>Go 1.21 or later</strong>: We're using some modern Go features, and the brutella/HAP library works best with recent versions. You can check your version with <code>go version</code>. If you need to upgrade, grab the latest from go.dev</p>
</li>
<li><p><strong>An Apple HomeKit environment</strong>: This means an iPhone or iPad running iOS 15+ with the Home app. You'll also want to be on the same WiFi network as the machine running your virtual light. HomeKit is entirely local, so your phone needs to be able to reach your development machine directly.</p>
</li>
</ol>
<p>One thing that tripped me up initially is that if you’re running this on a Linux server or inside a container, make sure mDNS traffic isn’t being blocked. Your firewall needs to allow UDP port 5353 (for mDNS discovery) and whatever port your accessory runs on (we'll use 51826). On a Mac this usually just works.</p>
<h2 id="heading-what-homekit-actually-is">What HomeKit Actually Is</h2>
<p>HomeKit is Apple's smart home framework. It's comprised of three things:</p>
<ol>
<li><p><strong>a protocol (HAP)</strong> that defines how devices talk to each other,</p>
</li>
<li><p><strong>a security model</strong> that encrypts and authenticates everything,</p>
</li>
<li><p><strong>and an ecosystem</strong> (the Home app, Siri, automations)</p>
</li>
</ol>
<p>Here, we’ll be focused on the protocol layer. We're building something that speaks HAP well enough that Apple's ecosystem accepts it as a real accessory.</p>
<h2 id="heading-the-smart-home-protocol-landscape">The Smart Home Protocol Landscape</h2>
<p>Before getting started, let's understand what we're dealing with. There are two protocols at play here:</p>
<ol>
<li><p><strong>HomeKit Accessory Protocol (HAP):</strong> Apple's original smart home protocol from 2014. It runs over your local WiFi network, uses mDNS for discovery, and encrypts everything with Curve25519 and ChaCha20-Poly1305. Every HomeKit device you've ever used speaks HAP.</p>
</li>
<li><p><strong>Matter</strong>: The new industry standard (2022) backed by Apple, Google, Amazon, and others. Matter is actually built on many of the same cryptographic primitives as HAP. When Apple added Matter support, they essentially made HomeKit bilingual, as it can speak both protocols.</p>
</li>
</ol>
<p>Here's what's interesting: Matter devices that connect to Apple Home still end up being controlled through HomeKit's infrastructure. Matter is the pairing and discovery layer, but once a device is in your Home, Apple's ecosystem takes over.</p>
<p>For this project, I'm using the HAP protocol directly via the <code>brutella/hap</code> library. This lets us see exactly what's happening without Matter's additional abstraction layer.</p>
<h2 id="heading-how-homekit-discovery-works">How HomeKit Discovery Works</h2>
<p>When you run a HomeKit accessory on your network, it doesn't just sit there waiting. It actively announces itself using <strong>mDNS</strong> (multicast DNS), also called Bonjour on Apple platforms.</p>
<p>The accessory broadcasts a service record that looks like this:</p>
<pre><code class="lang-plaintext">_hap._tcp.local.
  name: Virtual Light._hap._tcp.local.
  port: 51826
  txt: 
    c#=1          // config number (changes trigger rediscovery)
    ff=0          // feature flags
    id=XX:XX:XX   // device ID (like a MAC address)
    md=Virtual Light  // model name
    pv=1.1        // protocol version
    s#=1          // state number
    sf=1          // status flag (1=not paired, 0=paired)
    ci=5          // category (5=lightbulb)
    sh=XXXXXX     // setup hash
</code></pre>
<p>Your iPhone is constantly listening for <code>_hap._tcp.local.</code> broadcasts. When it sees one with <code>sf=1</code> (unpaired), it shows up in "Add Accessory" as available.</p>
<p>Let's see this in code. Here's the minimal server setup:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"log"</span>

    <span class="hljs-string">"github.com/brutella/hap"</span>
    <span class="hljs-string">"github.com/brutella/hap/accessory"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    light := accessory.NewLightbulb(accessory.Info{
        Name:         <span class="hljs-string">"Virtual Light"</span>,
        Manufacturer: <span class="hljs-string">"My Smart Home"</span>,
    })

    server, err := hap.NewServer(hap.NewFsStore(<span class="hljs-string">"./data"</span>), light.A)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    server.Pin = <span class="hljs-string">"00102003"</span>
    server.Addr = <span class="hljs-string">":51826"</span>

    server.ListenAndServe(context.Background())
}
</code></pre>
<p>When <code>ListenAndServe</code> runs, it:</p>
<ol>
<li><p>Generates a unique device ID if one doesn't exist</p>
</li>
<li><p>Starts listening on port 51826</p>
</li>
<li><p>Registers the mDNS service record</p>
</li>
<li><p>Waits for connections</p>
</li>
</ol>
<p>At this point, your iPhone can discover it. But what happens when you try to pair it?</p>
<h2 id="heading-the-pairing-process-what-happens-when-you-scan-the-qr-code">The Pairing Process: What Happens When You Scan the QR Code</h2>
<p>This is where it gets interesting. HomeKit uses the <strong>SRP (Secure Remote Password)</strong> protocol for pairing. It’s the same protocol used in things like 1Passwords authentication.</p>
<p>When you scan the QR code or enter the PIN, here's the actual sequence:</p>
<h3 id="heading-step-1-pair-setup-m1-ios-accessory">Step 1: Pair Setup M1 (iOS → Accessory)</h3>
<pre><code class="lang-plaintext">iOS sends: { method: "pair-setup", state: 1 }
</code></pre>
<p>Your phone initiates pairing, telling the accessory "I want to pair with you."</p>
<h3 id="heading-step-2-pair-setup-m2-accessory-ios">Step 2: Pair Setup M2 (Accessory → iOS)</h3>
<pre><code class="lang-plaintext">Accessory sends: { 
  state: 2,
  salt: &lt;16 random bytes&gt;,
  public_key: &lt;SRP public key B&gt;
}
</code></pre>
<p>The accessory generates an SRP salt and public key. The PIN code you entered isn't sent over the network – instead, it's used to derive a verifier locally.</p>
<h3 id="heading-step-3-pair-setup-m3-ios-accessory">Step 3: Pair Setup M3 (iOS → Accessory)</h3>
<pre><code class="lang-plaintext">iOS sends: {
  state: 3,
  public_key: &lt;SRP public key A&gt;,
  proof: &lt;SRP proof M1&gt;
}
</code></pre>
<p>Your iPhone uses the PIN to compute its own SRP values and sends a proof that it knows the PIN.</p>
<h3 id="heading-step-4-pair-setup-m4-accessory-ios">Step 4: Pair Setup M4 (Accessory → iOS)</h3>
<pre><code class="lang-plaintext">Accessory sends: {
  state: 4,
  proof: &lt;SRP proof M2&gt;
}
</code></pre>
<p>The accessory verifies the proof. If the PIN was wrong, pairing fails here. If correct, it sends its own proof back.</p>
<h3 id="heading-step-5-6-key-exchange">Step 5-6: Key Exchange</h3>
<p>Now both sides have a shared secret derived from SRP. They use this to establish an encrypted channel and exchange long term Ed25519 public keys. These keys are stored permanently. This is why your lights still work after rebooting your router.</p>
<p>The whole dance takes about 2 seconds. After this, <code>sf</code> in the mDNS record changes from <code>1</code> to <code>0</code> and the accessory disappears from "Add Accessory".</p>
<h2 id="heading-the-setup-uri-whats-in-that-qr-code">The Setup URI: What's in That QR Code?</h2>
<p>The QR code contains a URI that encodes everything needed for pairing:</p>
<pre><code class="lang-plaintext">X-HM://0ABCDEFGH1234
        ^^^^^^^^^^^^
        |       |
        |       +-- Setup ID (4 chars)
        +---------- Encoded payload (9 chars, base-36)
</code></pre>
<p>The payload packs three things into 45 bits:</p>
<ol>
<li><p><strong>Category:</strong> what type of accessory this is (5 = lightbulb, 6 = outlet, 10 = thermostat, and so on)</p>
</li>
<li><p><strong>Flags:</strong> how the accessory can pair (2 = supports IP ,wifi pairing , 4 = supports BLE pairing , 6 = supports both)</p>
</li>
<li><p><strong>PIN code</strong> as integer</p>
</li>
</ol>
<p>This lets your iPhone know what icon to show and the PIN to use, all from scanning a single QR code.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">generateSetupURI</span><span class="hljs-params">(pin, setupID <span class="hljs-keyword">string</span>, category <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-comment">// PIN "00102003" becomes integer 102003</span>
    <span class="hljs-keyword">var</span> pinInt <span class="hljs-keyword">uint64</span>
    <span class="hljs-keyword">for</span> _, c := <span class="hljs-keyword">range</span> pin {
        <span class="hljs-keyword">if</span> c &gt;= <span class="hljs-string">'0'</span> &amp;&amp; c &lt;= <span class="hljs-string">'9'</span> {
            pinInt = pinInt*<span class="hljs-number">10</span> + <span class="hljs-keyword">uint64</span>(c-<span class="hljs-string">'0'</span>)
        }
    }

    <span class="hljs-comment">// Bit layout:</span>
    <span class="hljs-comment">// [39:32] = category (5 = lightbulb)</span>
    <span class="hljs-comment">// [31:28] = flags (2 = IP pairing supported)</span>
    <span class="hljs-comment">// [26:0]  = PIN code</span>
    payload := (<span class="hljs-keyword">uint64</span>(category) &lt;&lt; <span class="hljs-number">32</span>) | (<span class="hljs-number">2</span> &lt;&lt; <span class="hljs-number">28</span>) | (pinInt &amp; <span class="hljs-number">0x7FFFFFF</span>)

    <span class="hljs-comment">// Encode as base-36 (0-9, A-Z)</span>
    <span class="hljs-keyword">const</span> chars = <span class="hljs-string">"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span>
    encoded := <span class="hljs-string">""</span>
    <span class="hljs-keyword">for</span> payload &gt; <span class="hljs-number">0</span> {
        encoded = <span class="hljs-keyword">string</span>(chars[payload%<span class="hljs-number">36</span>]) + encoded
        payload /= <span class="hljs-number">36</span>
    }

    <span class="hljs-keyword">for</span> <span class="hljs-built_in">len</span>(encoded) &lt; <span class="hljs-number">9</span> {
        encoded = <span class="hljs-string">"0"</span> + encoded
    }

    <span class="hljs-keyword">return</span> <span class="hljs-string">"X-HM://"</span> + encoded + setupID
}
</code></pre>
<p>When your iPhone camera sees <code>X-HM://</code>, it knows this is a HomeKit code. It decodes the payload to extract the category (so it can show the right icon) and the PIN (so you don't have to type it). The setup ID helps with identification when multiple unpaired accessories are on the network.</p>
<h2 id="heading-what-happens-when-you-toggle-the-light">What Happens When You Toggle the Light</h2>
<p>Now for the part I was most curious about. When you tap the light button in the Home app, what actually travels across your network?</p>
<h3 id="heading-step-1-encrypted-session">Step 1: Encrypted Session</h3>
<p>Your iPhone doesn't just send commands in plaintext. Every paired session uses the longterm keys exchanged during pairing to establish a session key. All communication is encrypted with ChaCha20Poly1305.</p>
<h3 id="heading-step-2-hap-request">Step 2: HAP Request</h3>
<p>Inside the encrypted channel, HomeKit uses a simple HTTP like protocol. A "turn on" command looks like this:</p>
<pre><code class="lang-plaintext">PUT /characteristics HTTP/1.1
Host: Virtual Light._hap._tcp.local
Content-Type: application/hap+json

{
  "characteristics": [{
    "aid": 1,        // accessory ID
    "iid": 10,       // instance ID (the "On" characteristic)
    "value": true    // new state
  }]
}
</code></pre>
<h3 id="heading-step-3-accessory-response">Step 3: Accessory Response</h3>
<p>The accessory processes the request and responds like this:</p>
<pre><code class="lang-plaintext">HTTP/1.1 204 No Content
</code></pre>
<p>If something went wrong, it'll return a status object with an error code.</p>
<p>In our Go code, we hook into this with a callback:</p>
<pre><code class="lang-go">light.Lightbulb.On.OnValueRemoteUpdate(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(on <span class="hljs-keyword">bool</span>)</span></span> {
    <span class="hljs-keyword">if</span> on {
        fmt.Println(<span class="hljs-string">"💡 Light ON"</span>)
    } <span class="hljs-keyword">else</span> {
        fmt.Println(<span class="hljs-string">"💡 Light OFF"</span>)
    }
})
</code></pre>
<p>This callback fires when the <code>value</code> in that PUT request changes. The <code>brutella/hap</code> library handles all the decryption, parsing, and response generation.</p>
<h2 id="heading-the-accessory-database-model">The Accessory Database Model</h2>
<p>HomeKit organizes everything into a hierarchy:</p>
<pre><code class="lang-plaintext">Accessory (aid=1)
└── Services
    ├── AccessoryInformation (iid=1)
    │   ├── Name (iid=2)
    │   ├── Manufacturer (iid=3)
    │   ├── Model (iid=4)
    │   └── SerialNumber (iid=5)
    │
    └── Lightbulb (iid=9)
        ├── On (iid=10)           ← boolean
        ├── Brightness (iid=11)   ← int 0-100
        └── Hue (iid=12)          ← float 0-360
</code></pre>
<p>Each characteristic has an <code>iid</code> (instance ID). When you change brightness to 75%, the PUT request targets <code>aid=1, iid=11, value=75</code>.</p>
<p>This model is why HomeKit accessories are interoperable. Every lightbulb, regardless of manufacturer, has the same characteristic structure.</p>
<h2 id="heading-persisting-pairing-data">Persisting Pairing Data</h2>
<p>When your accessory pairs with a controller (iPhone), it stores:</p>
<ul>
<li><p>The controller's Ed25519 public key</p>
</li>
<li><p>A controller ID (36chars UUID)</p>
</li>
<li><p>Permission level (admin or regular user)</p>
</li>
</ul>
<p>The accessory also has its own keypairs that must persist across restarts. If you lose this, all paired controllers become orphaned – that is, they think they’re paired, but the accessory doesn't recognize them.</p>
<p>As mentioned earlier, we need to save pairing info so that if the app/device restarts, it can communicate with Homekit again. You could use a database, but for a single accessory, a JSON file works fine. If the process crashes mid-session, you won’t lose pairing data.</p>
<p>I wrote a simple JSON store to keep everything in one file:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> JSONStore <span class="hljs-keyword">struct</span> {
    path <span class="hljs-keyword">string</span>
    data <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>][]<span class="hljs-keyword">byte</span>
    mu   sync.RWMutex
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">Set</span><span class="hljs-params">(key <span class="hljs-keyword">string</span>, value []<span class="hljs-keyword">byte</span>)</span> <span class="hljs-title">error</span></span> {
    s.mu.Lock()
    <span class="hljs-keyword">defer</span> s.mu.Unlock()
    s.data[key] = value
    <span class="hljs-keyword">return</span> s.save()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">Get</span><span class="hljs-params">(key <span class="hljs-keyword">string</span>)</span> <span class="hljs-params">([]<span class="hljs-keyword">byte</span>, error)</span></span> {
    s.mu.RLock()
    <span class="hljs-keyword">defer</span> s.mu.RUnlock()
    <span class="hljs-keyword">if</span> v, ok := s.data[key]; ok {
        <span class="hljs-keyword">return</span> v, <span class="hljs-literal">nil</span>
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, fmt.Errorf(<span class="hljs-string">"key not found: %s"</span>, key)
}
</code></pre>
<p>The HAP library stores several keys:</p>
<ul>
<li><p><code>uuid</code> – accessory's unique identifier</p>
</li>
<li><p><code>public</code> / <code>private</code> – Ed25519 keypair</p>
</li>
<li><p><code>*-pairings</code> – paired controller keys</p>
</li>
</ul>
<p>If you delete this JSON file, the accessory (our virtual-light) forgets all its paired controllers. Your iPhone still thinks it's paired, but the accessory doesn't recognize it anymore – you'll see "No Response" in the Home app. The fix removes the accessory from the Home app and pairs it fresh using the QR code again.</p>
<h2 id="heading-event-notifications">Event Notifications</h2>
<p>One thing I didn't expect is that HomeKit supports push notifications from accessories. When our light state changes (maybe from a physical switch), we can notify all connected controllers:</p>
<pre><code class="lang-go">light.Lightbulb.On.SetValue(<span class="hljs-literal">true</span>)  <span class="hljs-comment">// This triggers notifications</span>
</code></pre>
<p>Under the hood, the accessory maintains persistent connections with controllers. When a characteristic changes, it sends an EVENT message:</p>
<pre><code class="lang-plaintext">EVENT/1.0 200 OK
Content-Type: application/hap+json

{
  "characteristics": [{
    "aid": 1,
    "iid": 10,
    "value": true
  }]
}
</code></pre>
<p>This is how your Home app updates in realtime when someone else turns on a light.</p>
<h2 id="heading-the-complete-implementation">The Complete Implementation</h2>
<p>Here's everything together:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"encoding/json"</span>
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"os"</span>
    <span class="hljs-string">"os/signal"</span>
    <span class="hljs-string">"sync"</span>
    <span class="hljs-string">"syscall"</span>

    <span class="hljs-string">"github.com/brutella/hap"</span>
    <span class="hljs-string">"github.com/brutella/hap/accessory"</span>
    <span class="hljs-string">"github.com/skip2/go-qrcode"</span>
)

<span class="hljs-keyword">const</span> (
    pinCode  = <span class="hljs-string">"00102003"</span>
    setupID  = <span class="hljs-string">"VLTX"</span>
    category = <span class="hljs-number">5</span>
    dbFile   = <span class="hljs-string">"data.json"</span>
)

<span class="hljs-keyword">type</span> JSONStore <span class="hljs-keyword">struct</span> {
    path <span class="hljs-keyword">string</span>
    data <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>][]<span class="hljs-keyword">byte</span>
    mu   sync.RWMutex
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewJSONStore</span><span class="hljs-params">(path <span class="hljs-keyword">string</span>)</span> *<span class="hljs-title">JSONStore</span></span> {
    s := &amp;JSONStore{
        path: path,
        data: <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>][]<span class="hljs-keyword">byte</span>),
    }
    s.load()
    <span class="hljs-keyword">return</span> s
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">load</span><span class="hljs-params">()</span></span> {
    file, err := os.ReadFile(s.path)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span>
    }
    json.Unmarshal(file, &amp;s.data)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">save</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
    file, err := json.MarshalIndent(s.data, <span class="hljs-string">""</span>, <span class="hljs-string">"  "</span>)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span> err
    }
    <span class="hljs-keyword">return</span> os.WriteFile(s.path, file, <span class="hljs-number">0644</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">Set</span><span class="hljs-params">(key <span class="hljs-keyword">string</span>, value []<span class="hljs-keyword">byte</span>)</span> <span class="hljs-title">error</span></span> {
    s.mu.Lock()
    <span class="hljs-keyword">defer</span> s.mu.Unlock()
    s.data[key] = value
    <span class="hljs-keyword">return</span> s.save()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">Get</span><span class="hljs-params">(key <span class="hljs-keyword">string</span>)</span> <span class="hljs-params">([]<span class="hljs-keyword">byte</span>, error)</span></span> {
    s.mu.RLock()
    <span class="hljs-keyword">defer</span> s.mu.RUnlock()
    <span class="hljs-keyword">if</span> v, ok := s.data[key]; ok {
        <span class="hljs-keyword">return</span> v, <span class="hljs-literal">nil</span>
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, fmt.Errorf(<span class="hljs-string">"key not found: %s"</span>, key)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">Delete</span><span class="hljs-params">(key <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">error</span></span> {
    s.mu.Lock()
    <span class="hljs-keyword">defer</span> s.mu.Unlock()
    <span class="hljs-built_in">delete</span>(s.data, key)
    <span class="hljs-keyword">return</span> s.save()
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *JSONStore)</span> <span class="hljs-title">KeysWithSuffix</span><span class="hljs-params">(suffix <span class="hljs-keyword">string</span>)</span> <span class="hljs-params">([]<span class="hljs-keyword">string</span>, error)</span></span> {
    s.mu.RLock()
    <span class="hljs-keyword">defer</span> s.mu.RUnlock()
    <span class="hljs-keyword">var</span> keys []<span class="hljs-keyword">string</span>
    <span class="hljs-keyword">for</span> k := <span class="hljs-keyword">range</span> s.data {
        <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(k) &gt;= <span class="hljs-built_in">len</span>(suffix) &amp;&amp; k[<span class="hljs-built_in">len</span>(k)-<span class="hljs-built_in">len</span>(suffix):] == suffix {
            keys = <span class="hljs-built_in">append</span>(keys, k)
        }
    }
    <span class="hljs-keyword">return</span> keys, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">generateSetupURI</span><span class="hljs-params">(pin, setupID <span class="hljs-keyword">string</span>, category <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">var</span> pinInt <span class="hljs-keyword">uint64</span>
    <span class="hljs-keyword">for</span> _, c := <span class="hljs-keyword">range</span> pin {
        <span class="hljs-keyword">if</span> c &gt;= <span class="hljs-string">'0'</span> &amp;&amp; c &lt;= <span class="hljs-string">'9'</span> {
            pinInt = pinInt*<span class="hljs-number">10</span> + <span class="hljs-keyword">uint64</span>(c-<span class="hljs-string">'0'</span>)
        }
    }

    payload := (<span class="hljs-keyword">uint64</span>(category) &lt;&lt; <span class="hljs-number">32</span>) | (<span class="hljs-number">2</span> &lt;&lt; <span class="hljs-number">28</span>) | (pinInt &amp; <span class="hljs-number">0x7FFFFFF</span>)

    <span class="hljs-keyword">const</span> chars = <span class="hljs-string">"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span>
    encoded := <span class="hljs-string">""</span>
    <span class="hljs-keyword">for</span> payload &gt; <span class="hljs-number">0</span> {
        encoded = <span class="hljs-keyword">string</span>(chars[payload%<span class="hljs-number">36</span>]) + encoded
        payload /= <span class="hljs-number">36</span>
    }

    <span class="hljs-keyword">for</span> <span class="hljs-built_in">len</span>(encoded) &lt; <span class="hljs-number">9</span> {
        encoded = <span class="hljs-string">"0"</span> + encoded
    }

    <span class="hljs-keyword">return</span> <span class="hljs-string">"X-HM://"</span> + encoded + setupID
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    light := accessory.NewLightbulb(accessory.Info{
        Name:         <span class="hljs-string">"Virtual Light"</span>,
        Manufacturer: <span class="hljs-string">"My Smart Home"</span>,
    })

    light.Lightbulb.On.OnValueRemoteUpdate(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(on <span class="hljs-keyword">bool</span>)</span></span> {
        <span class="hljs-keyword">if</span> on {
            fmt.Println(<span class="hljs-string">"💡 Light ON"</span>)
        } <span class="hljs-keyword">else</span> {
            fmt.Println(<span class="hljs-string">"💡 Light OFF"</span>)
        }
    })

    store := NewJSONStore(dbFile)

    server, err := hap.NewServer(store, light.A)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    server.Pin = pinCode
    server.SetupId = setupID
    server.Addr = <span class="hljs-string">":51826"</span>

    fmt.Println(<span class="hljs-string">"=============================================="</span>)
    fmt.Println(<span class="hljs-string">"       Virtual HomeKit Light"</span>)
    fmt.Println(<span class="hljs-string">"=============================================="</span>)
    fmt.Println(<span class="hljs-string">"PIN: 001-02-003"</span>)
    fmt.Println()

    setupURI := generateSetupURI(pinCode, setupID, category)
    <span class="hljs-keyword">if</span> qr, err := qrcode.New(setupURI, qrcode.Medium); err == <span class="hljs-literal">nil</span> {
        fmt.Println(qr.ToSmallString(<span class="hljs-literal">false</span>))
    }

    fmt.Println(<span class="hljs-string">"Manual: Home app → + → More Options → Virtual Light"</span>)
    fmt.Printf(<span class="hljs-string">"Data stored in: %s\n"</span>, dbFile)
    fmt.Println(<span class="hljs-string">"=============================================="</span>)

    ctx, cancel := context.WithCancel(context.Background())
    <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> {
        c := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> os.Signal, <span class="hljs-number">1</span>)
        signal.Notify(c, os.Interrupt, syscall.SIGTERM)
        &lt;-c
        cancel()
    }()

    fmt.Println(<span class="hljs-string">"Running... (Ctrl+C to stop)"</span>)
    server.ListenAndServe(ctx)
}
</code></pre>
<p>Run it, pair it, and watch the terminal as you toggle from your phone. Each "💡 Light ON" is the end of an encrypted request that traveled from your phone, through your router, to this Go process.</p>
<h2 id="heading-what-i-learned">What I Learned</h2>
<p>Building this cleared up several things I'd been fuzzy on:</p>
<ol>
<li><p><strong>HomeKit is entirely local.</strong> There are no cloud servers involved in controlling devices – your commands go directly from phone to device over your LAN. This is why HomeKit devices work when your internet is down.</p>
</li>
<li><p><strong>The security model is solid.</strong> SRP for pairing means the PIN never crosses the network. Ed25519 + ChaCha20 for sessions means that even someone sniffing your WiFi sees only encrypted blobs.</p>
</li>
<li><p><strong>Matter doesn't replace HAP.</strong> At least not in Apple's ecosystem. Matter handles discovery and pairing across ecosystems, but Apple Home still uses HAP concepts internally.</p>
</li>
<li><p><strong>The protocol is HTTPish.</strong> Once you get past the encryption, it’s just PUT/GET requests with JSON bodies – surprisingly approachable.</p>
</li>
</ol>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>The <a target="_blank" href="https://github.com/rezmoss/virtual-light">code is here</a> if you want to experiment yourself. You could try adding brightness control, or create a switch instead of a light. The best way to understand a protocol is to speak it ;)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Apple Code Signing Handbook ]]>
                </title>
                <description>
                    <![CDATA[ In this handbook, I’ll demystify the Apple app code signing process. Apple's ecosystem is powerful, but its distribution mechanisms – with various identifiers, certificates, and profiles – can appear complex. This guide attempts to make that journey ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/apple-code-signing-handbook/</link>
                <guid isPermaLink="false">68489084490c709f6b3070ed</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sravan Karuturi ]]>
                </dc:creator>
                <pubDate>Tue, 10 Jun 2025 20:07:32 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749585600223/49e9c922-0b5d-4a98-a619-eedfd7a8b617.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this handbook, I’ll demystify the Apple app code signing process. Apple's ecosystem is powerful, but its distribution mechanisms – with various identifiers, certificates, and profiles – can appear complex. This guide attempts to make that journey more manageable and straightforward for you.</p>
<p>Throughout this handbook, you will learn how to:</p>
<ul>
<li><p>Correctly establish and manage an app's unique identity.</p>
</li>
<li><p>Understand the roles of different Apple developer certificates and how to create and manage them.</p>
</li>
<li><p>Differentiate between various types of provisioning profiles and know when to use each one.</p>
</li>
</ul>
<p>This guide is geared towards new developers who want to learn how the code signing process works, but it should also be useful experienced developers who want or need to refresh their memory.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>While there are no hard prerequisites to understanding the certificates, bundles, and provisioning profiles for distributing on Apple platforms, it helps to have an Apple developer account to follow along.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-app-ids-bundle-ids-your-apps-identity">App IDs, Bundle IDs – Your App’s Identity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-distribution-a-deep-dive-into-certificates">Understanding Distribution: A Deep Dive into Certificates</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-bridge-between-everything-provisioning-profiles">Bridge between everything: Provisioning Profiles</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-device-management-development-and-ad-hoc-builds">Device management – Development and Ad Hoc Builds</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-possibilities-enabling-capabilities-and-services">Possibilities: Enabling Capabilities and Services</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-app-ids-bundle-ids-your-apps-identity"><strong>App IDs, Bundle IDs — Your App’s Identity</strong></h2>
<p>The Bundle ID and the corresponding App ID registered with Apple form the basis of an application’s identity. Establishing these correctly from the beginning is very important, as errors or misconfigurations here can lead to significant complications down the line, particularly once you’ve submitted your app to App Store Connect.</p>
<h3 id="heading-understanding-cfbundleidentifier-bundle-id">Understanding <code>CFBundleIdentifier</code> (Bundle ID)</h3>
<h4 id="heading-what-is-the-bundle-id">What is the “Bundle ID”?</h4>
<p>Think of the Bundle ID as a unique name or a fingerprint for your app. The <code>CFBundleIdentifier</code>, more commonly known as the <strong>Bundle ID</strong>, is a string that uniquely identifies your application.</p>
<p>This identifier is not just a name – it serves multiple crucial purposes.</p>
<ul>
<li><p>The operating system relies on it to apply specific preferences and settings to an app.</p>
</li>
<li><p>This is used to launch the application from other apps etc.</p>
</li>
<li><p>It plays an essential role in the validation of an app's code signature, ensuring the app's integrity and authenticity.</p>
</li>
<li><p>The Bundle ID defined in an app's Info.plist file must exactly match the Bundle ID registered for the app in App Store Connect for successful submission and distribution.</p>
</li>
</ul>
<p>The Bundle ID string must adhere to specific character limitations: it can only contain alphanumeric characters <code>A-Z, a-z, 0-9</code>, hyphens <code>-</code>, and periods <code>.</code>. It's important to note that Bundle IDs are treated as <strong>case-insensitive</strong> by the system.</p>
<h3 id="heading-how-to-choose-and-format-your-bundle-id-reverse-dns-and-best-practices">How to Choose and Format Your Bundle ID (Reverse-DNS and Best Practices)</h3>
<p>Apple highly recommends, and it is standard practice, to use a reverse-DNS (Domain Name System) format for Bundle IDs.</p>
<p>A common example would be <code>com.yourcompanyname.appname</code>. This convention leverages the global uniqueness of domain names to help ensure the global uniqueness of Bundle IDs.</p>
<p>If an organization uses its unique domain name (for example, <code>sravan.gg</code> becomes <code>gg.sravan</code> ) as the prefix, and the app name is unique within that organization, the resulting Bundle ID (for example, <code>gg.sravan.mycoolapp</code> ) is highly likely to be unique worldwide.</p>
<p><strong>Sidenote</strong>: While Xcode won’t stop you from creating something like <code>com.google.mapping</code> or something like that even if you don’t work at Google, this will most likely get rejected when it goes through the AppStore review process. This is because this implies ownership of that domain. So, while it’s technically possible when starting out, you shouldn’t use domains that don’t belong to you.</p>
<p>The fundamental nature of the Bundle ID as a unique, system-wide identifier – coupled with its immutability after an app is first uploaded to App Store Connect – means that you should treat its selection with the same seriousness as choosing a <strong>permanent, unchangeable identifier</strong> for a critical entity. A mistake in the Bundle ID after this point can necessitate creating an entirely new app listing on the App Store.</p>
<h3 id="heading-app-ids-in-the-apple-developer-portal-explicit-vs-wildcard">App IDs in the Apple Developer Portal: Explicit vs. Wildcard</h3>
<h4 id="heading-which-one-do-you-need">Which One Do You Need?</h4>
<p>In the Apple Developer Portal, developers register an "App ID." This App ID is a record that links one or more applications from a single development team to specific app services (capabilities) and is used in provisioning profiles. We’ll learn more about this in the following sections.</p>
<p>There are two main types of App IDs:</p>
<ul>
<li><p><strong>Explicit App ID:</strong> This type is used for a single application. The Bundle ID specified within an explicit App ID must be an exact match for the CFBundleIdentifier in the app's Info.plist file (for example, <code>com.mycompany.myapp</code>). Explicit App IDs are required for apps that use many of Apple's specific services and capabilities, such as In-App Purchases (which are enabled by default for explicit App IDs), Push Notifications, iCloud, HealthKit, and Sign in with Apple.</p>
</li>
<li><p><strong>Wildcard App ID:</strong> This type can be used for a set of applications that share a common Bundle ID prefix. It contains an asterisk (*) as the last part of its Bundle ID string (for example, <code>com.mycompany.*</code>). This wildcard App ID would match any app whose Bundle ID starts with <code>com.mycompany.</code>, such as <a target="_blank" href="http://com.mycompany.app"><code>com.mycompany.app</code></a> or <code>com.mycompany.utility</code>. But you can’t use wildcard App IDs if the app requires services or capabilities that mandate an explicit App ID.</p>
</li>
</ul>
<p>The choice between an explicit and a wildcard App ID has significant implications. The App ID acts as a central registration point, and the capabilities are "enabled" for this registration – more on capabilities later in this handbook.</p>
<p>You can think of an explicit App ID as a specific key designed to unlock extra "keyholes" (capabilities). A wildcard App ID, being more generic, might not fit these extra keyholes. If you choose a wildcard App ID initially for convenience, but you need a feature requiring an explicit App ID (like Push Notifications) later, you’ll be forced to create a new explicit App ID and reconfigure associated settings and provisioning profiles.</p>
<p>So, make sure you carefully consider your current and future app features when selecting an App ID type. The following table provides a quick comparison**.**</p>
<p>My personal recommendation is always go with explicit App Ids unless you need the flexibility of wildcard app ids.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Explicit App ID</strong></td><td><strong>Wildcard App ID</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Bundle ID Match</strong></td><td>Exact match (for example, <a target="_blank" href="http://com.foo.bar">com.foo.bar</a>)</td><td>Suffix match (for example, <a target="_blank" href="http://com.foo">com.foo</a>.*)</td></tr>
<tr>
<td><strong>Use Case</strong></td><td>Single app</td><td>Set of apps with similar base ID</td></tr>
<tr>
<td><strong>Capabilities</strong></td><td>Supports all capabilities</td><td>Limited (cannot use services requiring explicit IDs)</td></tr>
<tr>
<td><strong>Uniqueness</strong></td><td>Globally unique identifier for one specific app</td><td>Identifies a group of apps</td></tr>
</tbody>
</table>
</div><h3 id="heading-step-by-step-how-to-register-your-app-id-in-the-apple-developer-portal">Step-by-Step: How to Register Your App ID in the Apple Developer Portal</h3>
<p>To register an App ID, an you’ll need an <strong>Apple Developer Program membership</strong>. Also, the actions must be performed by someone with an Account Holder or Admin role.</p>
<p>The process is as follows:</p>
<ol>
<li><p>Sign in to the Apple Developer Portal and navigate to "Certificates, Identifiers &amp; Profiles," then select "Identifiers" from the sidebar.</p>
</li>
<li><p>Click the “Add button (+)” to create a new identifier.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748642247245/a24b527f-e810-4a9c-b75a-dcd3d189b1d1.png" alt="Picture depicting the Add button" class="image--center mx-auto" width="1130" height="404" loading="lazy"></p>
</li>
<li><p>Select "App IDs" from the list of options and click "Continue."</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748642283885/851f64f3-e608-4fb7-9f31-bd30adb64beb.png" alt="851f64f3-e608-4fb7-9f31-bd30adb64beb" class="image--center mx-auto" width="1628" height="704" loading="lazy"></p>
</li>
<li><p>Make sure that the "App" type is selected (it usually is by default) and click "Continue."</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748642318142/a7b28529-bbe6-4240-953e-836de3e948ac.png" alt="App type selection" class="image--center mx-auto" width="1526" height="766" loading="lazy"></p>
</li>
<li><p>Enter a "Description" for the App ID. This is for your reference within the portal (for example, "My very cool App ID").</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748642392862/a5322cf5-3d75-4b0b-93bf-d46dd1ce8afe.png" alt="App Id registration screen" class="image--center mx-auto" width="2446" height="698" loading="lazy"></p>
</li>
<li><p>Choose the "App ID Type": "Explicit" or "Wildcard."</p>
</li>
<li><p>For an "Explicit App ID," enter the exact Bundle ID that will be used in your Xcode project (for example, <code>com.yourcompany.yourapp</code>). For a "Wildcard App ID," enter a Bundle ID suffix ending with an asterisk (for example, <code>com.yourcompany.*</code>).</p>
</li>
<li><p>Scroll down to the "Capabilities" section and select the checkboxes for any app services your app will use. Some capabilities might require further configuration at this stage or later. (Again, we’ll cover app capabilities in more detail later on).</p>
</li>
<li><p>Click "Continue," review all the details carefully, and then click "Register" to finalize the App ID creation.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748642432661/2052a435-ed0e-404a-9178-7d6541fc9421.png" alt="Confirm the App ID screen" class="image--center mx-auto" width="2486" height="708" loading="lazy"></p>
</li>
</ol>
<h3 id="heading-how-to-manage-your-bundle-id-xcode-app-store-connect-and-the-point-of-no-return">How to Manage Your Bundle ID: Xcode, App Store Connect, and the Point of No Return</h3>
<p>The Bundle ID specified in an Xcode project is critical. To set it:</p>
<ol>
<li><p>In the Xcode project navigator, select the target for your app.</p>
</li>
<li><p>Open the "Signing &amp; Capabilities" tab.</p>
</li>
<li><p>Expand the "Signing" section.</p>
</li>
<li><p>In the "Bundle Identifier" text field, enter the Bundle ID. This identifier must precisely match the Bundle ID associated with an explicit App ID registered in the Developer Portal, or conform to the pattern of a wildcard App ID if applicable.</p>
</li>
</ol>
<p>It's important to understand the difference between the "Bundle ID" (or <code>CFBundleIdentifier</code>) in the Xcode project and the "App ID" registered in the Developer Portal. The "App ID" in the developer portal is an entity that <em>contains</em> a “Bundle ID” string (either explicit or wildcard). The string in your Xcode project's "Bundle Identifier" field must match this contained string.</p>
<p>When preparing for distribution via TestFlight or the App Store, you’ll need to create an app record in App Store Connect. The Bundle ID you enter during this app record creation must exactly match the Bundle ID in the Xcode project.</p>
<h4 id="heading-a-critical-warning-immutability-after-first-upload">A Critical Warning: Immutability After First Upload</h4>
<p>This is a point of no return: Once you upload a build of an app to App Store Connect, the Bundle ID for that app record <strong>cannot be changed</strong>.</p>
<p>In addition, after an upload, you can’t delete the associated explicit App ID registered in the Developer Portal. This immutability highlights the need for <em>careful planning and verification</em> of the Bundle ID before any uploads occur.</p>
<p>If you prefer programmatic management or automation, the App Store Connect API provides resources for managing Bundle IDs. You can <a target="_blank" href="https://developer.apple.com/documentation/appstoreconnectapi">read more on that here</a>.</p>
<h2 id="heading-understanding-distribution-a-deep-dive-into-certificates"><strong>Understanding Distribution: A Deep Dive into Certificates</strong></h2>
<h3 id="heading-what-are-certificates">What are Certificates?</h3>
<p>Certificates are digital credentials that verify a <strong>developer's identity</strong> – that is, you – to Apple and, by extension, to the app users.</p>
<p>They are fundamental to Apple's code signing process, which is mandatory for all apps to ensure they originate from a <strong>known source</strong> and have not been tampered with since being signed.</p>
<h3 id="heading-what-is-code-signing-ensuring-trust-and-integrity">What is Code Signing: Ensuring Trust and Integrity</h3>
<p>Code signing is you as a developer signing the app with your signature. It is the process of attaching a digital signature to an app's code. This signature assures users of two key things:</p>
<ol>
<li><p><strong>Authenticity:</strong> The app was created by an identified Apple developer (an individual or a team).</p>
</li>
<li><p><strong>Integrity:</strong> The app's code has not been altered or corrupted since it was signed by the developer.</p>
</li>
</ol>
<p>The process involves using a private key, securely held by the developer (you), to create the signature. The corresponding public key, embedded within the developer's certificate (issued by Apple), is used by the system to verify this signature.</p>
<p>This system of identity verification and integrity checking is crucial. The developer's certificate, issued by Apple as a Certificate Authority (CA), vouches for their identity. The code signing process, using hashing and encryption, ensures that any modification to the code after signing would invalidate the signature.</p>
<p>For app developers, benefits of code signing include removing warnings on macOS for apps distributed outside the Mac App Store, providing a smoother user experience. It is a mandatory requirement for listing applications on any of Apple's App Stores. It also enhances security of the app as it acts as a deterrent against malicious tampering.</p>
<h3 id="heading-types-of-certificates-development-distribution-and-developer-id">Types of Certificates: Development, Distribution, and Developer ID</h3>
<p>Apple provides different types of certificates for various stages of development and methods of distribution. Each of them has a distinct role to play throughout the app development process.</p>
<h4 id="heading-1-development-certificates-for-example-apple-development">1. Development Certificates (for example, "Apple Development"):</h4>
<ul>
<li><p><strong>Purpose:</strong> Used to sign apps during the development phase, allowing them to be installed and run on a limited number of <em>registered test devices</em> and simulators for debugging and testing.</p>
</li>
<li><p><strong>Identifies:</strong> Typically identifies an individual developer through their developer ID.</p>
</li>
<li><p><strong>Used with:</strong> Development provisioning profiles – more on this later.</p>
</li>
</ul>
<h4 id="heading-2-distribution-certificates-for-example-apple-distribution">2. Distribution Certificates (for example, "Apple Distribution"):</h4>
<ul>
<li><p><strong>Purpose:</strong> Used to sign apps intended for distribution, either through Ad Hoc methods (to a limited set of <em>registered testers</em>) or for submission to the App Store.</p>
</li>
<li><p><strong>Identifies:</strong> The development team via the team identifier.</p>
</li>
<li><p><strong>Use Cases:</strong></p>
<ol>
<li><p><strong>App Store:</strong> For signing the final version of an app that will be uploaded to App Store Connect for TestFlight beta testing or release on the App Store (iOS, macOS, tvOS, watchOS). These are used with App Store provisioning profiles – more on this later.</p>
</li>
<li><p><strong>Ad Hoc:</strong> For signing apps that will be distributed to a <em>limited number of registered test devices outside of the App Store or TestFlight</em>. These are used with Ad Hoc provisioning profile. More on this later.</p>
</li>
</ol>
</li>
</ul>
<h4 id="heading-3-developer-id-certificates-for-mac-apps-distributed-outside-the-mac-app-store">3. Developer ID Certificates (for Mac apps distributed outside the Mac App Store):</h4>
<ul>
<li><p><strong>Purpose:</strong> Specifically for macOS developers who wish to distribute their applications directly to users (for example, from their own website) rather than through the Mac App Store. Gatekeeper on macOS recognizes apps signed with a Developer ID certificate, assuring users that the app is from a known developer and has not been tampered with.</p>
</li>
<li><p><strong>Types:</strong></p>
<ol>
<li><p><strong>Developer ID Application:</strong> Used to sign the Mac application bundle (.app) itself.</p>
</li>
<li><p><strong>Developer ID Installer:</strong> Used to sign a Mac Installer Package (.pkg) that contains the signed application.</p>
</li>
<li><p><strong>Limit:</strong> Developers can create up to five Developer ID Application certificates and up to five Developer ID Installer certificates.</p>
</li>
</ol>
</li>
</ul>
<p>The following table summarizes these certificate types:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Certificate Type</strong></td><td><strong>Issued To</strong></td><td><strong>Primary Purpose</strong></td><td><strong>Used With Provisioning Profile Type</strong></td><td><strong>Key Use Cases</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Apple Development</td><td>Individual Dev ID</td><td>Develop &amp; debug on registered devices</td><td>Development</td><td>Xcode builds for local testing, running on personal/team test devices.</td></tr>
<tr>
<td>Apple Distribution</td><td>Team ID</td><td>Submit app to App Store / Ad Hoc distribution</td><td>App Store, Ad Hoc</td><td>Final builds for TestFlight, App Store submission, or QA/client Ad Hoc builds.</td></tr>
<tr>
<td>Developer ID Application</td><td>Team ID</td><td>Sign Mac app for distribution outside Mac App Store</td><td><strong>Developer ID Provisioning</strong> <strong>Profile</strong> if the app utilizes specific capabilities (e.g., Push Notifications, Associated Domains).</td><td>Distributing Mac software directly to users (for example, from website).</td></tr>
<tr>
<td>Developer ID Installer</td><td>Team ID</td><td>Sign Mac Installer Pkg for distribution outside Mac App Store</td><td>N/A. (The app inside the package may need a profile).</td><td>Distributing Mac software in a .pkg installer directly to users.</td></tr>
<tr>
<td>APNs / Service Keys (.p8)</td><td>Team ID</td><td>Secure communication with specific Apple services</td><td>N/A for app signing</td><td>Push Notifications, MusicKit, DeviceCheck and so on. (Token-based authentication)</td></tr>
</tbody>
</table>
</div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748216973656/76df3f64-c84e-4195-a092-37c1143d8b1b.png" alt="Create a new certificate screen in App Store Connect" class="image--center mx-auto" width="1768" height="1384" loading="lazy"></p>
<h3 id="heading-how-to-create-an-apple-certificate-an-overview">How to Create an Apple Certificate – An Overview</h3>
<p>Here’s a general outline of how you create an Apple Certificate:</p>
<ul>
<li><p>Generate a Certificate Signing Request (CSR) on your Mac. (Yes you need a mac.)</p>
</li>
<li><p>You upload this CSR in AppStoreConnect as a part of creating the certificate.</p>
</li>
<li><p>Download the certificate from AppStoreConnect once it’s issued.</p>
</li>
<li><p>Install the certificate into your Keychain.</p>
</li>
</ul>
<p>Now we’ll go through each step in more detail. This part is very important, since we have to save some of the files generated locally or we lose the ability to transfer these certificates. This would mean revoking and re-issuing certificates (I have done this more times than I’d like to admit).</p>
<h4 id="heading-how-to-create-a-certificate-signing-request-csr">How to Create a Certificate Signing Request (CSR)</h4>
<p>A Certificate Signing Request (CSR) is a fancy name for an encrypted block of text containing information about who’s requesting the certificate (like your name and the public key). These are widely used in the cryptography world.</p>
<p>For our purposes, you’ll generate a CSR on your Mac and then submit it to Apple to request a digital certificate. The CSR generation process also creates a new public/private key pair on the Mac – the private key is stored in Keychain Access and is used for the eventual code signing.</p>
<p>To create a CSR using Keychain Access on macOS:</p>
<ol>
<li><p>Launch Keychain Access (you can find it at <code>/Applications/Utilities/</code> or use spotlight).</p>
</li>
<li><p>From the menu bar, choose Keychain Access &gt; Certificate Assistant &gt; Request a Certificate From a Certificate Authority.... (Here the Certificate Authority would be Apple).</p>
</li>
<li><p>In the dialog, enter your email address and a common name for the key (for example, "My Mac Key" or "[Your Name] Dev Key"). This name is primarily for your identification in the Keychain.</p>
</li>
<li><p>Leave the "CA Email Address" field empty – we won’t email it to the Certificate Authority (Apple).</p>
</li>
<li><p>Select the "Saved to disk" option and click "Continue".</p>
</li>
<li><p>Save the file, which will have a .certSigningRequest extension. The corresponding private key is now stored in the login keychain. <strong>This private key is irreplaceable by Apple and you must store it yourself.</strong></p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748288861336/50f20da3-69d9-476d-97e7-331f9b9b5c76.png" alt="Dialog for the CSR creation" class="image--center mx-auto" width="684" height="510" loading="lazy"></p>
<h4 id="heading-how-to-generate-and-download-your-apple-certificates">How to Generate and Download Your Apple Certificates</h4>
<p>Once you’ve created a CSR, you can request a certificate from the Apple Developer Portal:</p>
<ol>
<li><p>Navigate to "Certificates, Identifiers &amp; Profiles" and select "Certificates".</p>
</li>
<li><p>Click the add button (+).</p>
</li>
<li><p>Choose the desired certificate type</p>
</li>
<li><p>Follow the prompts, and when asked, upload the .certSigningRequest file generated earlier.</p>
</li>
<li><p>After Apple processes the request, the certificate will be available for download as a .cer file.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748289386364/78f46b4e-b232-4484-98c2-dcb75120fd61.png" alt="Prompt to upload the CSR after selecting the type of certificate" class="image--center mx-auto" width="1293" height="319" loading="lazy"></p>
</li>
</ol>
<p>To install the certificate, double-click the downloaded .cer file. It will be added to the Keychain Access application – usually appearing in the "login" keychain under the "My Certificates" category, where it should be paired with the private key generated during the CSR generation process earlier.</p>
<p>You can see my certificate and private key in the image below for reference.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748289120657/38f711dd-887a-4fae-844d-e389c65234cf.png" alt="An example of how your certificate and the private key will look like in the keychain" class="image--center mx-auto" width="905" height="44" loading="lazy"></p>
<p>To recap, the CSR certifies that you generated the request from your mac. The certificate certifies that Apple (in this case, an intermediary like the "Apple Worldwide Developer Relations Certification Authority") confirms that they verified the CSR and that it is indeed you who will sign with the certificate (<code>.cer</code>) file.</p>
<p>This is enforced by only you having access to the private key – if you lose it, you cannot use this certificate anymore.</p>
<p>So, if you use this certificate (and the private key) to sign an app, the app store / operating system knows that it is you for sure since Apple confirmed it.</p>
<h3 id="heading-how-to-store-your-keys-what-are-p12-files">How to Store Your Keys: What are .p12 Files?</h3>
<p>As I mentioned in the previous section, to code sign an app you need your certificate (containing the public key) and the corresponding private key. This is created along with the CSR, and you can find it in the <code>Keychain Access</code> app.</p>
<p>We call the combination of the certificate and the private key a digital identity. This proves your identity when you sign an app with them.</p>
<h4 id="heading-p12-files-personal-information-exchange">.p12 Files (Personal Information Exchange):</h4>
<p>A .p12 file is a password-protected archive format used to bundle a certificate along with its private key. Its primary purposes are:</p>
<ul>
<li><p>Backing up the digital identity in case you lose access to your Mac.</p>
</li>
<li><p>Transferring the digital identity to another Mac (for example, for another team member or a new development machine).</p>
</li>
<li><p>Providing the identity to automated build systems or third-party build services.</p>
</li>
</ul>
<p>Historically, I have stored the .p12 file on a shared drive with my team and shared the password to it verbally – you can also store it in a local backup disk.</p>
<p>Great. So how do you create one?</p>
<h4 id="heading-to-export-a-p12-file-from-keychain-access">To export a .p12 file from Keychain Access:</h4>
<ol>
<li><p>Open Keychain Access, select the "login" keychain, and go to the "My Certificates" category.</p>
</li>
<li><p>Locate the desired certificate. It should have an expandable disclosure triangle indicating an associated private key (look at the image of my certificate above).</p>
</li>
<li><p>Select <em>both</em> the certificate and its private key (or right-click the certificate and choose "Export").</p>
</li>
<li><p>Right-click and choose "Export [X] items...".</p>
</li>
<li><p>In the save dialog, choose the "Personal Information Exchange (.p12)" file format.</p>
</li>
<li><p>Assign a strong password to protect the .p12 file. This password will be required when importing the file elsewhere. It is crucial for security.</p>
</li>
<li><p>Save the file to a secure location.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748297124625/f9d2cfe0-3538-405e-8fb0-af08276c4326.png" alt="Image of exporting my certificate and private key as a .p12 file" class="image--center mx-auto" width="468" height="266" loading="lazy"></p>
</li>
</ol>
<h2 id="heading-bridge-between-everything-provisioning-profiles"><strong>Bridge Between Everything: Provisioning Profiles</strong></h2>
<p>Provisioning profiles are the final link between an App ID, developer certificates, and, in some cases, a list of specific test devices. They act as a permission slip, authorizing an app signed with a particular certificate to be installed and run either on designated devices or to be submitted to the App Store.</p>
<h3 id="heading-what-exactly-is-a-provisioning-profile">What Exactly is a Provisioning Profile?</h3>
<p>A provisioning profile is a <code>.mobileprovision</code> (for iOS / VisionOS) or <code>.provisionprofile</code> (for macOS) file that holds several key pieces of information:</p>
<ul>
<li><p><strong>The App ID:</strong> Specifies which application (or set of applications, if using a wildcard App ID) the profile applies to.</p>
</li>
<li><p><strong>Certificates:</strong> Contains one or more developer or distribution certificates that can be used to sign the app.</p>
</li>
<li><p><strong>Device UDIDs (for Development and Ad Hoc):</strong> For profiles intended for testing on specific devices, it includes a list of the Unique Device Identifiers (UDIDs) of those authorized devices – more on devices in the next section.</p>
</li>
<li><p><strong>Entitlements:</strong> A list of app services or capabilities (like Push Notifications, iCloud, App Groups) that the app is permitted to use. These are derived from the capabilities enabled for the <em>associated App ID</em>.</p>
</li>
</ul>
<p>You can open the file using <code>vim</code> or any editor to see parts of the content which include the App Id, Operating Systems, Certificates, and so on.</p>
<p>The operating system checks the provisioning profile at app launch to ensure the app is authorized to run on the current device and use the requested services. If the profile is missing, invalid, or doesn't match the app's signature or the device, the app will not launch.</p>
<p>They are difference from certificates, because certificates are tied to you as a developer. But provisioning profiles are to a specific app – with specific capabilities to a specific developer and maybe on specific devices.</p>
<p>If any of these change (let’s say you added a capability or your certificate expired, for example), you’ll need to generate the provisioning profile again. These are the files you will work with the most out of all the above, and any change can cause your profile to become invalid.</p>
<h3 id="heading-types-of-provisioning-profiles-development-ad-hoc-app-store-and-enterprise">Types of Provisioning Profiles: Development, Ad Hoc, App Store, (and Enterprise)</h3>
<h3 id="heading-types-of-provisioning-profiles-development-ad-hoc-app-store-and-enterprise-1"><strong>Types of Provisioning Profiles: Development, Ad Hoc, App Store, (and Enterprise)</strong></h3>
<p>Just like certificates, we have multiple types of provisioning profiles. Similar to certificates, there can be development and distribution provisioning profiles.</p>
<p>Since we also keep track of the devices a profile is supposed to run, we have several kinds of distribution profiles based on which devices it should run on.</p>
<p>We also have special profiles like “Enterprise” which will add additional capabilities (like main camera access on the Vision Pro) but will restrict your app distribution methods to enterprise only.</p>
<p>We will go over each of these types now. Feel free to skip to the one that you’re looking for.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Profile Type</strong></td><td><strong>Purpose</strong></td><td><strong>Required Certificate Type(s)</strong></td><td><strong>Device Registration Required?</strong></td><td><strong>Distribution Method</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Development</strong></td><td>Install &amp; debug on registered devices during development (need Xcode to install).</td><td>Development</td><td>Yes</td><td>Xcode run, local device deployment.</td></tr>
<tr>
<td><strong>Ad Hoc</strong></td><td>Distribute to a limited number of registered test devices (no need for Xcode).</td><td>Distribution</td><td>Yes</td><td>Manual install (for example, via link, email, MDM) for testers.</td></tr>
<tr>
<td><strong>App Store Connect</strong></td><td>Submit app to App Store Connect for TestFlight or App Store release.</td><td>Distribution</td><td>No</td><td>Upload to App Store Connect.</td></tr>
<tr>
<td><strong>Enterprise</strong></td><td>Distribute proprietary apps to employees within an organization.</td><td>Enterprise (Distribution)</td><td>No (subject to program terms)</td><td>Internal distribution (e.g., private portal, MDM).</td></tr>
<tr>
<td><strong>Developer ID</strong></td><td>Allows a macOS app that is distributed outside the App Store to use advanced features</td><td>Developer ID</td><td>No</td><td>Outside the Mac App Store (for example, a web page, USB, MDM )</td></tr>
</tbody>
</table>
</div><h4 id="heading-development-provisioning-profile"><strong>Development Provisioning Profile:</strong></h4>
<ul>
<li><p><strong>Allows</strong> an app to be installed and debugged on specific devices registered in the developer's account during the active development phase. More on device registration later.</p>
</li>
<li><p><strong>Contains</strong> an App ID, one or more development certificates, and a list of registered device UDIDs.</p>
</li>
<li><p><strong>Created</strong> manually in the Apple Developer Portal or generated automatically by Xcode if <code>Automatically manage signing</code> is enabled.</p>
</li>
</ul>
<h4 id="heading-ad-hoc-provisioning-profile"><strong>Ad Hoc Provisioning Profile:</strong></h4>
<ul>
<li><p><strong>Allows</strong> distribution of an app to a limited number of registered test devices <strong>without</strong> requiring Xcode for installation. This is ideal for distributing builds to QA teams, beta testers, or clients for feedback.</p>
</li>
<li><p><strong>Contains</strong> an App ID (often an explicit App ID, or an Xcode-managed one like <code>XC Wildcard</code> or <code>XC</code>), a single distribution certificate, and a list of registered device UDIDs.</p>
</li>
<li><p><strong>Created</strong> manually in the Developer Portal or managed by Xcode's automatic signing.</p>
</li>
</ul>
<h4 id="heading-app-store-connect-provisioning-profile"><strong>App Store Connect Provisioning Profile:</strong></h4>
<ul>
<li><p><strong>Required</strong> to sign an app for submission to App Store Connect. This is the pathway for distributing apps via TestFlight for broader beta testing and for official release on the App Store.</p>
</li>
<li><p><strong>Contains</strong> an explicit App ID (or an App ID that matches the app's bundle ID, including Xcode-managed App IDs), and a single distribution certificate. <em>Device UDIDs are not included in this profile type since this is meant for broader distribution.</em></p>
</li>
<li><p><strong>Created</strong> manually in the Developer Portal or managed by Xcode's automatic signing.</p>
</li>
</ul>
<h4 id="heading-enterprise-provisioning-profile"><strong>Enterprise Provisioning Profile:</strong></h4>
<ul>
<li><p>Exclusively for members of the <strong>Apple Developer Enterprise Program</strong>. It allows developers of these orgs to distribute proprietary, in-house applications directly to their employees, bypassing the public App Store.</p>
</li>
<li><p>Note: This program has stringent enrollment criteria and is strictly for internal distribution within the enrolled organization – these apps cannot be pushed to AppStore.</p>
</li>
</ul>
<h4 id="heading-developer-id-provisioning-profile"><strong>Developer ID Provisioning Profile:</strong></h4>
<ul>
<li><p><strong>Required</strong> to utilize certain Apple services or advanced capabilities like Push Notifications, CloudKit, Sign in with Apple, or specific iCloud services.</p>
</li>
<li><p><strong>Contains</strong> an App ID, a Developer ID distribution certificate, the entitlements authorized for the app.</p>
</li>
<li><p><strong>Created</strong> manually in the Developer Portal – will not be added automatically by Xcode’s automatic signing.</p>
</li>
</ul>
<h3 id="heading-how-to-create-and-manage-provisioning-profiles">How to Create and Manage Provisioning Profiles</h3>
<p>Creating and managing provisioning profiles usually requires an Account Holder or Admin role in the Apple Developer Program. You also need a configured App ID, the appropriate certificate(s), and for Development or Ad Hoc profiles, a list of registered device UDIDs.</p>
<p>If you are new developer, my recommendation is to read this article completely, then get back to this section once you have your devices setup.</p>
<p>General steps for manual creation in the Developer Portal:</p>
<ol>
<li><p>Navigate to "Certificates, Identifiers &amp; Profiles" and select "Profiles".</p>
</li>
<li><p>Click the add button (+).</p>
</li>
<li><p>Select the type of provisioning profile to create (for example, "iOS App Development," "Ad Hoc," "App Store").</p>
</li>
<li><p>Choose the App ID you’re targeting from the dropdown list.</p>
</li>
<li><p>Select the certificate(s) to include in the profile. Development profiles can include multiple development certificates – so you can include all the team member certificates here. Ad Hoc and App Store profiles include a single distribution certificate.</p>
</li>
<li><p>If creating a Development or Ad Hoc profile, select the registered devices to include.</p>
</li>
<li><p>Provide a name for the provisioning profile (this is for identification in the portal and Xcode).</p>
</li>
<li><p>Click "Generate" and then "Download" the <code>.mobileprovision</code> or <code>.provisionprofile</code> file.</p>
</li>
</ol>
<p>You need to make downloaded profiles available to Xcode. You can often do this by double-clicking the downloaded file or by refreshing profiles within Xcode's account settings (Preferences &gt; Accounts).</p>
<p>I really like Xcode's "Automatically manage signing" feature and it can simplify profile management by a lot. It creates and updates profiles as needed. But, understanding the manual process is crucial for troubleshooting because when things go wrong, it is straightforward to debug the issue with this knowledge.</p>
<p>Provisioning profiles will become invalid and require regeneration if:</p>
<ul>
<li><p>The capabilities of the associated App ID are changed – let’s say you added a new capability.</p>
</li>
<li><p>An included certificate expires or is revoked.</p>
</li>
<li><p>For Development/Ad Hoc profiles, if devices are added or removed from the registered list in a way that affects the profile's device set, or if the profile's own expiration date is reached. When such changes occur, you have to edit the profile (if possible) or delete it and recreate it in the Developer Portal, then re-download it and install it again. While this may seem like a complicated step, it’s straightforward if you do it a couple of times.</p>
</li>
</ul>
<h2 id="heading-device-management-development-and-ad-hoc-builds"><strong>Device Management — Development and Ad Hoc Builds</strong></h2>
<p>For testing applications on physical Apple hardware outside of Testflight or AppStore, you’ll need to register the Unique Device Identifiers (UDIDs) of your test devices with your Apple Developer account. This registration is a necessary step for creating Development and Ad Hoc provisioning profiles.</p>
<h3 id="heading-why-you-need-to-register-test-devices">Why You Need to Register Test Devices</h3>
<p>Development and Ad Hoc provisioning profiles are specifically tied to a list of registered devices. An app signed with this profile can be installed directly without going through App Store process. This means that you need to register devices you intend to develop on. This restricts bad faith actors from releasing apps widely without developer and App Store supervision.</p>
<p>The UUID of a device is like a physical address (think Mac Address). If you don’t include this in the provisioning profile you used to sign an app package, it cannot be installed on that device.</p>
<p>Let’s go over the steps to do that.</p>
<h3 id="heading-how-to-find-your-devices-udid-unique-device-identifier">How to Find Your Device's UDID (Unique Device Identifier)</h3>
<p>A UDID is a unique 40-character hexadecimal string (for older devices) or a 25-character string (format XXXXXXXX-XXXXXXXXXXXXXXXX) that uniquely identifies a specific iPhone, iPad, Apple Watch, Apple TV, Vision Pro or Mac.</p>
<p>There are several ways to find a device's UDID:</p>
<ul>
<li><p><strong>Xcode:</strong> Connect the device to a Mac running Xcode. Open Xcode and navigate to Window &gt; Devices and Simulators. Select the connected device from the list on the left. The UDID will be displayed as the "Identifier" in the device information panel.</p>
</li>
<li><p><strong>Finder (macOS Catalina and later):</strong> Connect the iOS or iPadOS device to a Mac. Open Finder and select the device from the sidebar under "Locations." The UDID may be displayed directly, or it might be necessary to click on the line of text beneath the device's name (which shows model, storage, and OS version) to cycle through to display the UDID.</p>
</li>
<li><p><strong>iTunes (older macOS versions):</strong> For Macs running macOS Mojave or earlier, connect the device and open iTunes. Select the device icon when it appears. In the "Summary" tab, click on the "Serial Number" field; this will change to display the UDID.</p>
</li>
<li><p><strong>Apple Silicon Macs:</strong> When registering an Apple Silicon Mac, it's important to look for the "Provisioning UDID," which can be found in System Information under Hardware &gt; Provisioning UDID.</p>
</li>
<li><p><strong>Other Ways:</strong> There are some websites that will install a profile on to your device to get the UUID – so as an absolute last resort, you can do this. <em>But I highly recommend doing it in the one of the official ways to avoid any potential issues.</em></p>
</li>
</ul>
<h3 id="heading-how-to-register-devices-in-the-apple-developer-portal">How to Register Devices in the Apple Developer Portal</h3>
<p>Device registration is managed through the "Certificates, Identifiers &amp; Profiles" section of the Apple Developer Portal (developer.apple.com) and typically requires an Account Holder or Admin role.</p>
<p>To manually register a single device:</p>
<ol>
<li><p>Sign in to the Apple Developer Portal and navigate to "Certificates, Identifiers &amp; Profiles," then select "Devices" from the sidebar.</p>
</li>
<li><p>Click the add button (+) to register a new device.</p>
</li>
<li><p>Select the correct platform for the device (for example, iOS, macOS, tvOS, watchOS).</p>
</li>
<li><p>Enter a descriptive "Device Name" (this is for your reference, for example, "Sravan’s iPhone 11 Pro") and the device's UDID obtained in the previous step.</p>
</li>
<li><p>Click "Continue," review the information to make sure everything is correct, and then click "Register".</p>
</li>
</ol>
<p>For registering multiple devices, the portal supports uploading a specially formatted text file (a .txt or a .deviceids file) containing device names and UDIDs.</p>
<p>If "Automatically manage signing" is enabled in Xcode, Xcode can automatically register a connected device when it's selected as a build target. This is the way I managed all of my personal projects and devices. On the other hand, the file upload was really useful at my workplace to keep track of all the devices and add them at once.</p>
<h3 id="heading-understanding-device-limits-and-annual-resets">Understanding Device Limits and Annual Resets</h3>
<p>The Apple Developer Program imposes limits on the number of devices that can be registered for testing:</p>
<ul>
<li><p><strong>Annual Limit:</strong> Each membership year, a development team can register up to 100 devices for each product family (iPhone, iPad, Apple Watch, Apple TV, Apple Vision Pro, Mac). If you are a large team, this can potentially bottleneck you. When we ran into this issue, we created a new development team that could be split so that it didn’t have too much interdependence. There is no other way as far as I know, other than asking Apple and appealing them.</p>
</li>
<li><p><strong>Disabling Devices:</strong> While a device can be disabled in the portal during the membership year, doing so <strong>does not free up its slot or increase the number of available devices for that year</strong>. This part is frustrating but I think this is the only way they can enforce the 100 device limit to avoid people swapping devices. They should just provide a pathway to increase the limit, really. Disabling a device will, however, invalidate any provisioning profiles that include it, requiring those profiles to be regenerated.</p>
</li>
<li><p><strong>Resetting Device List (Start of New Membership Year):</strong> At the beginning of a new membership year, Account Holders, Admins, and App Managers are given a one-time option when they first sign in to "Certificates, Identifiers &amp; Profiles" to remove devices from their list. This allows them to "reset" their available device count back to 100 for each product family. You can choose to remove specific devices or all registered devices. <strong>This is your one chance per year to remove unused devices completely and free up slots for new devices.</strong></p>
</li>
<li><p><strong>Membership Expiration:</strong> If a developer program membership is nearing expiration and is not planned for renewal, the Account Holder will have an option, starting 30 days before expiration, to download a copy of their registered device list. They can also opt to have all devices removed from the account immediately upon membership expiration. If no action is taken, devices are typically removed automatically 180 days after membership expiration.</p>
</li>
</ul>
<h2 id="heading-possibilities-enabling-capabilities-and-services"><strong>Possibilities: Enabling Capabilities and Services</strong></h2>
<p>App Capabilities (or App Services) are features provided by Apple that we (as developers) can integrate into our applications to extend functionality and provide richer user experiences. Examples include iCloud storage, Push Notifications, Sign in with Apple, Apple Pay and HealthKit integration. Enabling these often requires explicit configuration for an app's App ID in the Apple Developer Portal and within the Xcode project.</p>
<h3 id="heading-why-you-should-use-capabilities">Why You Should Use Capabilities</h3>
<p>Making full use of these App capabilities can set your app apart from other apps in a very noticeable way. You can use Apple Wallet integration if you want users to scan a membership card. You can use journaling suggestions if you want to prompt them to journal something. You can use iCloud Storage to lean further into inter-device synchronization.</p>
<p>When you enable a capability for an App ID, it results in specific entitlements being added to the app's provisioning profile. These entitlements are permissions that the operating system checks at runtime to ensure the app is authorized to use the requested service.</p>
<h3 id="heading-how-to-configure-capabilities-for-your-app-id-apple-developer-portal">How to Configure Capabilities for Your App ID (Apple Developer Portal)</h3>
<p>Enabling and configuring capabilities is typically done by an Account Holder or Admin in the Apple Developer Portal (developer.apple.com).</p>
<ol>
<li><p>Navigate to "Certificates, Identifiers &amp; Profiles" and select "Identifiers."</p>
</li>
<li><p>Choose the App ID for which capabilities need to be configured.</p>
</li>
<li><p>In the App ID's settings, there will be a "Capabilities" tab. Select the checkboxes for the capabilities the app requires.</p>
</li>
<li><p>Many capabilities require additional configuration steps. For these, a "Configure" or "Edit" button will usually appear next to the capability once selected. Examples include:</p>
</li>
</ol>
<ul>
<li><p><strong>App Groups:</strong> Requires creating or selecting an app group identifier to allow data sharing between a main app and its extensions, or between different apps from the same developer.</p>
</li>
<li><p><strong>Apple Pay:</strong> Requires associating one or more Merchant IDs with the App ID.</p>
</li>
<li><p><strong>iCloud:</strong> May require choosing Xcode version compatibility and creating or assigning iCloud containers for Key-Value or Document storage</p>
</li>
<li><p><strong>Sign in with Apple:</strong> May require configuring the App ID as a primary app or grouping it with an existing primary App ID, and optionally providing a server-to-server notification endpoint URL.</p>
</li>
</ul>
<ol start="5">
<li>After configuring all selected capabilities, click "Save." A warning dialog may appear, which needs confirmation to finalize the changes.</li>
</ol>
<p><strong>Enabling a capability in the Developer Portal is only one part of the process.</strong> You’ll also need to add and configure it within the app's target in the Xcode project, under the "Signing &amp; Capabilities" tab.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748480139418/6a4007b3-01bd-484a-865c-8c5e728e15e0.png" alt="Showing the Signing &amp; Capabilities screen in Xcode" class="image--center mx-auto" width="614" height="114" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748480260906/e0dcec33-24ce-448b-91be-b79f5638e6fc.png" alt="Screenshot showing the Capabilities selector in Xcode" class="image--center mx-auto" width="793" height="608" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748480340624/ac56896a-0fb0-4cb0-a3fc-c894a255794a.png" alt="Screenshot of Xcode showing three capabilities. " class="image--center mx-auto" width="1187" height="434" loading="lazy"></p>
<ol>
<li><p>Navigate to the project settings and select “Signing &amp; Capabilities”.</p>
</li>
<li><p>Press the “+ Capability” button to select the capability.</p>
</li>
<li><p>Once selected, the capability should appear in the pane. Depending on the capability, you might want to configure it further.</p>
</li>
</ol>
<p>This Xcode step integrates the necessary frameworks, adds entitlements files to the project, and adjusts build settings.</p>
<h3 id="heading-how-enabling-capabilities-affects-your-provisioning-profiles">How Enabling Capabilities Affects Your Provisioning Profiles</h3>
<p>Changes to an App ID's enabled capabilities have a direct and significant impact on its associated provisioning profiles.</p>
<ul>
<li><p><strong>Invalidation:</strong> When a capability is enabled, disabled, or its configuration is modified for an App ID, <strong>all existing provisioning profiles that use that App ID immediately become invalid</strong>.</p>
</li>
<li><p><strong>Regeneration Required:</strong> These invalidated provisioning profiles must be regenerated (either by editing and re-saving them in the Developer Portal or by having Xcode's automatic signing handle it). The regenerated profiles will then include the updated set of entitlements corresponding to the newly configured capabilities.</p>
</li>
<li><p><strong>Platform Impact:</strong> Enabling a capability for an App ID that is used across multiple platforms (for example, an iOS app and its watchOS companion) will affect the provisioning profiles for all eligible platforms that use that App ID.</p>
</li>
</ul>
<p>This is something to keep in mind. Especially when it comes to distribution profiles since those are usually manually managed.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>While all of these might seem daunting, Apple’s automatic process should handle most of it. But I highly recommend learning how everything works so that you can debug it in case something goes wrong. I also highly recommend using manually created profiles for distribution.</p>
<p>While signing and handling certificates is not the most exciting part of the App development process, it is a necessary skill to have. In my next article, I will go over distributing an app from start to finish (which includes these processes and more restrictions).</p>
<p>You can follow me at <a class="user-mention" href="https://hashnode.com/@sravankaruturi">Sravan Karuturi</a> for my other posts.</p>
 ]]>
                </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="600" height="400" 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="600" height="400" 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="600" height="400" 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 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[ How to Turn Off Quick Note and Hot Corners [Solved for MacOS Monterey] ]]>
                </title>
                <description>
                    <![CDATA[ I recently updated to MacOS Monterey (Version 12.0). Sometimes software companies like Apple will add features I don't like, then enable them by default. This is what happened with the New Quick Note hot corner. Here is what the Quick Notes feature l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/turn-off-quick-note-mac-monterey/</link>
                <guid isPermaLink="false">66b8d63cb7a8332d9a6b209d</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mac ]]>
                    </category>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Quincy Larson ]]>
                </dc:creator>
                <pubDate>Thu, 18 Nov 2021 04:09:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/11/Window.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I recently updated to MacOS Monterey (Version 12.0). Sometimes software companies like Apple will add features I don't like, then enable them by default. This is what happened with the New Quick Note hot corner.</p>
<p>Here is what the Quick Notes feature looks like when you move your cursor to the lower right hand corner of the screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/Window_and_Notes_and_How_to_Turn_Off_Quick_Note_in_MacOS_Monterrey_-_freeCodeCamp_org_--.png" alt="Image" width="600" height="400" loading="lazy">
<em>The New Quick Note feature in the lower right hand screen of MacOS Monterey</em></p>
<p>I like a lot of MacOS Monterey's features, but I didn't like this popping up so frequently when I was moving my mouse around. So I disabled it. You can do this, too, and it only takes a few seconds.</p>
<h2 id="heading-how-to-disable-the-new-quick-note-feature-in-macos-monterey">How to Disable the New Quick Note Feature in MacOS Monterey</h2>
<p>First of all, navigate to your MacOS preferences. </p>
<h3 id="heading-step-1-open-system-preferences">Step #1: Open System Preferences</h3>
<p>The fastest way to do this is to press <strong>Command + Space</strong> to open up Spotlight.</p>
<p>Then type "pref" and you should see a System Preferences option.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/Spotlight_and_How_to_Turn_Off_Quick_Notes_in_Mac_-_Solved_for_MacOS_Monterey_12_0_Quick_Note_-_freeCodeCamp_org_---1.png" alt="Image" width="600" height="400" loading="lazy">
<em>MacOS Spotlight is a helpful way to open up applications quickly. You can open it by pressing Command + Space</em></p>
<h3 id="heading-step-2-open-mission-control-preferences">Step #2: Open Mission Control Preferences</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/System_Preferences_and_Developers_Spent_2_1_Billion_Minutes__4_000_years__Using_freeCodeCamp_in_2021__and_Other_Year-end_Facts_-_freeCodeCamp_org_---1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click the Mission Control icon pointed to above</em></p>
<h3 id="heading-step-3-click-the-hot-corners-button">Step #3: Click the "Hot Corners..." button</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/Mission_Control_and_Developers_Spent_2_1_Billion_Minutes__4_000_years__Using_freeCodeCamp_in_2021__and_Other_Year-end_Facts_-_freeCodeCamp_org_--.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Hot Corners button is in the lower left-hand corner</em></p>
<h3 id="heading-step-4-disable-the-quick-note-hot-corner-gesture">Step #4: Disable the Quick Note Hot Corner Gesture</h3>
<p>You can now disable the Quick Note hot corner. If you prefer, you could instead assign this hot corner to something else. I personally find these hot corners more distracting than helpful, and turn all four of them off. </p>
<p>Remember: anything you can do with a hot corner, you can do with the MacOS built-in Spotlight feature.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/OtherViews_and_Mission_Control_and_Developers_Spent_2_1_Billion_Minutes__4_000_years__Using_freeCodeCamp_in_2021__and_Other_Year-end_Facts_-_freeCodeCamp_org_--.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click the drop down for the lower-right hand corner and set it to "–" which means nothing will happen when you move your cursor to the lower right hand corner of your screen.</em></p>
<h3 id="heading-step-5-click-the-ok-button-and-close-mission-control">Step #5: Click the OK Button and Close Mission Control</h3>
<p>Congratulations. You have disabled the Quick Note hot corner. It shouldn't pop up anymore.</p>
<p>I hope this has been helpful. Have a fun, productive day.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Install Xcode Command Line Tools on a Mac ]]>
                </title>
                <description>
                    <![CDATA[ Developers need to install Xcode Command Line Tools before they can develop software on a Mac. Apple provides a complete development environment for programmers named Xcode. If you are developing software for macOS, iOS, tvOS, and watchOS, you must i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/install-xcode-command-line-tools/</link>
                <guid isPermaLink="false">66ba1609a16d07b8deb68309</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Xcode ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Kehoe ]]>
                </dc:creator>
                <pubDate>Mon, 19 Jul 2021 22:25:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/07/Terminal_Mac.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Developers need to install Xcode Command Line Tools before they can develop software on a Mac.</p>
<p>Apple provides a complete development environment for programmers named Xcode. If you are developing software for macOS, iOS, tvOS, and watchOS, you must install the full Xcode application. </p>
<p>It's not pre-installed, but you can install it from the <a target="_blank" href="https://developer.apple.com/download/">Apple developer website</a> or the App Store on your Mac.</p>
<h2 id="heading-what-are-xcode-command-line-tools">What are Xcode Command Line Tools?</h2>
<p>If you're not developing software for an Apple device, you won't need the full Xcode application (it requires over 40GB of disk space!).</p>
<p>Instead, you'll install Xcode Command Line Tools. It's a smaller package for software developers with tools that run on the command line, that is, in the Terminal application.</p>
<p>Programmers have used these tools on Unix operating systems since computing's beginnings, and they serve as the foundation of almost all software development. </p>
<p>Luckily, the Xcode Command Line Tools package only requires 1.2GB of space on your disk.</p>
<p>You have three choices to install Xcode Command Line Tools on a Mac:</p>
<ul>
<li>install the full Xcode package</li>
<li>install Xcode Command Line Tools when triggered by a command</li>
<li>install Xcode Command Line Tools as part of a Homebrew installation.</li>
</ul>
<p>I don't recommend installing the full Xcode package unless you're developing software for an Apple device. The download will take too long and it will consume unnecessary disk space. Instead, try either of two faster methods.</p>
<h2 id="heading-how-to-install-xcode-command-line-tools-from-a-command-prompt">How to Install Xcode Command Line Tools from a Command Prompt</h2>
<p>Apple has made it easy to install Xcode Command Line Tools because certain commands will prompt you to begin installation.</p>
<p>Here are examples of commands that will trigger a prompt to install Xcode Command Line Tools:</p>
<ul>
<li><code>clang</code> – a compiler that turns source code into an executable program</li>
<li><code>gcc</code> – the GNU compiler</li>
<li><code>git</code> – the save-as-you-go version control system</li>
</ul>
<p>Running any of these commands in the terminal will bring up a prompt to install Xcode Command Line Tools. I've written elsewhere about <a target="_blank" href="https://mac.install.guide/terminal/index.html">How to Open Terminal on MacOS</a> – just click the Spotlight icon in the menu bar and type “terminal.”</p>
<p>You can also enter the command <code>xcode-select --install</code> in the terminal to begin the installation process. You'll see a panel that asks you to install Xcode Command Line Tools.</p>
<p><img src="https://mac.install.guide/assets/images/ruby/install-Xcode-CLT.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click 'Install' to begin the download and installation process.</p>
<p><img src="https://mac.install.guide/assets/images/ruby/install-Xcode-CLT-progress.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Installation takes 8 minutes on a 2021 Mac M1 Mini, with a 100Mbps Internet connection. It's significantly slower on Mac Intel over a slow Internet connection.</p>
<p><img src="https://mac.install.guide/assets/images/ruby/install-Xcode-CLT-done.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You'll see a confirmation message when installation is complete.</p>
<p>Verify that you've successfully installed Xcode Command Line Tools:</p>
<pre><code class="lang-bash">$ xcode-select -p
</code></pre>
<p>You should see the following:</p>
<pre><code class="lang-bash">/Library/Developer/CommandLineTools
</code></pre>
<h2 id="heading-how-to-use-homebrew-to-install-xcode-command-line-tools">How to Use Homebrew to Install Xcode Command Line Tools</h2>
<p>As easy as it is to use the command prompt to install Xcode Command Line Tools, I recommend an even easier method: using Homebrew.</p>
<p>This option was only recently added to Homebrew, so many developers are not aware of it.</p>
<p>Homebrew is the popular Mac package manager. Most developers need programming languages and utilities that don't come installed on macOS and are not included in the Xcode Command Line Tools package. Homebrew can install almost any open-source tool for developers.</p>
<p>Since you'll probably need Homebrew, you might as well let Homebrew install Xcode Command Line Tools for you.</p>
<p>First, check if Homebrew is already installed.</p>
<pre><code class="lang-bash">$ brew
</code></pre>
<p>If Homebrew is not installed, you will see:</p>
<pre><code class="lang-bash">zsh: <span class="hljs-built_in">command</span> not found: brew
</code></pre>
<p>Homebrew provides an installation script you can run with a single command (check that it hasn't changed at the <a target="_blank" href="https://brew.sh/">Homebrew site</a>).</p>
<pre><code class="lang-bash">$ /bin/bash -c <span class="hljs-string">"<span class="hljs-subst">$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)</span>"</span>
</code></pre>
<p>The Homebrew installation script will ask you to enter your Mac user password. This is the password you use to sign in to your Mac.</p>
<pre><code class="lang-bash">Password:
</code></pre>
<p>You won't see the characters as you type. Press enter when you are done.</p>
<p><img src="https://mac.install.guide/assets/images/ruby/homebrew-enter-password.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you haven't already installed Xcode Command Line Tools, you'll see a message that "The Xcode Command Line Tools will be installed." Press return to continue when prompted by the Homebrew installation script.</p>
<p><img src="https://mac.install.guide/assets/images/ruby/install-homebrew.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You’ll see diagnostic and progress messages. Homebrew installation takes 2 to 15 minutes on a 2021 Mac M1 Mini, with a 100Mbps Internet connection. It's significantly slower on Mac Intel over a slow Internet connection.</p>
<p><img src="https://mac.install.guide/assets/images/ruby/homebrew-complete.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On Mac Intel machines, that's all you need to do – Homebrew is ready to use. On Mac Intel, Homebrew installs itself into the <code>/usr/local/bin</code> directory, which is already configured for access by the shell with the macOS default <code>$PATH</code>.</p>
<p>On Apple Silicon machines, there's one more step. Homebrew files are installed into the <code>/opt/homebrew</code> folder. But the folder is not part of the default <code>$PATH</code>. Follow Homebrew's advice and create a <code>~/.zprofile</code> file that contains a command which sets up Homebrew. Homebrew shows instructions at the end of the installation process:</p>
<pre><code class="lang-bash">- Add Homebrew to your PATH <span class="hljs-keyword">in</span> ~/.zprofile:
<span class="hljs-built_in">echo</span> <span class="hljs-string">'eval "$(/opt/homebrew/bin/brew shellenv)"'</span> &gt;&gt; ~/.zprofile
<span class="hljs-built_in">eval</span> <span class="hljs-string">"<span class="hljs-subst">$(/opt/homebrew/bin/brew shellenv)</span>"</span>
</code></pre>
<p>After you've installed Homebrew, check that Homebrew is installed properly.</p>
<pre><code class="lang-bash">$ brew doctor
</code></pre>
<p>You should see this:</p>
<pre><code class="lang-bash">Your system is ready to brew.
</code></pre>
<p>If Homebrew is successfully installed, there will be Homebrew files in <code>/usr/local</code> (for macOS Intel) or <code>/opt/homebrew</code> (for Apple Silicon).</p>
<p>Now you have both Xcode Command Line Tools and Homebrew installed. If you want to learn more about adding Homebrew packages to set up your development environment, see <a target="_blank" href="https://mac.install.guide/homebrew/6.html">Install a Homebrew Package</a>.</p>
<h2 id="heading-more-information">More information</h2>
<p>I've written an in-depth guide to <a target="_blank" href="https://mac.install.guide/commandlinetools/index.html">Install Xcode Command Line Tools</a> that goes beyond these basics. </p>
<p>In the guide, I explain how to check if <a target="_blank" href="https://mac.install.guide/commandlinetools/2.html">Xcode Command Line Tools Are Already Installed</a>. I go into more detail about how to <a target="_blank" href="https://mac.install.guide/commandlinetools/3.html">Install Xcode Command Line Tools with Homebrew</a>. Finally, I explain how to <a target="_blank" href="https://mac.install.guide/commandlinetools/6.html">Uninstall Xcode Command Line Tools</a>, <a target="_blank" href="https://mac.install.guide/commandlinetools/7.html">Reinstall Xcode Command Line Tools</a>, and provide a <a target="_blank" href="https://mac.install.guide/commandlinetools/8.html">List of Xcode Command Line Tools</a> that you can use.</p>
<p>There's also a complete guide to <a target="_blank" href="https://mac.install.guide/homebrew/index.html">Install Homebrew for Mac</a> that explains how to <a target="_blank" href="https://mac.install.guide/homebrew/4.html">Update Homebrew</a>, <a target="_blank" href="https://mac.install.guide/homebrew/5.html">Uninstall Homebrew</a>, and keep up with other <a target="_blank" href="https://mac.install.guide/homebrew/8.html">Housekeeping for Homebrew</a>.</p>
<h2 id="heading-your-development-environment">Your development environment</h2>
<p>MacOS is the most popular platform for software development because the operating system is based on Unix, the longtime standard for software development.</p>
<p>With Xcode Command Line Tools installed, you'll have a solid foundation for adding almost any open source development tool.</p>
<p>Add Homebrew and you have a package manager that can install version managers, programming languages, and almost any other tool you may need.</p>
<p>Combined with a text editor and terminal application, you'll be prepared for any tutorial you'll find on freeCodeCamp.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get the Identifier For Advertisers (IDFA) in iOS14 ]]>
                </title>
                <description>
                    <![CDATA[ If the title of this article means something to you, then you are probably aware of the earthquake caused by iOS14.  With the release of iOS14, there have been major changes in the way applications can gather information about a user. One of them dea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-the-identifier-for-advertisers-ios14/</link>
                <guid isPermaLink="false">66ba50108e44e0cdf1281252</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ios app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tomer ]]>
                </dc:creator>
                <pubDate>Tue, 22 Sep 2020 17:44:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/0_oIyg9OzrsA2PiXHW.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If the title of this article means something to you, then you are probably aware of the earthquake caused by iOS14. </p>
<p>With the release of iOS14, there have been major changes in the way applications can gather information about a user. One of them deals with the Identifier For Advertisers (or IDFA) and how applications can access it. </p>
<p>But for those that don't know, let's first explain what the IDFA is and why it's important.</p>
<h2 id="heading-what-is-an-idfa">What is an IDFA?</h2>
<p>Each iOS device owner can decide whether they want to be tracked by advertising companies. This allows those companies to supplying that user with content that is tailored towards them (based on their online browsing habits).</p>
<p>Companies can do this with what’s known as an IDFA (Identifier For Advertisers). This is a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#:~:text=A%20universally%20unique%20identifier%20(UUID,%2C%20for%20practical%20purposes%2C%20unique.) string that lets advertisers match the user with their behavior.</p>
<p>Here's an example of a UUID string : 123e4567-e89b-12d3-a456–426614174000.</p>
<h3 id="heading-so-what-are-those-changes-we-talked-about-earlier">So, what are those changes we talked about earlier?</h3>
<p>In short, applications will now be required to show a dialog to the user, asking them if they want to allow the application to track them or not.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Screen-Shot-2020-09-17-at-22.35.25.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Tracking Authorization Dialog</em></p>
<p>Looks pretty ominous, right?</p>
<p>This is in contrast with how things worked before iOS14, where you only had to check if the device had limited advertising tracking enabled or disabled.</p>
<p>The newest version of Apple’s operating system (iOS14) is already available (has been since September 16th). Developers who use the IDFA have to make changes in their applications in order to be compatible for iOS14. </p>
<p>On September 3rd, Apple made an <a target="_blank" href="https://developer.apple.com/news/?id=hx9s63c5%27">update</a> and pushed the deadline to complete these updates to the start of next year:</p>
<blockquote>
<p>“To give developers time to make necessary changes, apps will be required to obtain permission to track users starting early next year”</p>
</blockquote>
<p>Now that we have some time to regain our composure and breathe again, let’s start preparing ourselves for what’s going to be the new normal in 2021. </p>
<p>In this article, we'll present some background about the IDFA and see how we can get its value from iOS14 and onwards.</p>
<h2 id="heading-how-does-the-idfa-get-used-by-advertisers">How does the IDFA Get Used By Advertisers?</h2>
<p>Let’s take a scenario (pre COIVD-19) where you are browsing the web on your iPhone and are looking for a hotel for your next vacation. </p>
<p>Each ad that you see will send a pixel with your IDFA attached to it. An advertiser can see that you are looking at a lot of ads promoting hotels by matching your IDFA and conclude that you are looking to book a hotel room. </p>
<p>From there, it won’t be long until you will be shown a lot of ads for hotel rooms.</p>
<p>This simple yet profound technology came into our lives back in 2012 with iOS6. Since then a lot has changed, and iOS14 is flipping the industry on its head, yet again.</p>
<p><em>✋</em> Note: <em>To use these new APIs you must have upgraded/downloaded XCode 12</em>.</p>
<h2 id="heading-advertising-tracking-and-getting-the-idfa">Advertising Tracking And Getting The IDFA</h2>
<p>Before iOS14, getting the IDFA was pretty simple.</p>
<p>You had to check whether <a target="_blank" href="https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614148-isadvertisingtrackingenabled">Advertising Tracking</a> was enabled or not, by doing this:</p>
<p><code>[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]</code></p>
<p>And if it was disabled, that meant you could acquire the IDFA through the <a target="_blank" href="https://developer.apple.com/documentation/adsupport/asidentifiermanager">ASIdentifierManager</a> class, like so:</p>
<p><code>[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];</code></p>
<p>Simple enough, right?</p>
<p><em>☝️ Beginning</em> with <em>iOS10, if the user disabled advertising tracking, the method above would return a UUID string filled with zeros.</em></p>
<p>One of the changes in iOS14 is the deprecation of the method that checks whether advertiser tracking is enabled or not. So how can applications get the coveted IDFA from iOS14 and onward?</p>
<p>They will have to use a new API that presents a dialog to the user. A few words of wisdom regarding this dialog:</p>
<ul>
<li>It can only be presented to the user <strong>once</strong></li>
<li>The only thing that can be altered in the dialog’s UI are the two lines above the Allow Tracking option (<strong>“Do you want to be tracked?”</strong>)</li>
</ul>
<p>This means that developers will need to think long and hard about how and when they will present the message to the user.</p>
<h2 id="heading-authorization-status">Authorization Status</h2>
<p>With iOS14, a new framework has been created called <a target="_blank" href="https://developer.apple.com/documentation/apptrackingtransparency?language=objc">App Tracking Transparency</a>. This framework contains a class called <a target="_blank" href="https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager?language=objc">ATTrackingManager</a>, which provides an API to:</p>
<ol>
<li>Present a dialog to the user requesting permission to track them</li>
<li>Query the authorization status (regardless of showing or not showing the dialog)</li>
</ol>
<p>We’ll first learn how to get the authorization status. To do so, you need to call the <strong>trackingAuthorizationStatus</strong> method.</p>
<p><code>ATTrackingManagerAuthorizationStatus status = [ATTrackingManager trackingAuthorizationStatus];</code></p>
<p>It will return an NSUInteger with one of the following values:</p>
<ul>
<li>ATTrackingManagerAuthorizationStatusNotDetermined = 0</li>
<li>ATTrackingManagerAuthorizationStatusRestricted = 1</li>
<li>ATTrackingManagerAuthorizationStatusAuthorized = 3</li>
<li>ATTrackingManagerAuthorizationStatusDenied = 2</li>
</ul>
<p>The first three results are pretty self explanatory, so we will focus for a minute on the last one. </p>
<p>You can get an authorization status that is restricted when the screen for enabling/disabling advertising tracking is locked and this option is set to enabled.</p>
<p>Apple has acknowledged this in devices that are identified as belonging to children (for example).</p>
<h2 id="heading-asking-for-permission-to-track">Asking For Permission To Track</h2>
<p>Before looking into the code needed to present the dialog, you must first include the <strong>NSUserTrackingUsageDescription</strong> key inside your info.plist file. </p>
<p>What you add as the value for this key will appear as the two lines mentioned earlier, in the dialog.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/Screen-Shot-2020-09-17-at-22.29.31.png" alt="Image" width="600" height="400" loading="lazy">
<em><strong>NSUserTrackingUsageDescription in the info.plist file</strong></em></p>
<p>To present the dialog, we need to call <a target="_blank" href="https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/3547037-requesttrackingauthorizationwith?language=objc">requestTrackingAuthorizationWithCompletionHandler</a>:</p>
<pre><code>[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
        <span class="hljs-keyword">if</span> (status == ATTrackingManagerAuthorizationStatusDenied) {
            <span class="hljs-comment">//Logic when authorization status is denied</span>
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (status == ATTrackingManagerAuthorizationStatusAuthorized) {
            <span class="hljs-comment">//Logic when authorization status is authorized</span>
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (status == ATTrackingManagerAuthorizationStatusNotDetermined) {
            <span class="hljs-comment">//Logic when authorization status is unknown</span>
        }  <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (status == ATTrackingManagerAuthorizationStatusRestricted) {
            <span class="hljs-comment">//Logic when authorization status is restricted</span>
        }
    }];
</code></pre><p>In the first picture of this article (where you see the dialog) you can see that the lines we wrote in the info.plist file show up as the two lines in the dialog.</p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>In conclusion, it's important to remember that these changes, while daunting, are not happening immediately. </p>
<p>You should also make sure to follow all of the steps detailed in this article so as not to come across crashes/errors in your applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Apple WWDC Scholarship Guide – How to Apply in 2021 ]]>
                </title>
                <description>
                    <![CDATA[ By Mehul Mohan Over the past year, I've received many messages asking how I got into WWDC 2019 as a scholar. And I've finally decided to write this post to answer those questions.  So chances are, if you're wondering how to apply for the scholarship,... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/apple-wwdc-scholarship-guide/</link>
                <guid isPermaLink="false">66d46044f855545810e934a7</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ conference ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 21 Aug 2020 20:30:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/48d68eb2-5262-41fb-bd9c-eebefb492ea6.JPG" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mehul Mohan</p>
<p>Over the past year, I've received many messages asking how I got into WWDC 2019 as a scholar. And I've finally decided to write this post to answer those questions. </p>
<p>So chances are, if you're wondering how to apply for the scholarship, your questions will be answered in this article.</p>
<h2 id="heading-what-is-the-apple-wwdc-scholarship">What is the Apple WWDC Scholarship?</h2>
<p>First things first, WWDC is Apple's World-Wide Developer Conference held every year in June. There, Apple announces recent software (and hardware) updates to some of its products including MacBooks, iPhones, and iMacs. </p>
<p>If you want to attend WWDC these are the associated costs:</p>
<ol>
<li>Event ticket price: $1600</li>
<li>One week stay in San Jose, California: $1000-$1500 (depends)</li>
<li>Travel and other expenses - $400-$500 (again, depends)</li>
<li>Plane ticket: $1500-$2000 (again, depends, but from India, this is a fair price)</li>
</ol>
<p>As a student, you likely can't afford this much. But Apple offers a scholarship to students, where they sponsor your plane ticket, event ticket price, and one week stay. That's about $5000 in savings if you manage to get selected as a WWDC Scholar.</p>
<h2 id="heading-who-am-i">Who am I?</h2>
<p>I'm a web developer who was an Apple WWDC '19 scholar. To sum up, I was probably the only person in the WWDC crowd who knew JavaScript better than Swift. </p>
<p>But if I can get the scholarship, so can you. So now let's discuss the WWDC scholarship in more depth.</p>
<h2 id="heading-wwdc-scholarship-101">WWDC Scholarship 101</h2>
<p>This is a scholarship which Apple offers to people enrolled in STEM programs around the world. If you're enrolled in a college or you're in school, chances are that you can apply for this scholarship.</p>
<p>To apply for the scholarship you have to build a simple project that the Apple review team can use and experience in under 3 minutes. More or less, these are the ONLY requirements of your WWDC app:</p>
<ol>
<li>Size limit (20 MB)</li>
<li>You should be enrolled in STEM organization</li>
<li>You have to use Apple technologies (Xcode, Swift, MacBooks, etc.)</li>
<li>Make it a small app, something that can be used and understood within 3 minutes</li>
</ol>
<p>Now, let's start in on how I did it, and then I'll give you a few pointers to help you out with your application next year.</p>
<h2 id="heading-how-i-cracked-the-wwdc19-scholarship-in-10-days">How I cracked the WWDC19 scholarship in 10 days</h2>
<p>To begin, I <em>literally</em> learned everything about WWDC: the Swift programming language, and the tech around it all in 10 days. No lies. And this helped me get the scholarship (I was one of the few from India that year). </p>
<p>But I don't want to confuse you with some clickbaity thing - it is not possible to crack that scholarship application from <em>a complete beginner</em> state in just 10 days.</p>
<p>I was able to do it because I had a little programming experience before, mostly with Node. The general concepts in programming remain the same, and after a while you're just hopping through syntax and documentation for the most part.</p>
<p>Here is what I submitted for WWDC 2019:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/owGuqiHHJI8" 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>
<p>Trust me, I had no idea either how to build this whole thing. I learned the required Apple APIs and frameworks in 10 days. </p>
<p>So here's how you can approach WWDC '21 in 5 steps:</p>
<h2 id="heading-1-learn-swift-and-apple-frameworks">#1: Learn Swift, and Apple frameworks</h2>
<p>Apple loves to see students using their technology - Swift, SwiftUI, ARKit, , and so on. The more you can use, the better. Don't force or bloat your app, but try to showcase what you know.</p>
<p>If you're creating a simple game, try to introduce some AR version of the game too. If you're creating a project for WWDC which could use some ML, do that. You'll get points for it.</p>
<h2 id="heading-2-pick-difficult-ideas">#2: Pick difficult ideas</h2>
<p>When I started to create my project for WWDC, I had no idea how would I do it. Not gonna lie, my final version wasn't really what I had imagined, but it was pretty close.</p>
<p>The more ambitious the idea you pick, the better are your chances. But balance your ambition with your timeframe – you don't want to have an incomplete app before submissions close.</p>
<p>For me, it was a very close call (I had my submission ready just about an hour before the deadline). Plus I had to work a lot to learn all this new Apple tech as I didn't know anything beforehand. </p>
<p>So make sure you have an estimate of what you need to learn and what you want to build. But like I said, go for shiny and ambitious ideas that stand out.</p>
<h2 id="heading-3-write-your-ideas-down-then-build-them-in-10-days">#3: Write your ideas down, then build them in 10 days</h2>
<p>This is more of personal opinion. But I've seen people who prefer to build something over the course of 2, 3, or 4 months before the scholarship kicks off. Trust me, you'll get a 500% productivity boost when the countdown starts ticking.</p>
<p>I would say keep a list of unique or innovative ideas you have with you. Learn the skillset, but develop projects which you intend to submit in the provided 10 days only. Honestly, it is enough time to pull off something decent which the Apple staff can experience in under 3 minutes (their direct instructions).</p>
<p>I recommended focusing on ideas that really impact the world – education, the health of the planet, making technology more accessible to people, and so on. </p>
<p>These are ideas that the Apple scholarship panel values a lot (at least that's what I've observed in most accepted submissions). And if you are interested in any of these fields, it would be a fun and good match for you.</p>
<h2 id="heading-4-try-going-for-swift-playgrounds-on-ipad">#4: Try going for Swift Playgrounds on iPad</h2>
<p>If possible, I would recommend NOT going with MacBook-based Xcode playground submissions. </p>
<p>I know there have been people who have won with their Xcode playgrounds. But I believe that if you go with a MacBook-based playground, you miss out on a ton of things. </p>
<p>I say this for two main reasons:</p>
<ol>
<li>iPad has a better camera and API support for things like ARKit and a better CPU for ML models/intensive apps</li>
<li>Swift Playground Books (available only on iPad) are beautiful to use and interact with (as a user)</li>
</ol>
<p>For quite some time, Apple has not changed its guidelines for the scholarship much. So it should be safe to assume that Swift playgrounds will be a choice next year too. </p>
<p>They're easy to work with (just like Swift playgrounds on Mac), and are highly engaging. iPads really enable a lot of useful things. So give iPad submission a try for the scholarship if possible.</p>
<h2 id="heading-5-focus-on-your-responses-too">#5: Focus on your responses, too</h2>
<p>The Apple panel also reads your responses to basic questions about what technology you've used and built your project with.</p>
<p>Make sure you mention everything and anything you've used, from the best Apple frameworks to external assets if you have used any. </p>
<p>Proofread your paragraphs – the only thing worse than a little bug in your code could be a little bug in your paragraph. </p>
<p>Apart from this, stay focused for 10 days, (I remember I pulled all-nighters for almost all 10 days), and most importantly do it for fun. There are a lot of ways to go one step forward in life, and this is just one of them. </p>
<p>Don't stress out too much over what the result might be. Because if you're attempting this, you're probably in your early 20s which means you have a full life in front of you. You'll have plenty of time to do more amazing things, irrespective of the result. So just go get it!</p>
<h2 id="heading-my-experience-with-wwdc">My Experience with WWDC</h2>
<p>In short: mind-blowingly amazingly super cool!</p>
<p>Although I wanted to keep this article focused on helping you out, I also wrote this section to motivate you to work hard for this scholarship. It unlocks a TON of networking opportunities, and you meet and make a bunch of cool friends (MKBHD included haha). Plus you'll have a lot of fun.</p>
<p>I shared some of my moments in the full vlog last year, <a target="_blank" href="https://www.youtube.com/watch?v=Ad2gZAVh_Io">see if you like what I did there</a>.</p>
<p>If you still have questions, or this article helped you out, feel free to reach out to me on <a target="_blank" href="https://twitter.com/mehulmpt">Twitter</a> or <a target="_blank" href="https://instagram.com/mehulmpt">Instagram</a> and tell me :) I'm also working on <a target="_blank" href="https://codedamn.com">codedamn</a>, a platform for developers to learn and connect, feel free to give it a visit too.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to View Your Apple iCloud Photos Online in Your Laptop or Desktop's Web Browser ]]>
                </title>
                <description>
                    <![CDATA[ Picture this: you just returned from a beautiful vacation and want to show all those gorgeous photos to your family. But your phone just died. And since you're at a family dinner your laptop is nowhere to be found. What do you do? iCloud Photos to th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-view-your-apple-icloud-photos-online-in-your-laptop-or-desktops-web-browser/</link>
                <guid isPermaLink="false">66b1fa5009c44225ad2c3909</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ icloud ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abigail Rennemeyer ]]>
                </dc:creator>
                <pubDate>Thu, 07 Nov 2019 19:23:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/06/5f9c9f84740569d1a4ca4307.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Picture this: you just returned from a beautiful vacation and want to show all those gorgeous photos to your family. But your phone just died. And since you're at a family dinner your laptop is nowhere to be found.</p>
<p>What do you do?</p>
<p>iCloud Photos to the rescue!</p>
<p>If you need to get into your photos but don't have any of your trusty devices on hand, this guide will show you how.</p>
<h2 id="heading-getting-started">Getting started</h2>
<p>You're probably familiar with the photos app on your iPhone. I know I visit it multiple times a day when I'm taking or looking for a photo of my adorable boxer.</p>
<p>But what if you're in that unfortunate situation mentioned above and don't have access to your phone (or tablet or laptop)? There's a simple answer: iCloud Photos. And you can access those photos from any computer or device, as long as you have an internet connection and your Apple login info.</p>
<p>So let's go find your photos.</p>
<h3 id="heading-go-to-icloudcom-and-sign-in">Go to iCloud.com and sign in</h3>
<p>Open any web browser and go to <a target="_blank" href="https://www.icloud.com/">icloud.com</a>. If you're not signed in you'll be prompted to do so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-sign-in-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-locate-the-photos-app">Locate the photos app</h3>
<p>Once you're signed in you'll be brought to a screen full of apps. And somewhere in there you'll see the photos app icon:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-photos-app-1-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Look for the colorful photo app</em></p>
<p>The first time you access your photos this way they might take a while to load. Especially if you have over 19,000 of them like I do. Just sit tight while iCloud prepares them (and feel free to go do something else while you wait).</p>
<h3 id="heading-browse-share-and-have-fun">Browse, share, and have fun!</h3>
<p>Once they're all loaded, it'll look a little something like this (with your own photos, of course):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-photos.png" alt="Image" width="600" height="400" loading="lazy">
<em>Voilà! Your photos are there for the taking.</em></p>
<p>Now you can show your eager family that 45 minute slide show you prepared on the plane ride home...which probably killed your phone battery.</p>
<h2 id="heading-getting-to-know-icloud-photos">Getting to know iCloud Photos</h2>
<p>But what else can you do now that you have access to your photos again? You can organize them, create favorites, delete unflattering or duplicate captures, and more. Let's have a look.</p>
<h3 id="heading-managing-favorites">Managing favorites</h3>
<p>Ah, that last evening at the beach/mountain/your favorite bar. Remember that super sweet photo you are just dying to show everyone to make them jealous? You can make it a favorite so you never have to search through all your photos for it again.</p>
<p>Just select that photo by double-clicking it so it opens. A little menu of icons will become selectable in the upper right:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-photo-favorite.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click the heart. Now that photo is in your favorites.</p>
<p>If you want to further manage your favorite photos just click on the "Favorites" tab in the left sidebar menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-favorites-options-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Under favorites, you can do all sorts of fun things</em></p>
<p>When you click once on any of those photos (as you can see, the last photo is highlighted blue), that upper right menu will become available again.</p>
<p>Those menu icons allow you to upload photos, add your selected photo to an album, share that photo, download it, or delete it.</p>
<p>Tip: just be careful when deleting items. You're not just deleting that photo from your favorites - you're deleting it from all your devices.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-delete-photo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Delete carefully!</em></p>
<p>Just in case you mistakenly delete a photo, however, you can recover it. Just visit the "Recently Deleted" tab in the left sidebar menu. There, you'll see your just-deleted photo and how many days it has left before it disappears. Forever.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-recently-deleted.png" alt="Image" width="600" height="400" loading="lazy">
<em>So you're tellin' me there's a chance...</em></p>
<h3 id="heading-creating-a-new-album">Creating a new album</h3>
<p>What if you want to share specific photos with your family but keep certain others private?</p>
<p>You can do that, too! Just look for the "My Albums" tab in the left sidebar menu:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-my-albums.png" alt="Image" width="600" height="400" loading="lazy">
<em>Just click once on "My Albums" and your albums (if you have any) shall appear.</em></p>
<p>If you want to create a new album, just click the "+" in the upper right corner:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-create-album-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You'll be asked to give the album a name, and once you do, you can add photos by clicking the upload photos icon in the upper right:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-upload-photos-to-new-album.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload away!</em></p>
<p>You can also add photos to your new album while you're browsing your pics. Just select a photo (or drag to select multiple photos) and click on the "+" in the upper right corner.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-add-photos-to-album-3-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add one or many photos to the album of your choice.</em></p>
<p>Then just select the album where you want the photos to go, and presto! Your album is populated with adorable dog photos (or whatever photos you've selected. Are there any other kinds of photos?).</p>
<h3 id="heading-managing-your-albums">Managing your albums</h3>
<p>Within your albums you can manage your photos the same ways as you can in your favorites. Just double-click on an album, select (click on) a photo, and edit away.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-album.png" alt="Image" width="600" height="400" loading="lazy">
<em>So many options, so little time...</em></p>
<p>And now all you need to do is put together that next stunning slideshow.</p>
<h2 id="heading-what-if-i-dont-see-any-photos">What if I don't see any photos?</h2>
<p>If you login to iCloud and don't see any photos, it could be that you haven't opted for your photos to be saved to iCloud.</p>
<p>To fix that, just go to Settings in your phone, select Photos, and toggle iCloud Photos on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/icloud-toggle-photos-on.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This will automatically upload and store your photos in iCloud so they're there when you need them.</p>
<p>Tip: if you can't toggle on that switch, it could be that your phone/device doesn't have enough space to store them. If that's the case you'll just need to <a target="_blank" href="https://support.apple.com/en-us/HT201318">upgrade your iCloud storage plan</a>.</p>
<p>Now you'll never be without your photos again.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Your App for iOS 13 Dark Mode ]]>
                </title>
                <description>
                    <![CDATA[ By Shifa Martin Apple launched the much-awaited iOS 13 updates globally on September 19 across all iPhones launched within the past 4 years (back to the iPhone 6s).  One of the biggest features of this update was the system-wide iOS 13 dark mode. It... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-an-app-for-dark-mode-on-ios-13-untitled/</link>
                <guid isPermaLink="false">66d460f88812486a37369d5a</guid>
                
                    <category>
                        <![CDATA[ app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ios app development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 27 Sep 2019 13:05:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/09/app-developer.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shifa Martin</p>
<p>Apple launched the much-awaited iOS 13 updates globally on September 19 across all iPhones launched within the past 4 years (back to the iPhone 6s). </p>
<blockquote>
<p>One of the biggest features of this update was the system-wide iOS 13 dark mode. It's expected to help with eye-strain caused by white light emitted by smartphone displays.</p>
</blockquote>
<p>While this feature is a joy to end-consumers using Apple devices, it's a task for iOS developers to prepare an app ready for iOS 13 dark mode.</p>
<h2 id="heading-how-to-set-up-your-app-for-ios-13-dark-mode">How to Set up your App for iOS 13 Dark Mode?</h2>
<p>To help developers with this issue, here is useful info and steps showing how they can prep up an existing iOS app for <a target="_blank" href="https://www.apple.com/ae/ios/ios-13/">iOS 13</a> dark mode.</p>
<ul>
<li>It’s not too hard to implement iOS 13 dark mode despite its system-wide scale.</li>
<li>Enabling iOS 13 dark mode on your existing app is also simple mostly thanks to the latest iOS 13 SDK. </li>
</ul>
<p>When using the latest version to build apps for iOS 13 dark mode, the OS will automatically update switches, buttons, and table views among other system controls. Though do note that images and text colors won’t adjust for dark mode automatically.</p>
<p>However, it’s still amazing to see that a system-wide change such as dark mode is so easy to implement. There are smaller code changes and more work that you'll be able to get done with the iOS 13 dark mode in that saved time.</p>
<h2 id="heading-how-to-adapt-colors-for-ios-13-dark-mode">How to Adapt Colors For iOS 13 Dark Mode</h2>
<p>First, let’s start with changing system colors iOS 13 dark mode:</p>
<p>Now there are new system colors added in UIColor, one of which is a label color. Using these new colors helps support dark mode and other high contrast modes in iOS 13.</p>
<pre><code class="lang-js">label.color = UIColor.secondaryLabel
</code></pre>
<p>Generally, you should use system colors for iOS 13 dark mode, which automatically adapts to changes in the interface for maintaining consistency across apps. However, developers can also choose to implement dark mode with custom colors. </p>
<blockquote>
<p>The asset catalog colors introduced with iOS 11 make it much easier to support dark mode by adding dark versions of a custom set of colors. </p>
</blockquote>
<p>You only have to select a preferred color from the catalog, then change Appearances to Any, Dark from the Attributes Inspector. </p>
<p>That's it! Now you have a custom iOS 13 dark mode ready for your mobile app.</p>
<h2 id="heading-troubleshooting-ios-13-dark-mode">Troubleshooting iOS 13 Dark Mode</h2>
<p>Let's say your app is not following iOS 13 dark mode. What will you do? Here are some easy steps to solve this issue.</p>
<h3 id="heading-step-1">Step 1</h3>
<p>You will need to know if the app is updated or not. </p>
<p>If the app is not working with iOS 13 Dark Mode or does not support it, simply update the app via Apple Store.</p>
<h3 id="heading-step-2">Step 2</h3>
<p>Check whether the Dark Mode of your iOS app has been enabled or not. </p>
<p>If not, go to Settings - Display &amp; Brightness - check whether "Dark" is enabled or not.</p>
<h3 id="heading-step-3">Step 3</h3>
<p>If your app is fully updated, but isn't working with iOS 13 Dark Mode, then check the in-app settings. <em>See the image:</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/app-not-following-ios-13s-dark-mode-check-these-settings.w1456-3.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you want more help on setting up your iOS 13 Dark Mode, get it from the <a target="_blank" href="https://www.valuecoders.com/dedicated-development-teams">dedicated development teams</a>. And, that is how I'm going to help you. </p>
<p>Also read tips for <a target="_blank" href="https://www.valuecoders.com/blog/technology-and-apps/11-tips-successful-mobile-app-development-businesses-android-ios/">mobile app development on iOS</a>. Hope all this information will be helpful for you. </p>
<p><em>Let's see what you have to do next.</em></p>
<h2 id="heading-adapt-images-for-ios-13-dark-mode">Adapt Images For iOS 13 Dark Mode</h2>
<p>Most images look great in iOS 13 dark mode, and at times they pop out in a way that really highlights details. However, you may still end up finding some images which look a bit off or unsuitable for dark mode. </p>
<blockquote>
<p>The good news is that you can adjust images for dark mode in the same way text is adjusted. </p>
</blockquote>
<p>All you need to do is select the image in the catalog and as done previously, and change attributes to Any, Dark in the Attributes Inspector. Now add the dark appearance of the image and we’re done.</p>
<h2 id="heading-programmatically-detecting-changes-in-ios-13-dark-mode">Programmatically Detecting Changes in iOS 13 Dark Mode</h2>
<p>Developers could face situations where they need to implement appearance changes in iOS 13 dark mode programmatically. This is how it's done:</p>
<pre><code class="lang-js">override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) 
{
    <span class="hljs-built_in">super</span>.traitCollectionDidChange(previousTraitCollection)

    <span class="hljs-keyword">let</span> userInterfaceStyle = traitCollection.userInterfaceStyle <span class="hljs-comment">// Either .unspecified, .light, or .dark</span>
    <span class="hljs-comment">// Update your user interface based on the appearance</span>
}
</code></pre>
<blockquote>
<p>Overriding traitCollectionDidChange helps in detecting appearance changes.</p>
<p>Then we only have to open traitCollection.userInterfaceStyle.</p>
</blockquote>
<p><strong>You can also verify if the existing appearance is using a new method you just implemented:</strong></p>
<pre><code class="lang-js">override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    <span class="hljs-built_in">super</span>.traitCollectionDidChange(previousTraitCollection)

    <span class="hljs-keyword">let</span> hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection) <span class="hljs-comment">// Bool</span>
    <span class="hljs-comment">// Update your user interface based on the appearance</span>
}
</code></pre>
<h2 id="heading-overriding-the-user-interface-style">Overriding the User Interface Style</h2>
<h3 id="heading-complete-app">Complete App</h3>
<p>The system automatically opts-in any app linked against the iOS 13.0 or later SDK to both light and dark appearances. </p>
<p>If you need extra time to work on your app’s Dark Mode support or want to keep your app in a single style, you can opt-out by including the UIUserInterfaceStyle key (with a value of Light or Dark) in your app’s Info.plist file. </p>
<p>Setting this key causes the system to ignore the user’s preference and always apply the specific appearance to your app.</p>
<blockquote>
<p><strong>Note:</strong> Supporting iOS 13 Dark Mode is strongly encouraged. Use the UI UserInterfaceStyle key to opt-out only temporarily while you work on improvements to your app’s Dark Mode support.</p>
</blockquote>
<h3 id="heading-specific-screens">Specific Screens</h3>
<p>In iOS 13, you can now override the user interface style on specific views or view controllers. For example, you may want only a certain view controller to be in iOS 13 dark mode, while the rest of your app is in light mode.</p>
<p>To override the user interface style, just override this variable in the top view or view controller and it will propagate down to sub-views:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Inside a UIViewController</span>
override func viewDidLoad() 
{
    <span class="hljs-built_in">super</span>.viewDidLoad()

    <span class="hljs-comment">// Always adopt a dark interface style.    </span>
    overrideUserInterfaceStyle = .dark
}
</code></pre>
<h3 id="heading-closing-notes">Closing Notes</h3>
<p>Thanks for reading the article! Here we've explored how to set up an app for iOS 13 dark mode. </p>
<p>iOS 13 dark mode brings with it a unique stress-free way to use a smartphone. Perhaps we’ll see a future where dark mode replaces the default mode with the whiter backgrounds. </p>
<p>By following these coding guidelines and tips you can easily set up your app for dark mode on iOS 13. </p>
<p><strong>If you need some expert help, feel free to g<a target="_blank" href="https://www.valuecoders.com/contact">et in touch</a> with <a target="_blank" href="https://www.valuecoders.com/hire-developers/hire-ios-developers">iOS developers</a> for iOS 13 dark mode related queries.</strong>   </p>
<p><strong>F</strong>ollow on Twitter for<strong> more </strong>updates:<strong> </strong><a target="_blank" href="https://twitter.com/ValueCoders">https://twitter.com/ValueCoders</a><em>**</em>  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to successfully submit an app to the App Store for review ]]>
                </title>
                <description>
                    <![CDATA[ By Irina Bulygina The Apple team has a strict vision concerning the quality of mobile applications. This is really great for the users, because the Apple team works hard to make the App Store a trustworthy ecosystem. The App Store has a high threshol... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-successfully-submit-an-app-to-the-app-store-for-review-ad7ccdd87722/</link>
                <guid isPermaLink="false">66c354fddae03919d93dc01c</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 19 Feb 2019 21:53:59 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*zfrYdaUXd2-v6f1KaepbnA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Irina Bulygina</p>
<p>The Apple team has a strict vision concerning the quality of mobile applications. This is really great for the users, because the Apple team works hard to make the App Store a trustworthy ecosystem. The App Store has a high threshold and tough requirements, not only for the app’s performance but for the implementation of appropriate security measures. The user can be sure that iOS applications are reliable.</p>
<p>However, meeting all the requirements can become a real hell for developers. Just to compare, the development of the application can take only a few weeks, while the time spent passing the App Store review can be up to a month (or even months if the developer disregards <a target="_blank" href="https://developer.apple.com/app-store/review/guidelines">Apple’s developer guidelines</a>).</p>
<p>I'm working at <a target="_blank" href="http://www.dashdevs.com">Dashdevs</a> as a Client Engager. My main duty is to create applications from scratch so they pass the review. I work with clients’ requirements. We have more than 9 years of expertise in the development of iOS applications. We’ve worked with various markets, industries, and different companies.</p>
<p>The complexity of the applications varies, too. We submitted 250+ apps for review during 2018. Not all of them passed the review the first time. But sometimes we felt real unbridled joy from a good review.</p>
<p>In this article, I want to share our experience so you can avoid common mistakes and easily pass the review stage.</p>
<h3 id="heading-how-to-apply-to-the-app-store"><strong>How to apply to the App Store</strong></h3>
<p>A shiny brand-new iOS application has been developed, tested, and is ready to see the world. A binary file is already uploaded to the iTunes Connect panel. But what else is needed?</p>
<ul>
<li>You need to add basic information (description, tags, contacts) about your application, add screenshots, and credentials of a demo user account (if your application requires the authorization).</li>
<li>You need to include detailed explanations of non-obvious features (like native gesture usage) and in-app purchases in the App Review notes.</li>
<li>Then you need to press the button “Submit for Review” to inform Apple that your application is ready for the App Store.</li>
</ul>
<p>You’ll be notified if something important in the description is missing. Then the application status review will be changed to “Waiting for review”. It can take a few days before the real check begins. When the verification team actually starts the review, the status of the application will be changed to “In Review”.</p>
<p><strong><em>Hint:</em></strong> <em>You will save some effort by installing the iTunes Connect application on your iPhone to receive immediate notifications about all the status changes.</em></p>
<p>App Store review is a mandatory step for all applications. The process of app verification sticks to the Apple Guidelines ensuring the best and the safest user experience.</p>
<p>They also review the primary information about the application. A part of the verification is done automatically using scripts, and people perform the other one. If your application has an issue, you will receive a notification with a precise description of what should be fixed. The timeframe for the first stage of review runs between 3 to 7 days. The inspection of the application updates is quicker — from 1 to 3 days.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9WES-31NeFCei5gylQdCdN0Jno1fRnw1HoVp" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Over the last few years, I’ve had some problems with applications submitted for review. Some of them were easy to fix, and some took many hours.</p>
<h3 id="heading-so-why-didnt-your-applications-pass-on-the-first-try">So, why didn’t your applications pass on the first try?</h3>
<p>Here’s what you need to take into account.</p>
<h4 id="heading-use-human-interface-guidelines-hig-for-the-design"><strong>Use Human Interface Guidelines (HIG) for the design</strong></h4>
<p>Your designers should follow the <a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines">HIG</a> from the very beginning. Sizes and positions of the buttons, the correct usage of the basic UI elements, and navigation must comply with Apple Guidelines. Fixing issues with HIG can cost you a lot if you find these issues at the end of the development.</p>
<p><strong><em>Hint:</em></strong> <em>Do not create an application that appears confusingly similar to an existing Apple product or any other application (no copycats). The Apple team is very strict about this.</em></p>
<h4 id="heading-check-the-functionality-list"><strong>Check the functionality list</strong></h4>
<p>Your application must include features, content, and a UI that elevate it beyond a repackaged website. The Apple team cares about the usefulness and benefits to the user.</p>
<p>There was a case when one of our applications was rejected because the Apple review team assumed that our app didn’t need to have the Sign up/Sign in functionality. So, we sent a notice of appeal with the evidence of the relevancy of this functionality.</p>
<p>Another case was a little bit different — the application was too simple for the AppStore (just a funny calendar). The application needed additional functionality. We improved it by adding a sharing feature, and it passed the review.</p>
<p>One more significant rule to refer to is that your application must not require the installation of other applications.</p>
<h4 id="heading-provide-a-demo-account-with-full-functionality-to-the-apple-team"><strong>Provide a demo account with full functionality to the Apple team</strong></h4>
<p>The App Store reviewing team will definitely try to register your app, but they will need to verify the rest of the features as well. For example, to review the functionalities of a bank application, they need to have an account with an activated card and some transactions on it. You need to be sure that the account accesses full functionality and all the back-end features are turned on.</p>
<p><strong><em>Hint:</em></strong> <em>do not provide this account to your QA team for usual testing, especially during the review period. Once, we sent an application for review, and at the same time our Quality Assurance engineer was testing the blocking functionality and occasionally banned a new user.</em></p>
<h4 id="heading-no-test-coming-soon-beta-trial-testflight-in-the-app"><strong>No “test”, “coming soon”, “beta”, “trial”, “Testflight” in the app.</strong></h4>
<p>All your future, unfinished, demo functionality must not be used in the app. Do not use these words for your application content at all, even for in-app screenshots and descriptions. If you need to test your application, you can join <a target="_blank" href="https://developer.apple.com/testflight/">Testflight services</a>.</p>
<p>We once made a ridiculous mistake with another one of our applications. As you might know, to prepare a submission to review, developers sometimes take screenshots of the application right from the TestFlight. These pictures are posted as the screenshots of the real app for the App Store. If you do so, check twice, as there can be the “Testflight” label in the status bar. When this happens, your application is rejected. This itty-bitty thing may block the submission of your application.</p>
<h4 id="heading-performance"><strong>Performance</strong></h4>
<p>No crashes, no slow performance, no memory leaks are allowed for App Store applications. Incomplete app bundles and binaries that crash or perform with obvious technical problems in applications are rejected at once.</p>
<h4 id="heading-describe-only-the-existing-functionality"><strong>Describe only the existing functionality</strong></h4>
<p>No advertisement for future features should be in the description of the app.</p>
<h4 id="heading-terms-and-conditions-privacy-policies"><strong>Terms and Conditions / Privacy Policies</strong>.</h4>
<p>These documents or the links to them must be added to the app. You need to explain to the user how their sensitive data is processed and what data is shared by the app with third parties and for what purposes (e.g., analytics tools, advertising networks, and third-party SDKs, etc.). A user needs to know the deletion and retention policies of your application.</p>
<h4 id="heading-intellectual-property"><strong>Intellectual Property</strong></h4>
<p>You need to have permissions to use all materials in the app (copyright issue). Do not use third-party trademarks, copyrighted works, or patented ideas in your app if you have not obtained the necessary license. Remember about the restrictions against using sexual or pornographic content, marijuana, tobacco, controlled substances, misleading quotations of religious texts, and violence in mobile applications.</p>
<h4 id="heading-licenses"><strong>Licenses</strong></h4>
<p>If some regulations within your business area demand a license for providing your services, such as FinTech, Medicine, Healthcare, etc., you need to attach a copy of those documents to the application review. If an app requires specific hardware, you need to provide a corresponding certificate or license for this hardware.</p>
<p>Another case from our experience: an application used a special sticker printer. At first, the application was rejected, and we needed to get a certificate to use those printers. It took us a month to get the official approval from the producer of the hardware.</p>
<p>Another example was a digital bank application. We needed to provide the App Store review team with the E-money License. This also applies to the cryptocurrency-industry.</p>
<blockquote>
<p>“<em>Apps facilitating Initial Coin Offerings (“ICOs”), cryptocurrency futures trading, and other crypto-securities or quasi-securities trading must come from established banks, securities firms, futures commission merchants (“FCM”), or other approved financial institutions and must comply with all applicable law”.</em></p>
</blockquote>
<h4 id="heading-ask-user-for-permissions"><strong>Ask user for permissions</strong></h4>
<p>Your application must ask permissions for using a camera, microphone, location, access to contacts, Camera Roll, and user locations. The permissions must be relevant to the application’s functionality. The App Store team cares that the information collected in the application is stored in the right way and prevents its unauthorized use, disclosure, or access by third parties.</p>
<p><strong><em>Hint:</em></strong> <em>don’t forget to add a description of these permissions to the .plist file. This is another common reason for rejections.</em></p>
<h4 id="heading-no-mock-up-data-in-the-app"><strong>No mock-up data in the app</strong></h4>
<p>If your application has no content for some forms you need, hide this element or add a placeholder for it with an explanation how the user can get the necessary data.</p>
<p>Sometimes developers hardcode to show the maximum user functionality. For example, your application has a section with charts displaying the user’s activity statistics in the app. In this case, there must be a placeholder with a prompt text that the chart will be available when the user starts to use the app on an everyday basis.</p>
<p>With advertisements, things are the same — you can not submit the app with empty ad banners or test adverts.</p>
<h4 id="heading-ability-to-moderate-users-content"><strong>Ability to moderate user’s content</strong></h4>
<p>“Block a user/content”, “report a user/content”, “blacklist for users” are required functionalities for the app if it provides multi-user communication (e.g. feeds, chats, groups). As a product owner, you need to be conscious that different people will use your application and some of them may disturb others. You need to provide your users with the ability to manage the content and the community they’re interacting with.</p>
<h3 id="heading-options-for-release">Options for release</h3>
<p>With every submission for review, my team gains new experience. My main advice is to submit your application to the App Store review as soon as you have developed the MVP of your application. Keep in mind that even if you pass the review, it does not mean that the app will be released.</p>
<p>There are three different actions you can take after a successful review:</p>
<ul>
<li><strong>Manually release this version:</strong> as a developer or an application manager, you need to go to the iTunes Connect panel and press the button to release the app.</li>
<li><strong>Automatically release this version:</strong> that means that the application will be published as soon as it passes the review.</li>
<li><strong>Automatically release this version after App Review, no earlier than…:</strong> you can select the time/date for the release. If your application passes the review, it will be published at that time.</li>
</ul>
<p>These options can help developers and product owners/managers to pass the review and wait for the marketing campaign to start. You need to know that the first app review is the most critical, and so the App Store team verifies the application for a much longer period and more thoroughly. Every further update is reviewed as well, but it takes less time for the verification. Sometimes can take just a few hours.</p>
<p>The App Store may reject your application. That’s OK. Do not panic. If you understand the reason, you just fix the issue and resubmit the application for review again. If you have questions or would like to provide additional information, you can use the Resolution Center to communicate with the App Review team. They are supportive and ready to help you with your application. We have fixed a lot of issues with their help.</p>
<p>I hope my examples mentioned in this article will be helpful for you and all your IOS applications will pass App Store verification on the very first attempt.</p>
<p>P.S. Useful links:</p>
<ul>
<li><a target="_blank" href="https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007072">App Programming Guide</a></li>
<li><a target="_blank" href="https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/">App Extension Programming Guide</a></li>
<li><a target="_blank" href="https://developer.apple.com/icloud/documentation/data-storage/index.html">iOS Data Storage Guidelines</a></li>
<li><a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines/">Human Interface Guidelines</a></li>
<li><a target="_blank" href="https://developer.apple.com/app-store/marketing/guidelines/">Marketing Resources and Identity Guidelines</a></li>
<li><a target="_blank" href="http://www.apple.com/legal/intellectual-property/guidelinesfor3rdparties.html">Guidelines for Using Apple Trademarks and Copyrights</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to set up PHP, CaddyServer, and Kirby on MacOS — and why you should do it ]]>
                </title>
                <description>
                    <![CDATA[ By Philipp Haidenbauer Recently Kirby Version 3.0 was released. As I have worked with Version 2 for quite some time in the past, I figured why not give it a try? Just before Christmas, I bought a brand new MacBook Air, so it was obvious that I would ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/php-caddyserver-und-kirby-on-macos-96811af35394/</link>
                <guid isPermaLink="false">66c35c93e335b31297533f79</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 03 Feb 2019 07:32:22 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*A-xWmyVxuvS0GqWQ" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Philipp Haidenbauer</p>
<p>Recently <a target="_blank" href="https://getkirby.com/">Kirby Version</a> 3.0 was released. As I have worked with Version 2 for quite some time in the past, I figured why not give it a try?</p>
<p>Just before Christmas, I bought a brand new MacBook Air, so it was obvious that I would like to try Kirby right away on it. I stumbled upon a great <a target="_blank" href="https://simonecarletti.com/blog/2016/05/caddy-server-php-macosx/">article</a> on how to set up <a target="_blank" href="https://caddyserver.com/">CaddyServer</a> and PHP on MacOS. But I changed some of it.</p>
<h3 id="heading-caddyserver-php-and-kirby">CaddyServer, PHP and Kirby</h3>
<p>Let’s get started with a brief overview of what software I’m talking about.</p>
<h4 id="heading-phphttpwwwphpnet"><a target="_blank" href="http://www.php.net/">PHP</a></h4>
<p>I don’t think I have much to say about PHP. It’s probably one of the oldest Scripting Languages out there in the WebWorld. PHP was “the” language for making your website “dynamic”. And it was also the first language I discovered and learned to play around with.</p>
<h4 id="heading-caddyserverhttpscaddyservercom"><a target="_blank" href="https://caddyserver.com/">CaddyServer</a></h4>
<p>Is a small but very powerful Web-Server which I discovered a few months ago. It has some really nice features like automatic SSL / HTTPs and a really easy configuration file (which you will see later). And it’s blazing fast. :)</p>
<h4 id="heading-kirbyhttpsgetkirbycom"><a target="_blank" href="https://getkirby.com/">Kirby</a></h4>
<p>Another great tool I discovered a few years ago. Basically, it’s a CMS (Content Management System) based on a simple FileStructure. Even if you don’t know much about PHP, it’s relatively simple to get into creating templates for pages and extending the whole functionality.</p>
<h4 id="heading-why">Why?</h4>
<p>Now that you know about all three projects, you might be asking why you should use them together. Well, there are multiple reasons for it:</p>
<ul>
<li>MacOS comes with a default <a target="_blank" href="https://httpd.apache.org/">apache2</a> installation, but as you might know, Apache is one of the biggest HTTP servers out there. It’s widely adopted, but it has one downside. It eats memory and CPU like no other web-server out there. So if you’re on the go, it also eats battery like crazy and I don’t like that.</li>
<li>Caddy is very lightweight and doesn’t really use much Memory / CPU / Battery.</li>
<li>Kirby, as I’ve said is easy to customize and extend. As it’s a CMS, you don’t need to worry about a database or application-specific logic from the beginning. That way you can prototype pretty fast, which leads to faster results and more satisfaction as you get things done. :)</li>
</ul>
<p>Without further ado, let’s get into setting it up:</p>
<h3 id="heading-first-of-all">First of all</h3>
<p>It’s essential to have <a target="_blank" href="https://brew.sh/index_de">homebrew</a> installed, as package management get’s a whole lot easier with it.</p>
<p>You can install it with a simple command:</p>
<pre><code>/usr/bin/ruby -e <span class="hljs-string">"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</span>
</code></pre><h3 id="heading-php">PHP</h3>
<p>Now that we have a package manager, it’s time to install the correct PHP-version. Kirby needs at least PHP7.1 so I installed 7.2 :)</p>
<pre><code>brew install php@<span class="hljs-number">7.2</span>
</code></pre><p>There are also some extensions which are needed:</p>
<pre><code>brew install freetype jpeg libpng gd
</code></pre><h3 id="heading-caddyserver">CaddyServer</h3>
<p>Now that we have PHP and some dependencies installed we can now install CaddyServer.</p>
<p>Simply download the suitable Version from <a target="_blank" href="https://caddyserver.com/download">https://caddyserver.com/download</a>.</p>
<p>You will receive a zip file. Extract it and copy the executable to a path inside your $PATH (in my case <code>/Users/phaidenbauer/bin/</code>):</p>
<pre><code>unzip caddy_v0<span class="hljs-number">.11</span><span class="hljs-number">.2</span>_darwin_amd64_personal.zipcp caddy /Users/phaidenbauer/bin/caddy
</code></pre><h3 id="heading-kirby">Kirby</h3>
<p>Next one is Kirby. Again download the zip from <a target="_blank" href="https://getkirby.com/try">https://getkirby.com/try</a>.<br>Extract it somewhere you have your projects. In my case that’s <code>/Users/phaidenbauer/development/</code>.</p>
<p>The next essential thing to get this whole thing running is the Caddyfile which tells Caddy what to do :)</p>
<pre><code>localhost:<span class="hljs-number">8080</span>tls offroot ./gzip
</code></pre><pre><code>rewrite {    r .*    to {path} {path}/ /index.php?{path}&amp;{query}}
</code></pre><pre><code>fastcgi / <span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>:<span class="hljs-number">9000</span> phpon startup launchctl load -w /Users/phaidenbauer/Library/LaunchAgents/homebrew.mxcl.php@<span class="hljs-number">7.2</span>.pliston shutdown launchctl unload -w /Users/phaidenbauer/Library/LaunchAgents/homebrew.mxcl.php@<span class="hljs-number">7.2</span>.plist
</code></pre><p>Let’s go through it:</p>
<p><code>localhost:8080</code> tells it on which Port it should listen. If you don't want to run it as root (or via <code>set_cap</code>) you should use something above 1024.</p>
<p><code>tls off</code> disables the built-in SSL / HTTPS feature, as we are only working locally.</p>
<p><code>root ./</code> sets the root-path of the serving directory.</p>
<p><code>gzip</code> enables the gzip-compression for responses.</p>
<p><code>rewrite { r .* to {path} {path}/ /index.php?{path}&amp;{query} }</code> rewrites all incoming URLs to suite Kirby’s needs. (It’s probably not the best solution but it works fine for my development environment.)</p>
<p><code>fastcgi / 127.0.0.1:9000 php</code> tells caddy to forward requests to a FastCGI-server. Which is, in our, case PHP.</p>
<p>Now we have two special functions.</p>
<pre><code>on startup launchctl load -w /Users/phaidenbauer/Library/LaunchAgents/homebrew.mxcl.php@<span class="hljs-number">7.2</span>.pliston shutdown launchctl unload -w /Users/phaidenbauer/Library/LaunchAgents/homebrew.mxcl.php@<span class="hljs-number">7.2</span>.plist
</code></pre><p>As I mentioned earlier it is just a MacBook Air, so I don’t want to have PHP running all the time. Especially when I don’t need it. The great thing is caddy can run commands on events. In this case, we use the startup and shutdown event to start and stop PHP. Great! No more waste of RAM and CPU while checking emails.</p>
<h3 id="heading-start-the-whole-thing">Start the whole thing :)</h3>
<p>Now we are pretty much set. The last thing to do is start them all together and start working:</p>
<pre><code>cd /Users/phaidenbauer/development/fly.phaidenbauer.comcaddy
</code></pre><p>You should see something like this:</p>
<pre><code>Activating privacy features... done.http:<span class="hljs-comment">//localhost:8080WARNING: File descriptor limit 4864 is too low for production servers. At least 8192 is recommended. Fix with `ulimit -n 8192`.</span>
</code></pre><p>And that's it. Take your favorite browser and surf to <a target="_blank" href="http://localhost:8080">http://localhost:8080</a>. Depending on if you downloaded the Kirby-Plainkit or Kirby-Starter kit you should see a simple “Hello” or a simple gallery.</p>
<p>And that’s it. Happy hacking :)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Swift vs. Objective-C: The trending up-and-comer vs. the dinosaur ]]>
                </title>
                <description>
                    <![CDATA[ By Colin Smith A short history of Swift I remember how pivotal it was when Swift was introduced at Apple’s 2014 WWDC (Worldwide Developers Conference). It was the talk of the town and all the devs I worked with couldn’t wait to try it out. The iOS co... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/https-medium-com-colin-gabriel-smith-swift-vs-objective-c-5b19add8e2ed/</link>
                <guid isPermaLink="false">66c357081efc805979ae9f78</guid>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Objective C ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 22 Jan 2019 22:10:07 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*2WOnhJVoWvnNt6HitAQVNg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Colin Smith</p>
<h3 id="heading-a-short-history-of-swift">A short history of Swift</h3>
<p>I remember how pivotal it was when Swift was introduced at Apple’s 2014 WWDC (Worldwide Developers Conference). It was the talk of the town and all the devs I worked with couldn’t wait to try it out. The iOS community was buzzing and there was a lot of excitement around the new language.</p>
<p>It was developed in order to carry on some concepts we saw in Objective-C such as extensible programming. But it pushed towards a different approach to coding with the protocol-oriented design and increased safety with static typing.</p>
<p>It was a huge hit and saw its growth sky rocket in the years after introduction. It was the <a target="_blank" href="https://insights.stackoverflow.com/survey/2015#tech">most loved</a> programming language in 2015, the <a target="_blank" href="https://insights.stackoverflow.com/survey/2016#technology">second most loved</a> in 2016, the 11th <a target="_blank" href="https://insights.stackoverflow.com/survey/2017#technology">most popular</a> programming language in 2017, beating out Objective-C, and it also <a target="_blank" href="https://insights.stackoverflow.com/survey/2018/#technology">beat out</a> Objective-C in 2018.</p>
<p>Swift is also a bet by Apple on <a target="_blank" href="https://www.businessinsider.com/apple-tim-cook-on-swift-2017-2">winning over novices</a> to become iOS developers. The hope is that new developers will learn the language and use it to build iOS apps. This then increases the ecosystem of the app store. Since Swift is optimized to work with iOS apps, this ensures the apps being written are of high quality.</p>
<p>Swifts popularity only continues to increase, especially for smaller apps and start-ups. The gap between Swift and Objective-C will only continue to grow. The future is bright for this young language.</p>
<h3 id="heading-a-short-history-of-objective-c">A short history of Objective-C</h3>
<p>Objective-C is an object-oriented programming language that is a superset of C, as the name of the language might reveal. This means that any valid C program will compile with an Objective-C compiler. It derives all its non-object oriented syntax from C and its object oriented syntax from SmallTalk. It was developed in 1984, so it has had time to mature as a language and is much more stable than Swift.</p>
<p>Most people know Objective-C as the language that is used to develop apps for the iPhone, but the history goes much deeper than that. I’d recommend reading <a target="_blank" href="https://medium.com/chmcore/a-short-history-of-objective-c-aff9d2bde8dd">this article</a> for a more in-depth look.</p>
<h3 id="heading-the-strengths-of-swift">The strengths of Swift</h3>
<p>Swift has grown tremendously in popularity for a few key reasons. First off, there are a lot of great development tools Apple has provided to work in conjunction with Swift. One of my personal favorites is the Playground, which is only compatible with Swift. Apple introduced Playgrounds <a target="_blank" href="https://developer.apple.com/videos/play/wwdc2016/408/">in 2016</a>. They were introduced as a way to learn how to code, but I loved them for a different reason.</p>
<p>Mobile development has always had more roadblocks than web development. You need a simulator, you usually need a proprietary Integrated Development Environment (IDE), and you need to set up a whole project just to test some small prototype. In Apple’s case, you also need a developer account. The nice thing about Playgrounds is you get around some of this. You do need Xcode or the Playgrounds app, but that is all. And you can get started with coding and compiling your code right away.</p>
<p>Yet, another huge advantage of Swift is the fact that it is open source. If you have ever wondered how a programming language worked under the hood, then you can <a target="_blank" href="https://github.com/apple/swift">go see for yourself</a>! This is a great way to understand the programming language you work with daily on a deeper level.</p>
<p>An honorable mention goes to a nice utility only available to Swift, the <a target="_blank" href="https://swift.org/package-manager/">Swift Package Manager</a>. The Swift Package Manager is simply a <a target="_blank" href="https://devopedia.org/dependency-manager">dependency manager</a> that is integrated with the Swift build system. It isn’t a game changer by any means, since CocoaPods and Carthage were doing this job a long time ago, but it’s another solution available if needed.</p>
<p>A lot of evidence here supports the fact that Apple is doing a lot to make Swift more desirable as the programming language of choice for iOS developers. They are creating nice utilities and auxiliaries to entice people to start using the language. This shows that Apple is pushing for Swift in full force.</p>
<h3 id="heading-language-features">Language features</h3>
<p>Let’s get into some of the details of the language itself. Swift is safer due to its static typing and the use of optionals. In Swift, if your code requires a string, the features of Swift will guarantee that your code gets a string and not another type, such as an int. This of course depends on if you’re using the language as it is intended and not force unwrapping everything.</p>
<p>Another great feature of Swift is its syntax. Especially compared to Objective-C. The best word to describe the syntax would be “succinct”. There is no need for semi-colons, calls to self or parentheses around if statements. It feels like you are skipping a lot of things that you don’t really need anyway. It can make the process of typing a lot of code “flow” better.</p>
<p>Some people say this leads to development velocity improvements, but I wouldn’t exactly say that myself. The continual need to unwrap objects to comply with Swifts type-safety offsets the development gains that come with the succinctness.</p>
<p>Swift also has a lot of great control flow options with guard, if-let, advanced switch statements, repeat-while and defer. I like all the different options because it lets people control the flow of their code in a way that makes sense to them. A lot of people hate defers but love guards and vice versa. It doesn’t really matter what you like or dislike, but the options are there and you can code in the way that feels best to you.</p>
<p>I can’t forget all the functional programming features such as filter, map and reduce. This is great for handling collections and comes in handy quite often.</p>
<h3 id="heading-the-weaknesses">The weaknesses</h3>
<p>Swift is a young language, and with that, comes some shifting. The migrations between versions are simply a pain. At a small company, the migration tool provided by Apple can be helpful and cover most cases. It becomes less helpful the more code you have. It’s even worse if your codebase contains both Objective-C and Swift code that interoperate.</p>
<p>At my last company, the migration effort took a dedicated group a whole weekend to do. They had to do it on the weekend so that they wouldn’t run into merge conflicts from other devs pushing code. This was incredibly painful for everyone involved.</p>
<p>A reason for these migrations is the fact that Swift <a target="_blank" href="https://theswiftdev.com/2018/11/06/swift-5-and-abi-stability/">isn’t ABI stable</a>. That means newer versions of Swift cannot work with older versions of Swift. That also means that the language cannot be packaged with the OS. This is a big deal for companies with large apps that actively combat app size because Swift is being bundled with the app and increasing the size.</p>
<p>Another issue is that Swift does not play well with Xcode. Xcode feels very choppy when working with Swift and autocomplete <a target="_blank" href="https://www.reddit.com/r/iOSProgramming/comments/8o1kbt/help_with_xcode_autocomplete_does_not_work/">simply doesn’t work</a> sometimes. This is strange given how hard Apple is pushing Swift. You would think that they would want make the experience of using Swift with Xcode a delight.</p>
<p>Swift also has problems with string handling, see the code example above. It is clunky as hell. In your day to day, this isn’t too bad. Where this comes into play the most is during interviews. Unfortunately for Swift devs, interviewers love asking questions that involve string manipulation. This is compounded by the fact that the way strings are handled has changed between versions of Swift.</p>
<h3 id="heading-the-strengths-of-objective-c">The strengths of Objective-C</h3>
<p>Objective-C is a highly dynamic, object oriented language. It is dynamic to the point that you can swap out method invocations at runtime using techniques like <a target="_blank" href="https://nshipster.com/method-swizzling/">Swizzling</a>. It is able to do these kinds of thing due to its message sending paradigm. This lets objects send messages to other objects at run time to determine the invocation of the method being called.</p>
<p>In practical purposes, what does this mean? Well, one big advantage is adaptability at runtime. This means accessing private APIs or doing things like mocking objects at runtime become possible. This can be especially useful when it comes to unit testing. Libraries like <a target="_blank" href="http://ocmock.org/swift/">OCMock</a> make this even easier and allow for very elaborate test set ups. Having good unit tests will make your app more stable and reliable.</p>
<p>Speaking of stability, Objective-C has been around for a long time which makes it a very stable language. With Swift, you’ll run into bugs that are <a target="_blank" href="https://github.com/apple/swift/pull/21727">pretty surprising</a> and would be disruptive to the stability of your app. In the example I linked above, this crash would be caused by the actual language you are using to code your app, not due to any error created by the code you wrote. This can be frustrating.</p>
<p>The last point, which is more important to certain companies, is compatibility with C and C++ libraries. Being that Objective-C is a superset of C, it is easy to use C and C++ code with Objective-C. You can even use Objective-C++ if you feel so inclined. This is important if your are dependent on third party C and C++ libraries.</p>
<h3 id="heading-the-weaknesses-1">The weaknesses</h3>
<p>The first main complaint I hear about Objective-C is syntax. I started my professional career using Objective-C so I have no issues with it. It is verbose and a bit unconventional with the use of square brackets. But opinions on syntax are just that, opinions. I figured I would list this point though since it is one of the first things that comes up when you mention Objective-C.</p>
<p>One thing I do agree with though is that block syntax is frustrating. <a target="_blank" href="http://goshdarnblocksyntax.com/">There is even a website</a> dedicated to decoding the mysteries of blocks in Objective-C. I actually use this website pretty often as a reference.</p>
<p>The biggest issue Objective-C faces right now is the fact that one day Apple may drop support for Objective-C with Cocoa and other common libraries used to create iOS apps. Since Objective-C is primarily used to create iOS apps, this would be a death knell for the language. It also means that newcomers to the iOS community are afraid to commit to learning Objective-C right now since it may no longer be used in the future.</p>
<p>Let’s get back to the language itself. It is prone to having hard to debug issues due to the dynamic nature of the language. The ability to send messages to nil and not crash on top of the lack of strict typing are some examples of things that lead to these hard to debug issues.</p>
<p>Objective-C does not hold your hand when it comes to these things either. Though it is nice that the app doesn’t crash when you send a message to nil, it may put your app in a weird state. It is very hard to debug issues like these. The fact that Swift has strict typing and the use of unwrapping optionals prevents these things at compile time.</p>
<h3 id="heading-should-i-learn-swift-or-objective-c">Should I learn Swift or Objective-C?</h3>
<p>The answer for most people will be Swift. Apple is clearly pushing Swift as the language of choice for its iOS application development community. Swift will only continue to become more performant as ABI stability is introduced and Swift becomes packaged with the OS itself.</p>
<p>If you’re looking to get a job as an iOS developer, Swift will be the language you want to learn. Most startup to mid-level companies will have their iOS apps written completely in Swift. This means you’ll be able to apply and interview for more jobs if you learn Swift.</p>
<p>Even at larger companies where Objective-C is still used heavily, interviews can still be done in Swift. So you can learn Objective-C once you join the company and not worry about burdening yourself with more things to learn before the interview.</p>
<p>You will want to learn Objective-C if you are already working at a start up or mid-level company and want to jump to a larger company. Skills with Objective-C will give you specialized knowledge and an edge over other interview candidates.</p>
<p><em>Liked what you read? Take a look at some of my other articles:</em></p>
<p><a target="_blank" href="https://medium.com/@colin.gabriel.smith/killing-it-during-your-first-tech-interview-16ce13f9d0ce">Tips for your first tech interview.</a></p>
<p><a target="_blank" href="https://medium.freecodecamp.org/how-i-went-from-stuck-and-hopeless-to-making-my-tech-career-dreams-come-true-d1fcf52c0650">Starting a tech career from nothing.</a></p>
<p><a target="_blank" href="https://link.medium.com/rCnf6bajBT">Should you get a computer science degree?</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What the new Apple Watch’s EKG means for the future of consumer wearables and healthcare ]]>
                </title>
                <description>
                    <![CDATA[ By James Hsu When Apple announced this September that its newest Series 4 Apple Watch includes EKG functionality, I imagined millions of hearts worldwide fluttering with delight. The news was significant for several reasons. The chief reason is it is... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-the-apple-watchs-new-ekg-feature-means-for-the-future-of-consumer-wearables-and-medicine-4189c070a4e/</link>
                <guid isPermaLink="false">66c365f4139b845d61e84bc1</guid>
                
                    <category>
                        <![CDATA[ Wearables ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apple ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Health, ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 24 Oct 2018 17:47:19 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*qXbNq_8QxwffeyKLMsrDwQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By James Hsu</p>
<p>When Apple announced this September that its newest Series 4 Apple Watch includes EKG functionality, I imagined millions of hearts worldwide fluttering with delight.</p>
<p>The news was significant for several reasons. The chief reason is it is the first time a mainstream consumer wearable device will perform a sophisticated medical procedure. This same procedure we need to see the doctor for today.</p>
<p>To understand the significance, you need first to set aside the fact that health and fitness are already key reasons why consumers currently use wearables. Fitness trackers have had <em>heart rate</em> sensors for many years now.</p>
<p>(Heart rate sensors are convenient for fitness purposes, to be sure. But, they’re also primitive. Anyone with a finger can feel for a pulse and calculate a heart rate if necessary.)</p>
<p>An <a target="_blank" href="https://www.webmd.com/heart-disease/electrocardiogram-ekgs#1">EKG (or ECG/electrocardiogram)</a> is different than a heart rate measurement. For one, because an EKG looks at the heart’s electrical impulses to monitor for and identify specific heart anomalies. These anomalies are the immediate precursor to serious medical conditions. Conditions like strokes or heart attacks.</p>
<p><em>The technology can and will save lives.</em></p>
<p>By adding new and substantial medical features, Apple (and others) could be paving the way to a future in which wearables serve as the frontline for the diagnosis, treatment, and even prevention of serious medical conditions.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*pexRirzLZVNNWU8t.jpg" alt="Image" width="800" height="456" loading="lazy">
<em>Hold your finger on the crown of the Series 4 Apple Watch, and you’ll get an EKG reading on the spot.</em></p>
<h3 id="heading-the-apple-watch-is-a-class-ii-medical-device">The Apple Watch is a class II medical device.</h3>
<p>Adding an EKG to the Apple Watch wasn’t just an engineering task.</p>
<p>It also required the attention and cooperation of the notoriously finicky Food and Drug Administration (FDA). The FD has cleared Apple’s use of two medical-grade features in the new Apple Watch: 1) the EKG, and 2) the Apple Watch’s ability to identify and notify users of an irregular heart rhythm.</p>
<p>It’s important to note that, with the FDA, “clearing” a device is not the same as “approving” one. The latter is much harder to do and requires much significant collaboration and testing to mitigate potential risks. Clearing the Apple watch took just one month from application to decision. Class II devices like the new Apple Watch don’t require FDA approval because the associated health risks aren’t deemed great enough to warrant a more rigorous vetting process.</p>
<p>It’s also important to understand that <a target="_blank" href="https://www.accessdata.fda.gov/cdrh_docs/pdf18/DEN180044.pdf">the FDA clearance letters</a> came with language stating that the cleared features are not intended for users under the age of 22, and are “not intended to replace traditional methods of diagnosis or treatment.”</p>
<p>Regarding the latter, what this means is that after your Apple Watch tells you it has detected a mild heart arrhythmia, you’ll probably want to follow up with your doctor to get a proper diagnosis.</p>
<p>On the other hand, if your Apple Watch tells you you’ve just had a heart attack, immediate urgency (and common sense) dictates that you’re going to go straight to the ER or call an ambulance, skipping the “traditional method of diagnosis” referenced in the FDA’s letter.</p>
<h3 id="heading-a-beachhead-for-new-medical-functionality">A beachhead for new medical functionality</h3>
<p>With the regulatory precedent established, Apple product managers are undoubtedly considering more medical functionality, to double down on this growing notion of the Apple Watch as a medical device.</p>
<p>If so, what might we see from Apple down the road?</p>
<p>Well, as it turns out, Apple has for <a target="_blank" href="https://www.theverge.com/2017/5/19/15662316/apple-watch-glucose-tracker-tim-cook">years been working on developing a blood glucose tracker</a> that ties to the Apple Watch. Such a tracker could help with diagnosis, treatment, and perhaps even prevention of type 2 diabetes.</p>
<p>Diabetes currently affects an estimated 30 million people in the United States alone. The challenge has been creating <em>noninvasive</em> technology that doesn’t require permeating the skin you to get a reading, as current glucose trackers must do. According to a CNBC report last year, Apple has assembled a new team to pursue this “holy grail” breakthrough.</p>
<p>Here’s Apple CEO Tim Cook on the opportunity with glucose trackers:</p>
<blockquote>
<p>“It’s mentally anguishing to stick yourself many times a day to check your blood sugar. There is lots of hope out there that if someone has constant knowledge of what they’re eating, they can instantly know what causes the response… and that they can adjust well before they become diabetic.”</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*AHq3637kPWpZJ8nd.jpg" alt="Image" width="800" height="533" loading="lazy">
<em>Apple CEO Tim Cook appears to be gung-ho about enabling the Apple Watch as a medical device, with CNBC reporting last year that he was personally testing a blood glucose tracker for the Apple Watch.</em></p>
<h3 id="heading-impact-on-healthcare-practices-and-insurance-costs">Impact on healthcare practices and insurance costs</h3>
<p>Cook’s predecessor, the legendary visionary Steve Jobs, reportedly first envisioned the popularization of consumer wearables that could provide blood glucose readings and other health vitals.</p>
<p>If Jobs’ vision of a versatile wearable health tracker comes to fruition, what effect might this have on the time-tested practice of the “annual physical?” For one, we might very well see formal doctor checkups give way to daily or even hourly automated testing through wearables like the Apple Watch.</p>
<p>And if this happens, what implication might widespread use of the device have beyond users’ health, for instance, on healthcare costs and the healthcare system itself? North American healthcare provider United Healthcare is an example of one insurance provider that is already <a target="_blank" href="https://www.uhc.com/employer/programs-tools/for-employees/unitedhealthcare-motion">offering financial incentives to customers that use wearable fitness trackers to meet daily fitness goals</a>.</p>
<p>When customers get ahold of devices that also address the medical component of wellness and longevity, I’d certainly expect to see such financial incentives increase and healthcare premiums decrease.</p>
<h3 id="heading-wearable-medical-technology-is-not-a-one-horse-race">Wearable medical technology is not a one-horse race</h3>
<p>FitBit, the other big player in health and fitness wearables, <a target="_blank" href="https://www.wired.com/story/when-your-activity-tracker-becomes-a-personal-medical-device/">has had a blood oxygen sensor built into its Ionic watch for more than a year</a>. The sensor can be used to detect common breathing related disorders such as asthma, sleep apnea, and even heart arrhythmia conditions such as atrial fibrillation.</p>
<p>There’s a problem, though. At the time of this story’s publication, Fitbit has not yet publicly released software that makes use of the hardware sensor.</p>
<p>Samsung is another company that has demonstrated a commitment to adapting its wearable technologies to support medical use cases.</p>
<p>For instance, Samsung’s Gear VR headset is used by California-based <a target="_blank" href="https://irisvision.com/">IrisVision</a> to allow legally blind users to see clearly in all aspects of life. Using <a target="_blank" href="https://citrusbits.com/portfolio/irisvision/">custom IrisVision software</a>, the IrisVision headset uses proprietary visual acuity algorithms to amplify any remaining useful vision a user still has. The result is clear vision and, for many users, the restoration of independence in their daily lives. IrisVision has the financial support of the National Institute of Health (NIH) and was developed by leading vision experts from Johns Hopkins University, UC Berkeley, Stanford, and UCLA.</p>
<h3 id="heading-medical-wearables-will-empower-clinical-researchers">Medical wearables will empower clinical researchers</h3>
<p>Beyond consumer healthcare, clinical researchers stand to benefit from these recent developments in wearables, too. When doing any sort of clinical research, getting reliable data can be an enormous challenge, especially when a study depends on self-reported data or recollections.</p>
<p>Even for clinical studies that do use lab results, gathering data collection can be a challenge — costly, impractical, or even impossible.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*Oq8V1mawbYvZH8ZL.jpg" alt="Image" width="800" height="532" loading="lazy">
<em>In clinical testing and research, data collection can be a considerable challenge without sophisticated wearables.</em></p>
<p>But, if these measurements can be taken automatically by a wearable device, that largely addresses the issue, providing rich, reliable, and (perhaps) actionable data to researchers whose work depends on the availability of data they can trust.</p>
<p>Case in point, Johns Hopkins University has for the past three years <a target="_blank" href="https://www.hopkinsmedicine.org/epiwatch/#.W8e46GhKiUk">been conducting a clinical study that allows participants to use their Apple Watches and the university’s EpiWatch app</a> to provide clinical data (heart rate and accelerometer data) to further their understanding of epilepsy.</p>
<p>And, just last September, the NIH granted $2.5M to <a target="_blank" href="http://www.biosensics.com/">BioSensics</a> to develop wearable sensors to monitor the symptoms of Huntington’s disease. <a target="_blank" href="https://clinicaltrials.gov/ct2/show/NCT03599076">A pilot study in collaboration with The University of Rochester is now underway</a>.</p>
<h3 id="heading-wearables-provide-the-sensors-and-hardware-but-user-experience-is-paramount">Wearables provide the sensors and hardware, but user experience is paramount.</h3>
<p>The hardware engineering associated with integrating medical sensors into small wearables is just one aspect of the challenge.</p>
<p>Another aspect of the challenge is inventing non-invasive or otherwise “user-friendly” sensors that can provide readings equivalent to what we, for example, currently need to draw blood to obtain. Frankly speaking, consumers will not buy a device that causes them pain or even startles them on a regular basis.</p>
<p>The regulatory hurdles (à la FDA) are another aspect of challenge, albeit one that seems promising based on the recent Apple clearances.</p>
<p>The final challenge is the software and user experience, which bring meaning to the data collected by the sensors. Sure, you can have an EKG provide readings — a line graph of electrical impulses — but how do you deliver that to your end user in a way that is not just useful, but is also intuitive and even enjoyable?</p>
<p>According to <a target="_blank" href="https://citrusbits.com/">CitrusBits</a> CEO, Harry Lee, apps are often the biggest competitive differentiator for wearables companies.</p>
<blockquote>
<p>“In the wearables space, the hardware aspect is already somewhat commoditized. Everyone, more or less, has access to the same sensors, microprocessors, and chips. Where companies like Apple, Fitbit, and CitrusBits stand apart is in their ability to design intuitive and robust apps for smartwatches and other devices, given inherent screen-size and control constraints. This is absolutely key to adoption, and we’ve already seen once-promising wearables companies such as Pebble forced to shut down in recent years, in part due to weak app offerings.”</p>
</blockquote>
<p>Looking ahead, the realization of Steve Jobs’ vision is clearly upon us: a future in which medical wearables will play a big role, perhaps even reducing the strain on existing healthcare systems.</p>
<p>It just may very well depend on a harmonious blend of computing hardware, non-invasive medical sensors, progressive regulatory oversight, and thoughtfully-crafted applications.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
