<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Donny Wals</title>
    <description>The latest articles on Forem by Donny Wals (@donnywals).</description>
    <link>https://forem.com/donnywals</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F267637%2Fee051902-148c-4ecb-bc4a-d2dcf35b616e.jpg</url>
      <title>Forem: Donny Wals</title>
      <link>https://forem.com/donnywals</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/donnywals"/>
    <language>en</language>
    <item>
      <title>Forcing an app out of memory on iOS</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Thu, 23 Dec 2021 11:11:14 +0000</pubDate>
      <link>https://forem.com/donnywals/forcing-an-app-out-of-memory-on-ios-1m6f</link>
      <guid>https://forem.com/donnywals/forcing-an-app-out-of-memory-on-ios-1m6f</guid>
      <description>&lt;p&gt;I’ve recently been working on a background uploading feature for an app. One of the key aspects to get right with a feature like that is to correctly handle scenarios where your app is suspended by the system due to RAM constraints or other, similar, reasons. Testing this is easily done by clearing the RAM memory on your device. Unfortunately, this isn’t straightforward. But it’s also not impossible.&lt;/p&gt;

&lt;p&gt;Note that opening the task switcher and force closing your app from there is not quite the same as forcing your app to be suspended. Or rather, it’s not the same as forcing your app out of memory.&lt;/p&gt;

&lt;p&gt;Luckily, there’s somewhat of a hidden trick to clear your iOS device’s RAM memory, resulting in your app getting suspended just like it would if the device ran out of memory due to something your user is doing.&lt;/p&gt;

&lt;p&gt;To force-clear your iOS device’s RAM memory, go through the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you’re using a device without a home button, enable Assistive Touch. If your device has a home button you can skip this step. You can enable Assistive Touch by going to &lt;strong&gt;Settings → Accessibility → Touch → Enable Assistive Touch&lt;/strong&gt;. This will make a floating software button appear on your device that can be tapped to access several shortcuts, a virtual home button is one of these shortcuts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1vqwGEiz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.donnywals.com/wp-content/uploads/IMG_0091-1024x715.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1vqwGEiz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.donnywals.com/wp-content/uploads/IMG_0091-1024x715.png" alt="Settings window for accessibility -&amp;gt; touch -&amp;gt; assistive touch" width="880" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In a (somewhat) fluid sequence press &lt;strong&gt;volume up&lt;/strong&gt;, &lt;strong&gt;volume down&lt;/strong&gt;, and then hold your device’s &lt;strong&gt;power button&lt;/strong&gt; until a screen appears that allows you to power down your device.&lt;/li&gt;
&lt;li&gt;Once that screen appears, tap the assistive touch button and then press and hold the &lt;strong&gt;virtual home button&lt;/strong&gt; until you’re prompted to unlock your device. You’ve successfully wiped your device’s RAM memory.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z2FNIKyy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.donnywals.com/wp-content/uploads/IMG_0092-1024x715.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z2FNIKyy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.donnywals.com/wp-content/uploads/IMG_0092-1024x715.jpg" alt="Shut down screen with assistive touch actions visible" width="880" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Being able to simulate situations where your app goes out of memory is incredibly useful when you’re working on features that rely on your app being resumed in the background even when it’s out of memory. Background uploads and downloads are just some examples of when this trick is useful. &lt;/p&gt;

&lt;p&gt;My favorite part of using this approach to debug my apps going out of memory is that I can do it completely detached from Xcode, and I can even ask other people like a Q&amp;amp;A department to test with this method to ensure everything works as expected.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Using Swift's async/await to build an image loader</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Tue, 07 Sep 2021 07:26:50 +0000</pubDate>
      <link>https://forem.com/donnywals/using-swift-s-async-await-to-build-an-image-loader-4kng</link>
      <guid>https://forem.com/donnywals/using-swift-s-async-await-to-build-an-image-loader-4kng</guid>
      <description>&lt;p&gt;Async/await will be the defacto way of doing asynchronous programming on iOS 15 and above. I've already written &lt;a href="https://www.donnywals.com/category/swift-concurrency/"&gt;quite a bit&lt;/a&gt; about the new Swift Concurrency features, and there's still plenty to write about. In this post, I'm going to take a look at building an asynchronous image loader that has support for caching.&lt;/p&gt;

&lt;p&gt;SwiftUI on iOS 15 already has a component that allows us to load images from the network but it doesn't support caching (other than what’s already offered by &lt;code&gt;URLSession&lt;/code&gt;), and it only works with a &lt;code&gt;URL&lt;/code&gt; rather than also accepting a &lt;code&gt;URLRequest&lt;/code&gt;. The component will be fine for most of our use cases, but as an exercise, I'd like to explore what it takes to implement such a component ourselves. More specifically I’d like to explore what it’s like to build an image loader with Swift Concurrency.&lt;/p&gt;

&lt;p&gt;We'll start by building the image loader object itself. After that, I'll show how you can build a simple SwiftUI view that uses the image loader to load images from the network (or a local cache if possible). We'll make it so that the loader work with both &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;URLRequest&lt;/code&gt; to allow for maximum configurability. &lt;/p&gt;

&lt;p&gt;Note that the point of this post is not to show you a perfect image caching solution. The point is to demonstrate how you'd build an &lt;code&gt;ImageLoader&lt;/code&gt; object that will check whether an image is available locally and only uses the network if the requested image isn't available locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the image loader API
&lt;/h2&gt;

&lt;p&gt;The public API for our image loader will be pretty simple. It'll be just two methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;public func fetch(_ url: URL) async throws -&amp;gt; UIImage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;public func fetch(_ urlRequest: URLRequest) async throws -&amp;gt; UIImage&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The image loader will keep track of in-flight requests and already loaded images. It'll reuse the image or the task that's loading the image whenever possible. For this reason, we'll want to make the image loader an &lt;code&gt;actor&lt;/code&gt;. If you're not familiar with actors, take a look at &lt;a href="https://www.donnywals.com/an-introduction-to-synchronizing-access-with-swifts-actors/"&gt;this post&lt;/a&gt; I published to brush up on Swift Concurrency's actors.&lt;/p&gt;

&lt;p&gt;While the public API is relatively simple, tracking in-progress fetches and loading images from disk when possible will require a little bit more effort. &lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the ImageLoader actor
&lt;/h2&gt;

&lt;p&gt;We'll work our way towards a fully featured loader one step at a time. Let's start by defining the skeleton for the &lt;code&gt;ImageLoader&lt;/code&gt; actor and take it from there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="n"&gt;actor&lt;/span&gt; &lt;span class="kt"&gt;ImageLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LoaderStatus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[:]&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// fetch image by URLRequest&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="kt"&gt;LoaderStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;inProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code snippet I actually did a little bit more than just define a skeleton. For example, I've defined a private enum &lt;code&gt;LoaderStatus&lt;/code&gt;. This enum will be used to keep track of which images we're loading from the network, and which images are available immediately from memory. I also went ahead and implemented the &lt;code&gt;fetch(:)&lt;/code&gt; method that takes a &lt;code&gt;URL&lt;/code&gt;. To keep things simple, it just constructs a &lt;code&gt;URLRequest&lt;/code&gt; with no additional configuration and calls the overload for &lt;code&gt;fetch(_:)&lt;/code&gt; that takes a &lt;code&gt;URLRequest&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now that we have a skeleton ready to go, we can start implementing the &lt;code&gt;fetch(_:)&lt;/code&gt; method. There are essentially three different scenarios that we can run into. Interestingly enough, these three scenarios are quite similar to what I wrote in an &lt;a href="https://www.donnywals.com/building-a-token-refresh-flow-with-async-await-and-swift-concurrency/"&gt;earlier Swift Concurrency related post&lt;/a&gt; that covered refreshing authentication tokens. &lt;/p&gt;

&lt;p&gt;The scenarios can be roughly defined as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;fetch(_:)&lt;/code&gt; has already been called for this &lt;code&gt;URLRequest&lt;/code&gt; so will either return a task or the loaded image.&lt;/li&gt;
&lt;li&gt;We can load the image from disk and store it in-memory&lt;/li&gt;
&lt;li&gt;We need to load the image from the network and store it in-memory and on disk&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll show you the implementation for &lt;code&gt;fetch(_:)&lt;/code&gt; one step at a time. Note that the code won't compile until we've finished the implementation.&lt;/p&gt;

&lt;p&gt;First, we'll want to check the &lt;code&gt;images&lt;/code&gt; dictionary to see if we can reuse an existing task or grab the image directly from the dictionary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// we'll need to implement a bit more before this code compiles&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above shouldn't look too surprising. We can simply check the dictionary like we would normally. Since &lt;code&gt;ImageLoader&lt;/code&gt; is an actor, it will ensure that accessing this dictionary is done in a thread safe way (don't forget to refer back to &lt;a href="https://www.donnywals.com/an-introduction-to-synchronizing-access-with-swifts-actors/"&gt;my post on actors&lt;/a&gt; if you're not familiar with them yet).&lt;/p&gt;

&lt;p&gt;If we find an image, we return it. If we encounter an in-progress task, we await the task's value to obtain the requested image without creating a new (duplicate) task.&lt;/p&gt;

&lt;p&gt;The next step is to check whether the image exist on disk to avoid having to go to the network if we don't have to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... code from the previous snippet&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imageFromFileSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// we'll need to implement a bit more before this code compiles&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code calls out to a private method called &lt;code&gt;imageFromFileSystem&lt;/code&gt;. I haven't shown you this method yet, I'll show you the implementation soon. First, I want to briefly cover what this code snippet does. It attempts to fetch the requested image from the filesystem. This is done synchronously and when an image is found we store it in the &lt;code&gt;images&lt;/code&gt; array so that the next called of &lt;code&gt;fetch(_:)&lt;/code&gt; will receive the image from memory rather than the filesystem.&lt;/p&gt;

&lt;p&gt;And again, this is all done in a thread safe manner because our &lt;code&gt;ImageLoader&lt;/code&gt; is an actor.&lt;/p&gt;

&lt;p&gt;As promised, here's what &lt;code&gt;imageFromFileSystem&lt;/code&gt; looks like. It's fairly straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;imageFromFileSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;assertionFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to generate a local path for &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;contentsOf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;absoluteString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addingPercentEncoding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;withAllowedCharacters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlPathAllowed&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;applicationSupport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;applicationSupportDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userDomainMask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;applicationSupport&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendingPathComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third and last situation we might encounter is one where the image needs to be retrieved from the network. Let's see what this looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... code from the previous snippets&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;URLSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;persistImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;persistImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jpegData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;compressionQuality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;assertionFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to generate a local path for &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This last addition to &lt;code&gt;fetch(:)&lt;/code&gt; creates a new &lt;code&gt;Task&lt;/code&gt; instance to fetch image data from the network. When the data is successfully retrieved, and it's converted to an instance of &lt;code&gt;UIImage&lt;/code&gt;. This image is then persisted to disk using the &lt;code&gt;persistImage(:for:)&lt;/code&gt; method that I included in this snippet.&lt;/p&gt;

&lt;p&gt;After creating the task, I update the &lt;code&gt;images&lt;/code&gt; dictionary so it contains the newly created task. This will allow other callers of &lt;code&gt;fetch(_:)&lt;/code&gt; to reuse this task. Next, I await the task's value and I update the &lt;code&gt;images&lt;/code&gt; dictionary so it contains the fetched image. Lastly, I return the image.&lt;/p&gt;

&lt;p&gt;You might be wondering why I need to add the in progress task to the &lt;code&gt;images&lt;/code&gt; dictionary before awaiting it.&lt;/p&gt;

&lt;p&gt;The reason is that while &lt;code&gt;fetch(:)&lt;/code&gt; is suspended to await the networking task's value, other callers to &lt;code&gt;fetch(:)&lt;/code&gt; will get  time to run. This means that while we're awaiting the task value, someone else might call the &lt;code&gt;fetch(_:)&lt;/code&gt; method and read the &lt;code&gt;images&lt;/code&gt; dictionary. If the in progress task isn't added to the dictionary at that time, we would kick off a second fetch. By updating the &lt;code&gt;images&lt;/code&gt; dictionary first, we make sure that subsequent callers will reuse the in progress task.&lt;/p&gt;

&lt;p&gt;At this point, we have a complete image loader done. Pretty sweet, right? I'm always delightfully surprised to see how simple actors make complicated flows that require careful synchronization to correctly handle concurrent access.&lt;/p&gt;

&lt;p&gt;Here's what the final implementation for the &lt;code&gt;fetch(_:)&lt;/code&gt; method looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imageFromFileSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;URLSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;persistImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;urlRequest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, using it in a SwiftUI view to create our own version of &lt;code&gt;AsyncImage&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building our custom SwiftUI async image view
&lt;/h2&gt;

&lt;p&gt;The custom SwiftUI view that we'll create in this section is mostly intended as a proof of concept. I've tested it in a few scenarios but not thoroughly enough to say with confidence that this would be a better async image than the built-in &lt;code&gt;AsyncImage&lt;/code&gt;. However, I'm pretty sure that this is an implementation that should work fine in many situations.&lt;/p&gt;

&lt;p&gt;To provide our custom image view with an instance of the &lt;code&gt;ImageLoader&lt;/code&gt;, I'll use SwiftUI's environment. To do this, we'll need to add a custom value to the &lt;code&gt;EnvironmentValues&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ImageLoaderKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EnvironmentKey&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;defaultValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ImageLoader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;EnvironmentValues&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;imageLoader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ImageLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;ImageLoaderKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;ImageLoaderKey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code adds an instance of &lt;code&gt;ImageLoader&lt;/code&gt; to the SwiftUI environment, allowing us to easily access it from within our custom view.&lt;/p&gt;

&lt;p&gt;Our SwiftUI view will be initialized with a &lt;code&gt;URL&lt;/code&gt; or a &lt;code&gt;URLRequest&lt;/code&gt;. To keep things simple, we'll always use a &lt;code&gt;URLRequest&lt;/code&gt; internally. &lt;/p&gt;

&lt;p&gt;Here's what the SwiftUI view's implementation looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;RemoteImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;
    &lt;span class="kd"&gt;@State&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;

    &lt;span class="kd"&gt;@Environment&lt;/span&gt;&lt;span class="p"&gt;(\&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;imageLoader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;imageLoader&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Group&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;uiImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;loadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;await&lt;/span&gt; &lt;span class="n"&gt;imageLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we're instantiating the view, we provide it with a &lt;code&gt;URL&lt;/code&gt; or a &lt;code&gt;URLRequest&lt;/code&gt;. When the view is first rendered, &lt;code&gt;image&lt;/code&gt; will be &lt;code&gt;nil&lt;/code&gt; so we'll just render a placeholder rectangle. I didn't give it any size, that would be up to the user of &lt;code&gt;RemoteImage&lt;/code&gt; to do.&lt;/p&gt;

&lt;p&gt;The SwiftUI view has a &lt;code&gt;task&lt;/code&gt; modifier applied. This modifier allows us to run asynchronous work when the view is first created. In this case, we'll use a task to ask the image loader for an image. When the image is loaded, we update the &lt;code&gt;@State var image&lt;/code&gt; which will trigger a redraw of the view.&lt;/p&gt;

&lt;p&gt;This SwiftUI view is pretty simple and it doesn't handle things like animations or updating the image later. Some nice additions could be to add the ability to use a placeholder image, or to make the &lt;code&gt;source&lt;/code&gt; property non-private and use an &lt;code&gt;onChange&lt;/code&gt; modifier to kick off a new task using the &lt;code&gt;Task&lt;/code&gt; initializer to load a new image. &lt;/p&gt;

&lt;p&gt;I'll leave these features to be implemented by you. The point of this simple view was merely to show you how this custom image loader can be used in a SwiftUI context; not to show you how to build a fantastic fully-featured SwiftUI image view replacement.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;In this post we covered a lot of ground. I mean, &lt;em&gt;a lot&lt;/em&gt;. You saw how you can build an &lt;code&gt;ImageLoader&lt;/code&gt; that gracefully handles concurrent calls by making it an actor. You saw how we can keep track of both in progress fetches as well as already fetched images using a dictionary. I showed you a very simple implementation of a file system cache as well. This allows us to cache images in memory, and load from the filesystem if needed. Lastly, you saw how we can implement logic to load our image from the network if needed.&lt;/p&gt;

&lt;p&gt;You learned that while an asynchronous function that's defined on an actor is suspended, the actor's state can be read and written by others. This means that we needed to assign our image loading task to our dictionary before awaiting the tasks result so that subsequent callers would reuse our in progress task.&lt;/p&gt;

&lt;p&gt;After that, I showed you how you can inject the custom image loader we've built into SwiftUI's environment, and how it can be used to build a very simple custom asynchronous image view. &lt;/p&gt;

&lt;p&gt;All in all, you've learned a lot in this post. And the best part is, in my opinion, that while the underlying logic and thought process is quite complex, Swift Concurrency allows us to express this logic in a sensible and readable way which is really awesome.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>async</category>
      <category>concurrency</category>
      <category>swiftui</category>
    </item>
    <item>
      <title>What exactly is a Combine AnyCancellable?</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Tue, 24 Aug 2021 18:41:11 +0000</pubDate>
      <link>https://forem.com/donnywals/what-exactly-is-a-combine-anycancellable-5gc3</link>
      <guid>https://forem.com/donnywals/what-exactly-is-a-combine-anycancellable-5gc3</guid>
      <description>&lt;p&gt;If you've worked with Combine at all in your applications you'll know what it means when I tell you that you should always retain your cancellables. Cancellables are an important part of working with Combine, similar to how disposables are an important part of working with RxSwift.&lt;/p&gt;

&lt;p&gt;For example, you might have built a publisher that wraps &lt;code&gt;CLLocationManagerDelegate&lt;/code&gt; and exposes the user's current location with a &lt;code&gt;currentLocation&lt;/code&gt; publisher that's a &lt;code&gt;CurrentValueSubject&amp;lt;CLLocation, Never&amp;gt;&lt;/code&gt;. If you subscribe to this publisher it might look a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ViewModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;locationProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LocationProvider&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;cancellables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;AnyCancellable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;locationProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LocationProvider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;locationProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;locationProvider&lt;/span&gt;
        &lt;span class="n"&gt;locationProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentLocation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sink&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;newLocation&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; 
            &lt;span class="c1"&gt;// use newLocation&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cancellables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For something that's so key to working with Combine, it kind of seems like cancellables are just something we deal with without really questioning it. Thats why in this post, I'd like to take a closer look at what a cancellable is, and more specifically, I'd like to look at what the enigmatic &lt;code&gt;AnyCancellable&lt;/code&gt; that's returned by both &lt;code&gt;sink&lt;/code&gt; and &lt;code&gt;assign(to:on:)&lt;/code&gt; is exactly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the purpose of cancellables in Combine
&lt;/h2&gt;

&lt;p&gt;Cancellables in Combine fulfill an important part in Combine's subscription lifecycle. &lt;a href="https://developer.apple.com/documentation/combine/cancellable"&gt;According to Apple&lt;/a&gt;, the &lt;code&gt;Cancellable&lt;/code&gt; protocol is the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A protocol indicating that an activity or action supports cancellation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok. That's not very useful per se. I mean, if supporting cancellation is all we want to do, why do we need to retain our cancellables?&lt;/p&gt;

&lt;p&gt;If we look at the detailed description for &lt;code&gt;Cancellable&lt;/code&gt;, you'll find that it says the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Calling cancel() frees up any allocated resources. It also stops side effects such as timers, network access, or disk I/O.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This still isn't great, but at least it's something. We know that an object that implements &lt;code&gt;Cancellable&lt;/code&gt; has a &lt;code&gt;cancel&lt;/code&gt; method that we can call to stop any in progress work. And more importantly, we know that we can expect any allocated resources to be freed up. That's really good to know.&lt;/p&gt;

&lt;p&gt;What this doesn't really tell us is why we need to retain our cancellables in Combine. Based on the information that Apple provides there's nothing that even hints towards the need to retain cancellables.&lt;/p&gt;

&lt;p&gt;Let's take a look at the documentation for &lt;code&gt;AnyCancellable&lt;/code&gt; next. Maybe a &lt;code&gt;Cancellable&lt;/code&gt; and &lt;code&gt;AnyCancellable&lt;/code&gt; aren't quite the same even though we'd expect &lt;code&gt;AnyCancellable&lt;/code&gt; to be nothing more than a &lt;a href="https://www.donnywals.com/understanding-type-erasure-in-swift/"&gt;type-erased&lt;/a&gt; &lt;code&gt;Cancellable&lt;/code&gt; based on the way Apple chose to name it.&lt;/p&gt;

&lt;p&gt;The short description explains the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A type-erasing cancellable object that executes a provided closure when canceled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok. That's interesting. So rather it being "just" a type erased object that conforms to &lt;code&gt;Cancellable&lt;/code&gt;, we can provide a closure to actually do something when we initialize an &lt;code&gt;AnyCancellable&lt;/code&gt;. When we subscribe to a publisher we don't create our own &lt;code&gt;AnyCancellable&lt;/code&gt; though, so we'll need to dig a little deeper. &lt;/p&gt;

&lt;p&gt;There's once sentence in the &lt;code&gt;AnyCancellable&lt;/code&gt; documentation that tells us exactly why we need to retain cancellables. It's the very last sentence in the discussion and it reads as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An AnyCancellable instance automatically calls cancel() when deinitialized.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what exactly does this tell us?&lt;/p&gt;

&lt;p&gt;Whenever an &lt;code&gt;AnyCancellable&lt;/code&gt; is deallocated, it will call &lt;code&gt;cancel()&lt;/code&gt; on itself. This will run the provided closure that I mentioned earlier. It's save to assume that this closure will ensure that any resources associated with our subscription are torn down. After all, that's what the &lt;code&gt;cancel()&lt;/code&gt; method is supposed to do according to the &lt;code&gt;Cancellable&lt;/code&gt; protocol.&lt;/p&gt;

&lt;p&gt;Based on this, we can deduce that the purpose of cancellables in Combine, or rather the purpose of &lt;code&gt;AnyCancellable&lt;/code&gt; in Combine is to associate the lifecycle of a Combine subscription to something other than the subscription completing.&lt;/p&gt;

&lt;p&gt;When we retain a cancellable in an instance of a view model, view controller, or any other object, the lifecycle of that subscription becomes connected to that of the owner (the retaining object) itself. Whenever the owner of the cancellable is deallocated, the subscription is torn down and all resources are freed up immediately.&lt;/p&gt;

&lt;p&gt;Note that this might not be quite intuitive when you think of that original description I quoted from the &lt;code&gt;Cancellable&lt;/code&gt; documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A protocol indicating that an activity or action supports cancellation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cancelling a subscription by calling &lt;code&gt;cancel()&lt;/code&gt; on an &lt;code&gt;AnyCancellable&lt;/code&gt; is not a graceful operation. This is already hinted at because the documentation for &lt;code&gt;Cancellable&lt;/code&gt; mentions that &lt;em&gt;"any allocated resources"&lt;/em&gt; will be freed up. You need to interpret this broadly.&lt;/p&gt;

&lt;p&gt;You won't just cancel an in flight network call and be notified about it in a &lt;code&gt;receiveCompletion&lt;/code&gt; closure. Instead, the entire subscription is torn down &lt;em&gt;immediately&lt;/em&gt;. You will not be informed of this, and you will not be able to react to this in your &lt;code&gt;receiveCompletion&lt;/code&gt; closure.&lt;/p&gt;

&lt;p&gt;So. To sum up the purpose of cancellables in Combine, they are used to tie the lifecycle of a subscription to the object that retains the cancellable that we receive when we subscribe to a publisher.&lt;/p&gt;

&lt;p&gt;This description might lead to you thinking that an &lt;code&gt;AnyCancellable&lt;/code&gt; is a wrapper for a subscription. Unfortunately, that's not quite accurate. It's also not flat out wrong, but there's a bit of a nuance here; Apple chose the name &lt;code&gt;AnyCancellable&lt;/code&gt; instead of &lt;code&gt;Subscription&lt;/code&gt; on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's inside an AnyCancellable exactly?
&lt;/h2&gt;

&lt;p&gt;If an &lt;code&gt;AnyCancellable&lt;/code&gt; isn't a subscription, then what it is? What's inside of an &lt;code&gt;AnyCancellable&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The answer is complicated. &lt;/p&gt;

&lt;p&gt;When I was first learning Combine I was lucky enough to run into an Apple employee at a conference. We got talking about Combine, and I explained that I was working on a Combine book. I kind of started firing off a few questions to validate my understanding of Combine and I was very lucky to kind of get an answer or two. &lt;/p&gt;

&lt;p&gt;One of my questions was "So is an &lt;code&gt;AnyCancellable&lt;/code&gt; a subscription then?" and the answer was short and simple "No. It's an &lt;code&gt;AnyCancellable&lt;/code&gt;". &lt;/p&gt;

&lt;p&gt;You might think that's unhelpful, and I would fully understand. However, the answer is fully correct as I learned in our conversation.&lt;/p&gt;

&lt;p&gt;Combine intentionally does not specify what's inside of a cancellable because we simply don't need to know exactly what is wrapped and how. All we need to know is that an &lt;code&gt;AnyCancellable&lt;/code&gt; conforms to the &lt;code&gt;Cancellable&lt;/code&gt; protocol, and when its &lt;code&gt;cancel()&lt;/code&gt; method is called, all resources retained by whatever the &lt;code&gt;Cancellable&lt;/code&gt; wrapper are released.&lt;/p&gt;

&lt;p&gt;In practice, we know that an &lt;code&gt;AnyCancellable&lt;/code&gt; will most likely wrap an object that conforms to &lt;code&gt;Subscription&lt;/code&gt; and possibly also one that conforms to &lt;code&gt;Subscriber&lt;/code&gt;. One of the two might even have a reference to a &lt;code&gt;Publisher&lt;/code&gt; object. &lt;/p&gt;

&lt;p&gt;We know this because we know that these three objects are always involved when you subscribe to a publisher. I've outlined this in more detail in &lt;a href="https://www.donnywals.com/understanding-combines-publishers-and-subscribers/"&gt;this post&lt;/a&gt; as well as my &lt;a href="https://practicalcombine.com"&gt;Combine book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is really a long-winded way of me trying to tell you that we don't know what's inside an &lt;code&gt;AnyCancellable&lt;/code&gt;, and it doesn't matter. You just need to remember that when an &lt;code&gt;AnyCancellable&lt;/code&gt; is deallocated it will run its cancellation closure which will tear down anything it retains. This includes tearing down your subscription to a publisher.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;In this post you learned about a key aspect of Combine; the &lt;code&gt;Cancellable&lt;/code&gt;. I explained what the &lt;code&gt;Cancellable&lt;/code&gt; protocol is, and from there I moved on to explain what the &lt;code&gt;AnyCancellable&lt;/code&gt; is. &lt;/p&gt;

&lt;p&gt;You learned that subscribing to a publisher with &lt;code&gt;sink&lt;/code&gt; or &lt;code&gt;assign(to:on:)&lt;/code&gt; will return an &lt;code&gt;AnyCancellable&lt;/code&gt; that will tear down your subscription whenever the &lt;code&gt;AnyCancellable&lt;/code&gt; is deallocated. This makes sure that your subscription to a publisher is deallocated when the object that retains your &lt;code&gt;AnyCancellable&lt;/code&gt; is deallocated. This prevents your subscriptions from being deallocated immediately when the scope where they're created exits.&lt;/p&gt;

&lt;p&gt;Lastly, I explained that we don't know what exactly is inside of the &lt;code&gt;AnyCancellable&lt;/code&gt; objects that we retain for our subscriptions. While we can be pretty certain that an &lt;code&gt;AnyCancellable&lt;/code&gt; must somehow retain a subscription, we shouldn't refer to it as a wrapper for a subscription because that would be inaccurate. &lt;/p&gt;

&lt;p&gt;Hopefully this post gave you some extra insights into something that everybody that works with Combine has to deal with even though there's not a ton of information out there on &lt;code&gt;AnyCancellable&lt;/code&gt; specifically.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>combine</category>
      <category>frp</category>
    </item>
    <item>
      <title>What does “atomic” mean in programming?</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Tue, 24 Aug 2021 07:44:56 +0000</pubDate>
      <link>https://forem.com/donnywals/what-does-atomic-mean-in-programming-1bm6</link>
      <guid>https://forem.com/donnywals/what-does-atomic-mean-in-programming-1bm6</guid>
      <description>&lt;p&gt;When you're learning about databases or multithreaded programming, it's likely that you'll come across the term "atomic" at some point.&lt;/p&gt;

&lt;p&gt;Usually you'll hear the term in the context of an operation. For example, an atomic read / write operation. Or atomic access to a property.&lt;/p&gt;

&lt;p&gt;But what does this mean?&lt;/p&gt;

&lt;p&gt;Generally, you can summarize atomic as "one at a time".&lt;/p&gt;

&lt;p&gt;For example, when accessing or mutating a property is atomic, it means that only one read or write operation can be performed at a time. If you have a program that reads a property atomically, this means that the property cannot change during this read operation.&lt;/p&gt;

&lt;p&gt;In Swift, operations on a dictionary are not atomic. This means that in a multithreaded application, a dictionary might be changed from one thread while another thread is reading from it. No thread or operation has exclusive access to your dictionary.&lt;/p&gt;

&lt;p&gt;If the operation was atomic, the first read operation would have to finish before the write can start.&lt;/p&gt;

&lt;p&gt;Another way to think of an atomic operation is that no observer of an atomic operation can "see" the operation as in-progress. You can observe the operation as not yet started or as completed, but never in between.&lt;/p&gt;

&lt;p&gt;I wrote a &lt;a href="https://www.donnywals.com/why-your-atomic-property-wrapper-doesnt-work-for-collection-types/"&gt;post about an @Atomic property wrapper&lt;/a&gt; that I've seen making the rounds. In that post, you can see why this property wrapper does not guarantee exclusive access properly for value types, resulting in strange results.&lt;/p&gt;

&lt;p&gt;If you want to learn more about atomicity and see an example of atomicity in Swift, I highly recommend you give that post a look.&lt;/p&gt;

&lt;p&gt;If you're just looking for a definition, think of atomic as exclusive or one at a time. When an operation is performed atomically, you know that no other operations will interfere with your atomic operation.&lt;/p&gt;

&lt;p&gt;I hope this quick tip gave you a better idea of what atomic means in programming. If you have any questions about this posts or if you have suggestions to make it better, feel free to reach out on &lt;a href="https://twitter.com/donnywals"&gt;Twitter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>swift</category>
      <category>atomic</category>
      <category>programming</category>
      <category>theory</category>
    </item>
    <item>
      <title>The iOS Developer's guide to WWDC 2021</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Thu, 03 Jun 2021 07:19:27 +0000</pubDate>
      <link>https://forem.com/donnywals/the-ios-developer-s-guide-to-wwdc-2021-46h2</link>
      <guid>https://forem.com/donnywals/the-ios-developer-s-guide-to-wwdc-2021-46h2</guid>
      <description>&lt;p&gt;WWDC is always an exciting time for iOS engineers. It's the one week a year where we're all newcomers to a whole range of features and APIs that Apple has just unleashed upon the world through their latest Xcode, macOS, iOS, tvOS, iPadOS, and watchOS betas. The entire iOS community comes out of hiding and we all come together to share thoughts, experiences, opinions, and findings. &lt;/p&gt;

&lt;p&gt;For a whole week, Apple releases dozens of sessions on different topics, and we all scramble to watch them as soon as possible to make sure we're all up to date with whatever the latest and greatest is. As a newcomer, or a person with a regular sleeping schedule, this can be quite intimidating.&lt;/p&gt;

&lt;p&gt;So that's why I figured I'd put together a little guide to making the most out of WWDC without being completely overwhelmed and intimidated by the sheer volume of content that Apple is about to unleash on us all.&lt;/p&gt;

&lt;p&gt;Let's jump right in, shall we.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 1: Breathe
&lt;/h2&gt;

&lt;p&gt;Once Apple opens up that firehose of new content and beta's it's a scramble. You immediately start up the Beta downloads once they're up. In the meantime, you scan the documentation for new things and you're looking at the Apple Developer app to try and figure out which sessions you're going to watch and when. &lt;/p&gt;

&lt;p&gt;It's a lot to take in all at once. &lt;/p&gt;

&lt;p&gt;When you blink twice, you'll see the first people Tweet about the cool things they're already doing with the new Xcode beta while you're still waiting for that &lt;code&gt;.xip&lt;/code&gt; file to &lt;em&gt;finally&lt;/em&gt; finish extracting. The FOMO becomes more real with the second.&lt;/p&gt;

&lt;p&gt;Just breathe. Take a moment, and breathe.&lt;/p&gt;

&lt;p&gt;The Xcode betas aren't going anywhere. You'll have plenty of time to mess around with new APIs if you want to. Because even though it looks like everybody is exploring all the new things in depth within seconds of the first betas becoming available, a lot of us are much, much slower. In fact, I'd say a majority of us are not on top of everything all the time, and you don't have to be either.&lt;/p&gt;

&lt;p&gt;Sit back, breathe, and proceed at a comfortable pace.&lt;/p&gt;

&lt;p&gt;You'll find that breathing, and taking it easy are a recurring theme in this guide. That's because it's important that you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 2: Figure out what's relevant to you
&lt;/h2&gt;

&lt;p&gt;When you keep an eye on Twitter throughout the week of WWDC you'll find that everybody is talking about the latest and greatest. For WWDC 2021 I'm sure everybody's going to be all over what's new in SwiftUI, Swift 5.5's async/await, and whatever other new and exciting frameworks and APIs Apple releases.&lt;/p&gt;

&lt;p&gt;Personally, I love exploring the new things too. It's new, it's fresh, it's exciting. But let's be honest; it's completely irrelevant for most of us in the short term. Apple isn't going to officially release anything they announce until more than three months later, so while it's fun to explore new things, it's not likely that you'll need to be aware of everything.&lt;/p&gt;

&lt;p&gt;Whenever I'm going through WWDC content I try to focus on two types of sessions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The super interesting sessions on new technology (for fun)&lt;/li&gt;
&lt;li&gt;Sessions that cover best practices or advances in technologies I'm already familiar with&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's right, I love watching sessions on stuff that's not new at all. Sometimes these sessions don't even involve any new features and instead cover (usually undocumented) tips, tricks, and best practices that I can incorporate into my work almost immediately. These sessions are most exciting to me because they are most relevant to me in the short term.&lt;/p&gt;

&lt;p&gt;So when you're in doubt about which sessions to watch, I would recommend to focus on what's relevant to you at the time rather than a new technology that everybody on the internet seems to be all over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 3: Move at a comfortable pace
&lt;/h2&gt;

&lt;p&gt;I can't stress it enough; that firehose of content that Apple unleashes during WWDC is intimidating. Apple will upload dozens of videos and each one will look more attractive than the other. You might feel the pressure to watch as many videos during the day as you can. Heck, you might even be so excited that it's excitement that drives you. And my advice to you is that you don't give in to that urge.&lt;/p&gt;

&lt;p&gt;Watch videos in a pace that is comfortable to you. If you're going over more than a couple of topics in the timespan of a few hours there's a good chance the contents won't really stick, and you'll be too tired to explore the APIs you've just learned about.&lt;/p&gt;

&lt;p&gt;Move at a pace that is comfortable to you. If that means watching two videos a day and spending a few hours exploring in code, then that's exactly what you should do. If you prefer watching more videos and not exploring until later,that's fine too! And if you want to skip the videos and just code all day long, guess what? All good!&lt;/p&gt;

&lt;p&gt;The videos aren't going anywhere for a long time. Watch them as needed. Maybe even pick a few videos from last year's WWDC if they're referred to from one of this year's videos. It's your choice.&lt;/p&gt;

&lt;p&gt;WWDC is not a race, so focus on having fun with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 4: Don't skip the State of the Union
&lt;/h2&gt;

&lt;p&gt;If you've ever attended an in-person WWDC you'll know that the main keynote that starts at 10AM PDT on the Monday of WWDC is the main event. People get in line for a good seat early in the morning; some even start queueing at 11PM the day before. It's where we see a first glimpse of all the goodness we'll get to learn more about in the week to come. However, as a developer this main event is probably not the most interesting first day presentation you can watch.&lt;/p&gt;

&lt;p&gt;After the main Keynote event, at 2PM PDT, there's a presentation called State of the Union. This presentation is the one to look out for as a developer in my opinion. It's where Apple will dig deeper into the APIs and Frameworks that were introduced, and they'll show off new OS features in-depth.&lt;/p&gt;

&lt;p&gt;I know that a lot of developers skip the State of the Union in favor of playing with new APIs and resting up, but I personally love watching the State of the Union. It usually gets me much more pumped up for all the good stuff than the main Keynote does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 5: Prepare for your lab sessions
&lt;/h2&gt;

&lt;p&gt;WWDC is a unique chance for developers to ask questions to Apple engineers directly. Once WWDC is underway we have the opportunity to request appointments with Apple engineers, and we can show them our projects and ask for input on ways to improve our code, solve bugs, or even just clarify how certain things are supposed to work. Labs is arguably the most valuable part of WWDC, so when WWDC went online last year it was a relieve to see that labs were brought online too. And this year is no different.&lt;/p&gt;

&lt;p&gt;When you book a lab appointment, try to make sure you come as prepared as possible. If you want to ask about (what you believe to be) a missing feature, or a bug, make sure you file feedback in Apple's &lt;a href="https://feedbackassistant.apple.com"&gt;feedback assistant&lt;/a&gt; ahead of time. This will make it so your lab session can be associated with the feedback which makes the Apple engineer's job a lot easier. It'll also allow the engineer to pull up your feedback ahead of time.&lt;/p&gt;

&lt;p&gt;Possibly more important than filing feedback is that you make sure you have a demo project ready to show off. If your lab starts and you have to work your way through your full codebase, it will make it harder for you and the engineer to work through your question, and potentially fix your problem. &lt;/p&gt;

&lt;p&gt;A bare-bones example of what you need will improve this a lot, and will help you make the most out of your lab appointment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip 6: File feedback
&lt;/h2&gt;

&lt;p&gt;This tip applies mostly to the period after WWDC. Once WWDC is over and we start spending actual time with new APIs, and we start testing our own apps on the latest Xcode version, bug will start showing themselves. Presented APIs might be missing features that you'd love to have, iOS 15 might do interesting things to your app, or maybe Xcode 13 crashes every time you do something specific.&lt;/p&gt;

&lt;p&gt;No matter what your feedback is, file it as soon as you can.&lt;/p&gt;

&lt;p&gt;Don't expect that others will already have filed your feedback. Even if they have, the more duplicates Apple gets, the more likely it is that your feedback is eventually bumped to the top of the list. This means that it's more likely that your bugs get fixed, and that your feature requests get implemented when you file your feedback.&lt;/p&gt;

&lt;p&gt;I know that Apple has a history of not always responding to feedback, and that it can be very time consuming to file feedback. But if there is a perfect time for you to do it, it's during the big beta cycle that starts with WWDC.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;WWDC is a hectic time for everybody. I think it's most important that you focus on taking it easy, not giving in to that fear of missing out, and not trying to learn everything in one week. Consume WWDC content at your own pace, and focus on what's relevant to you unless it's simply something you're super interested in even though it might not be something that you can apply in your work just yet.&lt;/p&gt;

&lt;p&gt;I hope that these tips help you make the most of your WWDC experience, and that you'll be able to enjoy this WWDC as much as I've always enjoyed mine!&lt;/p&gt;

</description>
      <category>wwdc2021</category>
      <category>ios</category>
      <category>swift</category>
    </item>
    <item>
      <title>Formatting dates in the user's locale using DateFormatter in Swift</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Thu, 15 Oct 2020 12:20:29 +0000</pubDate>
      <link>https://forem.com/donnywals/formatting-dates-in-the-user-s-locale-using-dateformatter-in-swift-5ee6</link>
      <guid>https://forem.com/donnywals/formatting-dates-in-the-user-s-locale-using-dateformatter-in-swift-5ee6</guid>
      <description>&lt;p&gt;Working with dates is hard, there is no doubt about that. And formatting dates properly for every user of your app is no easier (if you want to do everything manually). Luckily, the system can help us.&lt;/p&gt;

&lt;p&gt;For example, in the US one would write &lt;strong&gt;"October 15"&lt;/strong&gt; while in The Netherlands we write &lt;strong&gt;15 oktober&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Note that the order of the date and the month is different, the spelling of the month is different and the capitalization is different too.&lt;/p&gt;

&lt;p&gt;The DateFormatter in iOS will handle a lot of this for you. For example, if you'd use the following code on a device that uses &lt;code&gt;nl&lt;/code&gt; as its locale you would see the output that I added to this snippet as a comment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DateFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dateFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dd MMMM"&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 15 oktober&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of this code is spot on. Exactly what we need and it matches the specified date format perfectly. If you'd run the same code on a device that uses &lt;code&gt;en_us&lt;/code&gt; as its locale the output would be &lt;strong&gt;15 October&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The date formatter got the spelling and capitalization right but the date and month are in the wrong order.&lt;/p&gt;

&lt;p&gt;You can fix this by using &lt;code&gt;setLocalizedDateFormatFromTemplate&lt;/code&gt; on your date formatter instead of assigning its &lt;code&gt;dateFormat&lt;/code&gt; directly. Let's look at an example that runs on a device with &lt;code&gt;nl&lt;/code&gt; as its locale again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DateFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLocalizedDateFormatFromTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dd MMMM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 15 oktober&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That still works, perfect. If you'd run this code on an &lt;code&gt;en_us&lt;/code&gt; device the output would be &lt;strong&gt;October 15&lt;/strong&gt;. Exactly what we need.&lt;/p&gt;

&lt;p&gt;If you want to play around with &lt;code&gt;setLocalizedDateFormatFromTemplate&lt;/code&gt; in a Playground you can give it a go with the following code that uses a date formatter in different locales:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DateFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"en_us"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLocalizedDateFormatFromTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dd MMMM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// October 15&lt;/span&gt;

&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"nl"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLocalizedDateFormatFromTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dd MMMM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 15 oktober&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have questions about this Quick Tip, or if you want to reach out to me for other reasons then don't hesitate to send me a message on &lt;a href="https://twitter.com/donnywals"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's a good thing that Swift and Foundation can handle these kinds of &lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
    </item>
    <item>
      <title>I wrote a book about Apple's Combine framework</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Fri, 27 Mar 2020 11:07:20 +0000</pubDate>
      <link>https://forem.com/donnywals/i-wrote-a-book-about-apple-s-combine-framework-388h</link>
      <guid>https://forem.com/donnywals/i-wrote-a-book-about-apple-s-combine-framework-388h</guid>
      <description>&lt;p&gt;After writing a series of posts about Combine on &lt;a href="https://donnywals.com/category/combine"&gt;my blog&lt;/a&gt; I figured a more complete, comprehensive resource that teaches Combine from a practical standpoint would be nice.&lt;/p&gt;

&lt;p&gt;My book teaches Combine using real-world examples because I love learning by doing, and seeing how my new skills will fit into my existing workflow. I did my best to ensure that the book I wrote fits this style of learning. &lt;/p&gt;

&lt;p&gt;Everything I show in my book is backed up by examples and anecdotes of how and when something is useful, and most imprtantly, why.&lt;/p&gt;

&lt;p&gt;Learn more about my book on &lt;a href="https://practicalcombine.com"&gt;practicalcombine.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
    </item>
    <item>
      <title>Reading and writing Property List files with Codable in Swift</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Wed, 04 Mar 2020 09:31:11 +0000</pubDate>
      <link>https://forem.com/donnywals/reading-and-writing-property-list-files-with-codable-in-swift-4d1k</link>
      <guid>https://forem.com/donnywals/reading-and-writing-property-list-files-with-codable-in-swift-4d1k</guid>
      <description>&lt;p&gt;You have probably seen and used a property list file at some point in your iOS journey. I know you have because every iOS app has an &lt;code&gt;Info.plist&lt;/code&gt; file. It's possible to create and store your own &lt;code&gt;.plist&lt;/code&gt; files to hold on to certain data, like user preferences that you don't want to store in &lt;code&gt;UserDefaults&lt;/code&gt; for any reason at all. In this week's Quick Tip you will learn how you can read and write data from and to property list files using Swift's &lt;code&gt;Codable&lt;/code&gt; protocol.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining a model that can be stored in a property list
&lt;/h2&gt;

&lt;p&gt;Because Swift has special &lt;code&gt;PropertyListEncoder&lt;/code&gt; and &lt;code&gt;PropertyListDecoder&lt;/code&gt; objects, it's possible to define the model that you want to store in a property list using &lt;code&gt;Codable&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;APIPreferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Codable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This model is trivial but you can create far more complex models if you want. Any model that conforms to &lt;code&gt;Codable&lt;/code&gt; can be used with property lists. If you haven't worked with &lt;code&gt;Codable&lt;/code&gt; before, check out &lt;a href="https://www.avanderlee.com/swift/json-parsing-decoding/"&gt;this post&lt;/a&gt; from my Antoine van der Lee to get yourself up to speed. His post is about JSON parsing, but everything he writes about defining models applies to property lists as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading a model from a property list
&lt;/h2&gt;

&lt;p&gt;We can load plist files from the filesystem using the &lt;code&gt;FileManager&lt;/code&gt; object. Let's dive right in with some code; this is a Quick Tip after all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;APIPreferencesLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;plistURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URL&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;documentDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userDomainMask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendingPathComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api_preferences.plist"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;APIPreferences&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;PropertyListDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;contentsOf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plistURL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;preferences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;APIPreferences&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;APIPreferences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;preferences&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I defined a simple class here because this allows me to use the &lt;code&gt;APIPreferenceLoader&lt;/code&gt; in a brief example at the end of this post.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;plistURL&lt;/code&gt; describes the location of the property list file on the file system. Since it's a file that we want to create and manage at runtime, it needs to be stored in the documents directory. We could store an initial version of the &lt;code&gt;plist&lt;/code&gt; file in the bundle but we'd always have to copy it over to the documents directory to update it later because the bundle is read-only. You might use the following code to perform this copy step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;APIPreferencesLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;copyPreferencesFromBundle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Bundle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forResource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"api_preferences"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ofType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"plist"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;atPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fileExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;atPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plistURL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;atPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plistURL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code extracts the default preferences from the bundle and checks whether a stored property list exists in the documents directory. If no file exists in the documents directory, the data that was extracted from the bundled property list is copied over to the path in the documents directory so it can be modified by the application later.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;load()&lt;/code&gt; method from the initial code sample uses a &lt;code&gt;PropertyListDecoder&lt;/code&gt; to decode the data that's loaded from the property list in the bundle into the &lt;code&gt;APIPreferences&lt;/code&gt; model. If you're familiar with decoding JSON in Swift, this code should look familiar to you because it's the exact same code! Convenient, isn't it?&lt;/p&gt;

&lt;p&gt;If we couldn't load the property list in the documents directory, or if the decoding failed, &lt;code&gt;load()&lt;/code&gt; returns an empty object by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing a model to a property list
&lt;/h2&gt;

&lt;p&gt;If you have a model that conforms to &lt;code&gt;Codable&lt;/code&gt; as I defined in the first section of this tip, you can use a &lt;code&gt;PropertyListEncoder&lt;/code&gt; to encode your model into data, and you can use &lt;code&gt;FileManager&lt;/code&gt; to write that data to a plist file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;APIPreferencesLoader&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;APIPreferences&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;PropertyListEncoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fileExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;atPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plistURL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Update an existing plist&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plistURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Create a new plist&lt;/span&gt;
        &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;atPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plistURL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code checks whether our property list file exists in the documents directory using the &lt;code&gt;plistURL&lt;/code&gt; that I defined in an earlier code snippet. If this file exists, we can simply write the encoded model's data to that file and we have successfully updated the property list in the documents directory. If the property list wasn't found in the documents directory, a new file is created with the encoded model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying out the code from this post
&lt;/h2&gt;

&lt;p&gt;If you've been following along, you can try the property list reading and writing quite easily with SwiftUI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ContentView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;@State&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;preferences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;APIPreferencesLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API Key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;preferences&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kt"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"baseURL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;preferences&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kt"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;APIPreferencesLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you enter some data in the text fields and press the update button, the data you entered will be persisted in a property list that's written to the document directory. When you run this example on your device or in the simulator you will find that your data is now persisted across launches.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;Because Swift contains a &lt;code&gt;PropertyListEncoder&lt;/code&gt; and a &lt;code&gt;PropertyListDecoder&lt;/code&gt; object, it's fairly simple to create models that can be written to a property list in Swift. This is especially true if you're already familiar with &lt;code&gt;Codable&lt;/code&gt; and the &lt;code&gt;FileManager&lt;/code&gt; utility. If you're not very experienced with these technologies, I hope that this Quick Tip provided you with some inspiration and ideas of what to look for, and what to explore.&lt;/p&gt;

&lt;p&gt;If you have any feedback about this tip, or if you want to reach out to me don't hesitate to send me a &lt;a href="https://twitter.com/donnywals"&gt;tweet&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
    </item>
    <item>
      <title>How to sort an Array based on a property of an element in Swift</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Tue, 25 Feb 2020 14:33:11 +0000</pubDate>
      <link>https://forem.com/donnywals/how-to-sort-an-array-based-on-a-property-of-an-element-in-swift-481e</link>
      <guid>https://forem.com/donnywals/how-to-sort-an-array-based-on-a-property-of-an-element-in-swift-481e</guid>
      <description>&lt;p&gt;The easiest way to sort an Array in Swift is to use the &lt;code&gt;sort&lt;/code&gt; method. This method is available for all Arrays that have &lt;code&gt;Equatable&lt;/code&gt; elements and it sorts your array in place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"this"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"of"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"strings"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// words is now ["a", "hello", "is", "list", "of", "strings", "this", "world"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This modifies the input Array and sorts its elements using &lt;code&gt;String&lt;/code&gt; conformance to &lt;code&gt;Equatable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But what if you want to sort the Array based on the length of each string? Or what if you want to sort an Array whose elements aren't &lt;code&gt;Equatable&lt;/code&gt;? Or maybe you have a list of objects that have an &lt;code&gt;id&lt;/code&gt; property and you want to sort by &lt;code&gt;id&lt;/code&gt;, or maybe you want to sort blog posts by date?&lt;/p&gt;

&lt;p&gt;You can achieve this using Array's &lt;code&gt;sort(by:)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"this"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"of"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"strings"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// words is ["a", "is", "of", "this", "list", "hello", "world", "strings"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use any kind of comparison logic in the closure that you pass to &lt;code&gt;sort(by:)&lt;/code&gt;. In this example, I used &lt;code&gt;count&lt;/code&gt; which is a property of &lt;code&gt;String&lt;/code&gt; to sort my Array by string length.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;sort()&lt;/code&gt; and &lt;code&gt;sort(by:)&lt;/code&gt; both modify the source Array in-place. If you don't want to modify the source and create a new Array instead, you can use &lt;code&gt;sorted()&lt;/code&gt; or &lt;code&gt;sorted(by:)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"this"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"of"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"strings"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// sorted is ["a", "is", "of", "this", "list", "hello", "world", "strings"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any questions about this tip, or if you have feedback for me, don't hesitate to send me a &lt;a href="https://twitter.com/donnywals"&gt;Tweet&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
    </item>
    <item>
      <title>Working with throwing functions in Swift</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Mon, 24 Feb 2020 08:25:09 +0000</pubDate>
      <link>https://forem.com/donnywals/working-with-throwing-functions-in-swift-4nol</link>
      <guid>https://forem.com/donnywals/working-with-throwing-functions-in-swift-4nol</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on my &lt;a href="https://www.donnywals.com/the-blog/"&gt;blog&lt;/a&gt;. You can read it in its original form &lt;a href="https://www.donnywals.com/working-with-throwing-functions-in-swift/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Swift 2.0, Apple introduced the &lt;code&gt;throws&lt;/code&gt; keyword in Swift. This addition to Swift language added the ability for developers to write code that clearly communicates that an error might occur during the execution of a code path, and it forces the caller of that code to handle, or explicitly ignore the error in-place. In this post I will show you what the &lt;code&gt;throws&lt;/code&gt; keyword is exactly, and how you can deal with errors in your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with code that throws errors
&lt;/h2&gt;

&lt;p&gt;If you've worked with &lt;code&gt;JSONDecoder&lt;/code&gt; in Swift, you have already experienced code that can throw an error. Let's look at a quick example to refresh your mind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello, world"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;using&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JSONDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is a very basic example of how you can work with code that might throw an error. When you call a function that can throw an error, you must prefix this invocation with the &lt;code&gt;try&lt;/code&gt; keyword. You can't just do this anywhere. Calling out to code that might throw an error must occur in a &lt;code&gt;do {} catch {}&lt;/code&gt; block. The &lt;code&gt;try&lt;/code&gt; prefixed code must be in the &lt;code&gt;do&lt;/code&gt; portion of the block. You can have more than one &lt;code&gt;try&lt;/code&gt; prefixed method call in a single &lt;code&gt;do&lt;/code&gt; block. When any of those method calls throws an error, execution is immediately moved to the &lt;code&gt;catch&lt;/code&gt; part. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;catch&lt;/code&gt; block receives a single argument, which is the &lt;code&gt;Error&lt;/code&gt; that was thrown in your &lt;code&gt;do&lt;/code&gt; block. In Swift, &lt;code&gt;Error&lt;/code&gt; is a protocol that is used to represent errors. It's possible to specialize your &lt;code&gt;catch&lt;/code&gt; block to make it catch only a specific kind of error. If you do this, you still need a general purpose &lt;code&gt;catch&lt;/code&gt; that will catch all other &lt;code&gt;Error&lt;/code&gt; types. Let's look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello, world"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;using&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JSONDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kt"&gt;DecodingError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong while decoding!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use pattern matching to specialize catch clauses for an entire category of errors, or a specific error (&lt;code&gt;catch is MyError.someCase&lt;/code&gt;). Doing this can be convenient if you have special handling paths for certain errors, but you do lose access to the original error. The final catch-all is invoked if none of the specialized &lt;code&gt;catch&lt;/code&gt; blocks match the thrown error.&lt;/p&gt;

&lt;p&gt;There are cases when you might make the decision that you don't want to handle any thrown errors. In these cases, you can use the &lt;code&gt;try?&lt;/code&gt; prefix instead of &lt;code&gt;try&lt;/code&gt;. When you call a throwing function with &lt;code&gt;try?&lt;/code&gt;, the function's return type becomes an &lt;code&gt;Optional&lt;/code&gt; that's &lt;code&gt;nil&lt;/code&gt; when an error was thrown. Let's look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;myErrorCase&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myErrorCase&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is pretty worthless in a real codebase, but it illustrates my point nicely. The &lt;code&gt;doSomething()&lt;/code&gt; function doesn't return anything. This means that it returns &lt;code&gt;Void&lt;/code&gt;, which can also be written as an empty tuple (&lt;code&gt;()&lt;/code&gt;). The printed result of this code is &lt;code&gt;nil&lt;/code&gt;. If you comment out the &lt;code&gt;throw&lt;/code&gt; line from &lt;code&gt;doSomething()&lt;/code&gt;, the printed output is &lt;code&gt;Optiona(())&lt;/code&gt;. In other words, an optional with &lt;code&gt;Void&lt;/code&gt; as its value. If a function has a return value and you call it with &lt;code&gt;try?&lt;/code&gt;, the result is also optional. Let's look at another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello, world"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;using&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JSONDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run this code in a Playground, you'll find that the printed value is &lt;code&gt;nil&lt;/code&gt;. The provided data isn't valid JSON, so it fails to decode. But because we call &lt;code&gt;decoder.decode(_:from:)&lt;/code&gt; with &lt;code&gt;try?&lt;/code&gt;, the error is hidden and &lt;code&gt;decode(_:from:)&lt;/code&gt; returns an optional value instead of its normal non-optional value.&lt;/p&gt;

&lt;p&gt;If you call a throwing function that returns an optional with &lt;code&gt;try?&lt;/code&gt;, you might expect a nested optional to be returned. After all, the function itself returns an optional and the return type of a throwing function is wrapped by an optional when you call it with &lt;code&gt;try?&lt;/code&gt;. This means that a function that returns &lt;code&gt;String&lt;/code&gt; returns &lt;code&gt;String?&lt;/code&gt; when you call it with &lt;code&gt;try?&lt;/code&gt;. However, if you call a function that returns &lt;code&gt;String?&lt;/code&gt;, it doesn't return &lt;code&gt;String??&lt;/code&gt;. Swift will automatically work around this nested optional, which is both a blessing and a curse. Consider the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;returnsOptionalString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// why is string nil? Is it due to an error? Or did the function execute successfully and we just got back nil without encountering any errors?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the code above might be more convenient to write than a &lt;code&gt;do {} catch {}&lt;/code&gt; block, you lose all error-related information. And in cases where code returns an optional, you don't whether you received &lt;code&gt;nil&lt;/code&gt; because of an error. You should only use &lt;code&gt;try?&lt;/code&gt; if you truly don't care about handling errors, or knowing whether an error occurred at all.&lt;/p&gt;

&lt;p&gt;There is one more way to deal with code that can throw errors. You can use &lt;code&gt;try!&lt;/code&gt; in cases where you're absolutely sure that your code shouldn't throw an error, and you want your app to crash if it does. This flavor of &lt;code&gt;try&lt;/code&gt; should be used sparingly, and preferably not at all. Let's look at one last example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;myErrorCase&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myErrorCase&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;try!&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code would crash at runtime. &lt;code&gt;doSomething()&lt;/code&gt; always throws an error, and by calling it with the &lt;code&gt;try!&lt;/code&gt; prefix we tell Swift that we don't expect &lt;code&gt;doSomething()&lt;/code&gt; to actually throw an error. And when it does, execution of the program should halt, and the app should crash. This is quite radical and, again, should be used sparingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Throwing errors in your own code
&lt;/h2&gt;

&lt;p&gt;Sometimes, the code you write needs a way to express that something went wrong and execution of that code path needs to stop immediately with an error. If the error is recoverable, you might have a good candidate for a throwing function on your hands. When I say that an error is recoverable, I mean that the error didn't occur due to a programming error (like accessing an out of bounds index in an array for example) and that the program isn't in an unexpected or invalid state. It might simply mean that &lt;em&gt;something&lt;/em&gt; went wrong.&lt;/p&gt;

&lt;p&gt;For example, when you try to decode invalid JSON using a &lt;code&gt;JSONDecoder&lt;/code&gt;, that's not considered an error that's severe enough to crash the app. Instead, an error is thrown to let you know that something went wrong. This is an important distinction, and trying to decode invalid JSON should never crash the application. At least not in the &lt;code&gt;JSONDecoder&lt;/code&gt;. You're free to crash your app is a decoding error occurs if you want but I'd strongly advise you not to. Especially if you're loading JSON from a webserver.&lt;/p&gt;

&lt;p&gt;When you're writing your own code, you might want to throw an error of your own. You already saw how to do this in the previous section in the &lt;code&gt;doSomething&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myErrorCase&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Functions that can throw an error &lt;strong&gt;must&lt;/strong&gt; have the &lt;code&gt;throws&lt;/code&gt; keyword appended to their signature, before the return type. Here's what a function signature for a throwing function with a return type looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;returnsOptionalString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do work&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're writing code in a so-called throwing function, you can call methods that throw errors without using a &lt;code&gt;do {} catch {}&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;decodeJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JSONDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;decodedString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;decodedString&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is okay because Swift knows that &lt;code&gt;decodeJSON(_:)&lt;/code&gt; might encounter and throw an error. When the JSON decoding fails in this function, the thrown error is passed up to the called of &lt;code&gt;decodeJSON&lt;/code&gt; because it's marked as throwing with the &lt;code&gt;throws&lt;/code&gt; keyword. When this function is called from another function that's throwing, that function will also forward the error up to its caller. The error will be passed up all the way to a caller that's not part of a throwing function. &lt;/p&gt;

&lt;p&gt;There is one more error throwing related keyword that I want to show you. It's called &lt;code&gt;rethrows&lt;/code&gt;. The &lt;code&gt;rethrows&lt;/code&gt; keyword is used for functions that don't &lt;em&gt;directly&lt;/em&gt; throw an error. Instead, the functions take a closure argument where the closure might throw instead of the function itself. Let's look at an example of a function that takes a throwing closure &lt;em&gt;without&lt;/em&gt; &lt;code&gt;rethrows&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;closure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="nf"&gt;closure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myErrorCase&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above I have defined an &lt;code&gt;execute&lt;/code&gt; function. This function takes a single closure argument, and all it does is execute the closure immediately. Nothing fancy. You'll see that both &lt;code&gt;execute(_:)&lt;/code&gt; and the closure it receives are marked with &lt;code&gt;throws&lt;/code&gt;. It's important to understand that marking a function as throwing does not mean that the function is guaranteed to throw an error. All we're saying is that it might. This is especially relevant for the closure argument. The closure that's passed might not even be capable of throwing an error, just like the first call to &lt;code&gt;execute(_:)&lt;/code&gt; in this example. Even though we know that this closure never throws an error, and the compiler also knows it, we must mark the call to &lt;code&gt;execute(_:)&lt;/code&gt; with &lt;code&gt;try&lt;/code&gt; because that function itself might throw an error.&lt;/p&gt;

&lt;p&gt;We can clean this code up a little bit by declaring &lt;code&gt;execute(_:)&lt;/code&gt; as rethrowing rather than throwing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;closure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;rethrows&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="nf"&gt;closure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myErrorCase&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;execute(_:)&lt;/code&gt; is now rethrowing, the Swift compiler can verify whether a code path might throw an error, and it will allow you to call &lt;code&gt;execute(_:)&lt;/code&gt; without &lt;code&gt;try&lt;/code&gt; if it can prove that the closure you passed to &lt;code&gt;execute(_:)&lt;/code&gt; doesn't throw an error. Quite neat right?&lt;/p&gt;

&lt;p&gt;You'll find &lt;code&gt;rethrows&lt;/code&gt; in several places in the Swift standard library. For example, &lt;code&gt;map(_:)&lt;/code&gt; is marked with &lt;code&gt;rethrows&lt;/code&gt; because the closure you supply to &lt;code&gt;map(_:)&lt;/code&gt; is allowed to throw errors if needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;mapped&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intLargerThanThree&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This probably isn't how you commonly use &lt;code&gt;map(_:)&lt;/code&gt; because typically the closure passed to this function doesn't throw. But now you know that you're allowed to throw errors while mapping, and you also know why you're not forced to mark every call to &lt;code&gt;map(_:)&lt;/code&gt; with &lt;code&gt;try&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Note that the execution of any throwing method or closure is halted immediately when an error is thrown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myErrorCase&lt;/span&gt;

  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is never printed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Throwing an error is a strong signal that something's wrong, and there's no point in fully executing the current code path. The error is sent to the caller of the throwing function, and it must be handled or forwarded from there. If you throw an error in a function that should return something, the function will not actually return anything. Instead, your code switches to the &lt;code&gt;catch&lt;/code&gt; part of the &lt;code&gt;do {} catch {}&lt;/code&gt; block immediately where you can handle the error. The exception here is when the called of your throwing function calls it with &lt;code&gt;try?&lt;/code&gt; or &lt;code&gt;try!&lt;/code&gt; like I explained in the previous section.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;In this post, I've shown you how you can deal with functions that can throw errors in Swift. You saw how you can call functions that are marked as throwing, how you can tell Swift you're not interested in handling an error and how you can tell Swift that you're absolutely sure a certain call will never actually throw an error at runtime.&lt;/p&gt;

&lt;p&gt;After that, I moved on to show you how you can throw errors from your own code, what the &lt;code&gt;rethrows&lt;/code&gt; keyword is and when it's useful.&lt;/p&gt;

&lt;p&gt;If you have any feedback for me about this post, or if you have any questions, don't hesitate to reach out to me on &lt;a href="https://twitter.com/donnywals"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
    </item>
    <item>
      <title>Testing push notifications in the Simulator with Xcode 11.4</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Thu, 13 Feb 2020 09:15:42 +0000</pubDate>
      <link>https://forem.com/donnywals/testing-push-notifications-in-the-simulator-with-xcode-11-4-ka7</link>
      <guid>https://forem.com/donnywals/testing-push-notifications-in-the-simulator-with-xcode-11-4-ka7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on &lt;a href="https://www.donnywals.com/the-blog"&gt;my blog&lt;/a&gt; where I publish weekly articles and tips.&lt;/p&gt;

&lt;p&gt;Xcode 11.4 is currently still in beta, keep in mind that you can't use this version of Xcode to ship apps to the store. Read my guide on &lt;a href="https://www/donnywals.com/installing-multiple-xcode-versions-with-xcversion/"&gt;installing multiple Xcode versions&lt;/a&gt; alongside each other if you want to play with the Xcode 11.4 beta while keeping your copy of 11.3.1 around as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For years we've had to resort to using physical devices when testing push notifications. With Xcode 11.4, Apple finally gives developers the tools needed to test push notifications on the iOS Simulator. I'm going to assume you already know how to add push notifications to your app. If you've never added push notifications to an app before, I have a post that describes &lt;a href="https://www.donnywals.com/testing-your-push-notifications-without-a-third-party-service/"&gt;how to set up and test push notifications without a third-party service&lt;/a&gt;. That post should get you all set up to follow along with this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending a test push from the command line
&lt;/h2&gt;

&lt;p&gt;Xcode comes with several command-line tools that allow you to run your tests, builds and other tasks directly from the Terminal in macOS. If you have Xcode installed, it should automatically install the command line tools on its first launch. If you've followed my guide on &lt;a href="https://www/donnywals.com/installing-multiple-xcode-versions-with-xcversion/"&gt;having multiple Xcode versions installed&lt;/a&gt;, make sure to select Xcode 11.4 or newer by running &lt;code&gt;xcversion select 11.4&lt;/code&gt; and replace 11.4 with the version of Xcode you want to use. Doing this will make sure the Xcode command line tools point to the correct toolchain.&lt;/p&gt;

&lt;p&gt;When you have an iOS 13.4 or newer simulator running, all you need to send a push notification is an apns notification payload. The payload should look similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Simulator Target Bundle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.donnywals.SilentPushDemo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"aps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"alert"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Push on the simulator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"So cool..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This notification is going to show up in the simulator!"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The formatting of the push notification is the same as it would be when you send it from a server to a device. The only exception is the &lt;code&gt;"Simulator Target Bundle"&lt;/code&gt; top-level key. This key should not be present in push notifications that you send from a production server. To send this push notification, you can run the following terminal command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcrun simctl push booted test_push.apns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will send a test push notification to all booted simulators. The last argument passed to this command is the path to the file that contains the test push notification. In this case, it's a file called &lt;code&gt;test_push.apns&lt;/code&gt; which exists in the directory as the one I'm running the command from.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;"Simulator Target Bundle"&lt;/code&gt; can be omitted from the file, but then the terminal command would be slightly different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcrun simctl push booted &amp;lt;your-bundle-identifier&amp;gt; test_push.apns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you don't include your app's bundle identifier in the payload, you need to specify the bundle identifier of the receiving app in the command. Make sure you replace &lt;code&gt;&amp;lt;your-bundle-identifier&amp;gt;&lt;/code&gt; with the receiving application's bundle identifier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending a test push notification without the command line
&lt;/h2&gt;

&lt;p&gt;If you're not comfortable using the command line to send a test push, you can also drag your test push notification directly to the simulator to have it delivered to that specific simulator immediately.&lt;/p&gt;

&lt;p&gt;When doing this, make sure your file has &lt;code&gt;.apns&lt;/code&gt; as its extension, and it must include the &lt;code&gt;"Simulator Target Bundle"&lt;/code&gt; top-level key so the simulator knows which application should receive your test push.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;The ability to test push notifications in the simulator is a feature that iOS developers have wanted for a very long time, and I think that it's great that Apple has finally provided us with this ability. Especially because they managed to make the process so straightforward by keeping everything local to the machine you're developing on.&lt;/p&gt;

&lt;p&gt;If you want to test with notifications that are actually generated and sent from your server, you still need to use a physical device because the simulator doesn't support true remote notifications just yet. However, I think this is a great step in the right direction and I'm sure I will use this feature regularly.&lt;/p&gt;

&lt;p&gt;If you have any questions or feedback for me, make sure to reach out on &lt;a href="https://twitter.com/donnywals"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Five ways to get better at receiving feedback</title>
      <dc:creator>Donny Wals</dc:creator>
      <pubDate>Wed, 05 Feb 2020 09:09:45 +0000</pubDate>
      <link>https://forem.com/donnywals/five-ways-to-get-better-at-receiving-feedback-5hi7</link>
      <guid>https://forem.com/donnywals/five-ways-to-get-better-at-receiving-feedback-5hi7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was originally posted on &lt;a href="https://www.donnywals.com"&gt;my blog&lt;/a&gt; and can be read &lt;a href="https://www.donnywals.com/five-ways-to-get-better-at-receiving-feedback/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I just started my career as a developer there was a lot I didn't know yet. There also were a lot of things I didn't understand or had never done before. I have always been lucky enough to work in places where I was able to learn and grow as needed, and most importantly, I was allowed to make mistakes. One of the hardest things wasn't that I was constantly learning and figuring out. That actually was the fun part! The hard bit was often receiving feedback.&lt;/p&gt;

&lt;p&gt;Whether it was feedback from clients, coworkers or teachers back in college. Something about getting feedback and learning about things I didn't get quite right, could have done better or differently always felt like it was some kind of an attack. You could argue that the feedback should have been delivered differently if that's the case, but the feedback usually was good and constructive. I just wasn't very good at receiving feedback. &lt;/p&gt;

&lt;p&gt;Just like giving feedback, being able to receive it is a skill. It's something you learn to get better at over time. And in this week's quick tip I would like to leave you with a couple of lessons that I have learned over the years about receiving feedback in a productive, and positive manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Listen, don't defend
&lt;/h2&gt;

&lt;p&gt;Something that I often found myself doing when I received feedback was coming up with counter-arguments or a defense against the feedback I was receiving. If somebody told me my code could have been better, I would tell them that my code was fine as it is. Or if somebody would point out that a specific animation wasn't quite right, I would immediately tell them that this was as good as it was going to get.&lt;/p&gt;

&lt;p&gt;Not only does this make the feedback process very frustrating for both parties involved, but it also chips away from your credibility over time. When you tell somebody something can't be done, and a more senior developer helps you to it done anyway, that doesn't reflect too good on you as the receiver of feedback. &lt;/p&gt;

&lt;p&gt;It's much better to listen carefully to the feedback you're receiving. Or if the feedback is delivered via an email, Jira ticket, code review or any other digital medium, read it carefully. Don't think about any counter-arguments just yet. Just soak up whatever feedback you're getting, no matter how wrong you think it is at the time of receiving it. Especially if the feedback is delivered to you carefully and properly, you can rest assured that the person giving you feedback has the best intentions and wants to ship a fantastic product, just like you.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Let the feedback sink in
&lt;/h2&gt;

&lt;p&gt;After listening to the feedback, or reading it all, it's very tempting to begin formulating a response immediately. Try not to do this. When you receive feedback that requires you to make a bunch of changes, or if you need to fix something you don't quite understand, or even think is impossible, chances are that your initial response is quite emotional. You worked really hard and now somebody is telling you that you didn't do a perfect job, of course you're not thrilled about that. That's normal.&lt;/p&gt;

&lt;p&gt;It's important to let feedback sink in for a moment, let your initial knee-jerk reaction subside before you respond. I distinctly remember sending a few too many emails back to coworkers and even clients with very well thought out responses explaining why I did what I did, and why I didn't their feedback was justified, only to regret it hours later. I knew they were right, for some reason I just felt the need to explain myself and justify my work to the person giving me feedback. If I had waited an hour or so before responding, I probably would have seen things very differently, and my responses would have been different too.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Don't take it personally
&lt;/h2&gt;

&lt;p&gt;This tip has been a game-changer for me. For the longest time, I took feedback personally. If somebody pointed out that an animation wasn't smooth, or that a label is misaligned it felt as if they were critiquing &lt;em&gt;me&lt;/em&gt;. All I would hear is that I didn't do a good enough job implementing a design, or that my coding isn't good enough. Detaching yourself from your work is really hard, but I found that it makes receiving feedback a lot easier.&lt;/p&gt;

&lt;p&gt;If feedback is given well, it never is an attack on you. It does not even critique on you as a person. It's an objective look at the work that was delivered. In the end, the purpose of giving and receiving feedback is to create a better product. Designers do their best to create a beautiful design, and as a developer, you try to do justice to this design while writing good code. The whole teams wants this project to succeed. So when somebody points out a flaw in the product, they are doing just that. They are not pointing out a flaw &lt;em&gt;you made&lt;/em&gt;. They are looking at the product and pointing out a flaw in the &lt;em&gt;product&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In a professional environment, nobody should be out to get you. Remember that.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Ask for more information if needed
&lt;/h2&gt;

&lt;p&gt;Sometimes, feedback isn't delivered very well. Key information is missing, or you don't understand what somebody means. It's easy to bounce this kind of feedback off and ignore it. It's one less thing on your todo list. Unfortunately, this almost never works. The person providing feedback to you obviously cared enough to give this feedback to you. If it's not clear, ask for more information. Ask the person that gave you feedback to explain themselves.&lt;/p&gt;

&lt;p&gt;This also applies in scenarios where you don't understand why somebody gave you certain feedback. If you're asked to refactor something in a code review but you don't understand why, you'll probably comply reluctantly. Instead, try asking this person for more information. Why do they want you to refactor? What do you gain from it? When you understand the why, implementing the feedback suddenly isn't so bad.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Ask for help
&lt;/h2&gt;

&lt;p&gt;In my career, I have often ignored this advice. When receiving feedback, I would often explain why I did what I did, and why changing my work to address the feedback was either impossible or would take a tremendous amount of time. Being a junior developer with just a year or two experience, that's a bold statement to make. When you get feedback from a more senior developer, or designer asking you to improve something, chances are that they know that it can be done.&lt;/p&gt;

&lt;p&gt;If this happens to you, don't jump into defense mode immediately. Instead, ask for help. Walk up to a coworker, your team lead or even the person giving you feedback and explain that you want to address their feedback but aren't quite sure how. You did a ton of research but couldn't figure out how to achieve the desired result. Doing this is &lt;em&gt;good&lt;/em&gt;. There is no shame in admitting that you don't know how to do something and asking for help. It's much better to be honest when you're not sure about something and asking for help than it is to make a bold claim saying that something can't be done, only to be proven wrong later. That's not good for your self-esteem, and it also harms your credibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;Receiving feedback can be hard. Especially if you're not very experienced yet. I hope that this post has given you some good tips to help you get better at receiving feedback. These tips are all derived from my own experiences as a developer over the past years and they really helped me grow as a developer.&lt;/p&gt;

&lt;p&gt;If you have any questions about this post for me, or if you want to share your experiences with receiving feedback, don't hesitate to reach out on &lt;a href="https://twitter.com/donnywals"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
    </item>
  </channel>
</rss>
