{
    "version": "https://jsonfeed.org/version/1",
    "title": "Natan Rolnik’s blog",
    "description": "My thoughts on iOS development, programming (mostly, but not exclusively, on Apple platforms) design, and other bits of technology, judaism, and life in general.",
    "home_page_url": "https://blog.natanrolnik.me/",
    "feed_url": "https://blog.natanrolnik.me/feed.json",
    "author": {
        "name": "Natan Rolnik", "url": "https://natanrolnik.me", "avatar": "https://gravatar.com/avatar/c7af4f539e54c0c2b159b8d35c506306?s=500"},
    "items": [
      {
            "id": "https://blog.natanrolnik.me/Swift-Toolkit-launch",
            "url": "https://blog.natanrolnik.me/swift-toolkit-launch",
            "title": "Launching SwiftToolkit.dev",
            "content_html": "<p>I’m thrilled to announce that during the the past few months, I’ve been working on a new website: <a href=\"https://SwiftToolkit.dev\">SwiftToolkit.dev</a>. The goal is to share tutorials, guides, cheatsheets and other resources that can be helpful in the tooling, developer experience, and server side Swift domains.</p>\n\n<p>Although there were some unexpected bumps along the way - a devastating ongoing war since October 7th and the loss of a close family member - I finally published the first posts, and here are some of them:</p>\n\n<ul>\n  <li><a href=\"https://swifttoolkit.dev/posts/hello-world\">Hello, World!</a>: why Swift can be a great choice for you or your team.</li>\n  <li><a href=\"https://swifttoolkit.dev/posts/spm-cheatsheet\">The SPM Syntax Cheatsheet</a>: forgot how to define your Package.swift files? Access the cheatsheet to quickly remember the syntax.</li>\n  <li><a href=\"https://swifttoolkit.dev/posts/argument-parser-guide\">The Interactive Swift Argument Parser Guide</a>: one of my favorite packages, the Swift Argument Parser helps creating command line tools in Swift. This post contains an interactive terminal simulator that shows the result of the sample code blocks!</li>\n</ul>\n\n<p>I’m looking forward to create more content, contribute to the Swift community, and help empowering other developers learn new areas.</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/SwiftToolkit.png\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/SwiftToolkit.png\" />\n  </a>\n\n</div>",
            "summary": "I’m thrilled to announce that during the the past few months, I’ve been working on a new website: SwiftToolkit.dev. The goal is to share tutorials, guides, cheatsheets and other resources that can be helpful in the tooling, developer experience, and server side Swift domains.",
            "date_published": "2024-03-29T09:00:00+00:00",
            "date_modified": "2024-03-29T09:00:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": ["Swift","Server Side Swift","Announcements"]},{
            "id": "https://blog.natanrolnik.me/Swift-Lambda-Build-Badges",
            "url": "https://blog.natanrolnik.me/swift-lambda-build-badges",
            "title": "Using Swift in AWS Lambda to Display CI Build Badges",
            "content_html": "<p>During the last month, as part of my work as an iOS Infra engineer at Houzz, I was responsible for moving our CI from a in-house, bare metal setup running TeamCity, to <a href=\"https://bitrise.io\">Bitrise</a>. The constant maintenance, hardware limitations, and lack of determinism were the main reasons for this change.</p>\n\n<p>Connected to the single repository containing the code for both Consumer and Pro apps, we have 6 types of builds: On commit, Nightly, and Release, for both apps. One of the advantages of the TeamCity approach when compared to Bitrise, is that it provides a way to see the status of these 6 builds, while Bitrise displays the builds sorted by time. When I realized we lost this quick and useful overview, I wanted to build something to replace it.</p>\n\n<p>Initially, I thought of building a web dashboard based on the Bitrise API. Or, possibly, storing the statuses at some server and updating it at the end of every build. But I quickly disregarded it. Requiring our devs to go to another page (specially now that everyone is remote, and displaying it in a TV in the office is not an option) and managing static pages or servers were factors that made me walk way from this idea. Then I thought about displaying a table with the existing and popular build badges, provided by many CI/CD solutions. Throw them in the repository’s Readme in GitHub, and that’s it!</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/20211401-BitriseBadge.png\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/20211401-BitriseBadge.png\" />\n  </a>\n\n</div>\n\n<p>Bitrise provides status images, so I thought there would be almost no work: just embed the images in the readme, and that’s it. Shortly after, I realized their Badge API is missing something basic: although it supports querying per branch statuses, it <a href=\"https://discuss.bitrise.io/t/status-badges-per-workflow/658\">doesn’t for workflow IDs</a>. As the different builds run per workflow, I couldn’t go with this solution.</p>\n\n<p>Embedding images in markdown do not support any logic, as they’re simple GET requests. I realized I would need some sort of logic running in a remote server: use the broader <a href=\"https://api-docs.bitrise.io\">Bitrise API</a>, analyze the response, and return an image, or maybe a redirect to <a href=\"https://shields.io\">Shields.io</a> with the correct parameters.</p>\n\n<p>Being able to run code in the cloud <strong>on demand</strong> seemed the perfect fit for my goal. Instead of managing servers, scaling and loading, many cloud providers do that for you by allocating the hardware resources which will execute your code only when it’s necessary. They take care of the servers running your code, so the industry calls this model <em>serverless</em>. AWS sells it as Lambda, Google Cloud and Azure simply call it Serverless, and even Cloudflare allows having serverless function with their Workers product.</p>\n\n<h2 id=\"the-swift-lambda-runtime\">The Swift Lambda Runtime</h2>\n\n<p>Although I’ve used Lambda in the past for executing Javascript, I wanted to try the <a href=\"https://github.com/swift-server/swift-aws-lambda-runtime\">Swift implementation of the AWS Lambda Runtime</a>, released a few months ago by the Swift Server Work Group. Besides the runtimes provided by default by AWS (as Node.js, Python, Ruby, Java and Go), one can implement custom runtimes which run on Amazon Linux. Some people have been working on supporting Swift on Lambda for a long time, but finally we have now an official package by the Swift Server group.</p>\n\n<p>To get started, you can watch <a href=\"https://developer.apple.com/videos/play/wwdc2020/10644/\">this WWDC20 session</a> by <a href=\"https://twitter.com/tomerdoron\">Tom Doron</a>, and also read <a href=\"https://fabianfett.de/getting-started-with-swift-aws-lambda-runtime\">this post</a> and <a href=\"https://fabianfett.de/swift-on-aws-lambda-creating-your-first-http-endpoint\">this post</a> by <a href=\"https://twitter.com/fabianfett\">Fabian Fett</a>, which describes some of the prerequisites, such as installing Docker, setting up an AWS account, and exposing your lambda to HTTP endpoint using API Gateway. Both Tom and Fabian work at Apple and maintain the Swift Lambda Runtime package.</p>\n\n<p>If you’re an iOS developer, writing some Lambda functions might be the fastest way to get something up and running to provide remote APIs for your apps. Or, maybe, if you work for a company that has both Android and iOS products, moving some of the code to the cloud might save you from writing parsing logic twice in your app clients.</p>\n\n<blockquote>\n  <p><strong>Note:</strong> this post will focus more on the implementation of the function itself to achieve my goal, rather than on how to deploy lambda functions. You can refer to Fabian’s post linked above if you want to learn how to deploy your Lambda function and connecting it to API Gateway. Lambda and API Gateway are two different services, which can be used together.</p>\n</blockquote>\n\n<h2 id=\"first-try-redirecting-to-shieldsio\">First Try: Redirecting to Shields.io</h2>\n\n<p>My first idea was to read the Bitrise API, querying for a specific workflow ID, and returning a redirect in the lambda response to Shields.io. This is a service that provides badges which can be included in Readmes and other pages. Alongside with ready badges for different services (which do the logic for you), it also allows you creating static badges, without any logic, based on parameters you provide. For example, copy <code class=\"language-plaintext highlighter-rouge\">https://img.shields.io/badge/TestBadge-works-green</code> and paste it into the address bar in your browser.</p>\n\n<p>To perform a redirect using the Swift runtime, you can write something like this:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">import</span> <span class=\"kt\">Foundation</span>\n<span class=\"kd\">import</span> <span class=\"kt\">AWSLambdaRuntime</span>\n<span class=\"kd\">import</span> <span class=\"kt\">AWSLambdaEvents</span>\n\n<span class=\"kt\">Lambda</span><span class=\"o\">.</span><span class=\"n\">run</span> <span class=\"p\">{</span> <span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"nv\">request</span><span class=\"p\">:</span> <span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Request</span><span class=\"p\">,</span> <span class=\"nv\">callback</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">(</span><span class=\"kt\">Result</span><span class=\"o\">&lt;</span><span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Response</span><span class=\"p\">,</span> <span class=\"kt\">Error</span><span class=\"o\">&gt;</span><span class=\"p\">)</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span> <span class=\"k\">in</span>\n    <span class=\"k\">let</span> <span class=\"nv\">headers</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s\">\"Location\"</span><span class=\"p\">:</span> <span class=\"s\">\"https://img.shields.io/badge/Redirect-Succeeded-orange\"</span><span class=\"p\">]</span>\n\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">found</span><span class=\"p\">,</span> <span class=\"nv\">headers</span><span class=\"p\">:</span> <span class=\"n\">headers</span><span class=\"p\">)))</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>If you use <code class=\"language-plaintext highlighter-rouge\">curl -i</code> to call the <code class=\"language-plaintext highlighter-rouge\">/invoke</code> path on localhost, you’ll get the following response:</p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>HTTP/1.1 200 OK\ncontent-length: 102\n\n{\"headers\":{\"Location\":\"https:\\/\\/img.shields.io\\/badge\\/Redirect-Succeeded-orange\"},\"statusCode\":302}\n</code></pre></div></div>\n\n<p>Notice how the <code class=\"language-plaintext highlighter-rouge\">/invoke</code> function returns <code class=\"language-plaintext highlighter-rouge\">200 OK</code>, while the body contains what API Gateway needs. API Gateway will convert the status code and the body into another response. After you deploy the same function, you should integrate the it via API Gateway, and calling it with <code class=\"language-plaintext highlighter-rouge\">curl -i</code> will result in the following response:</p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>HTTP/2 302\ndate: Fri, 15 Jan 2021 13:06:29 GMT\ncontent-length: 0\nlocation: https://img.shields.io/badge/Redirect-Succeeded-orange\n</code></pre></div></div>\n\n<p>Notice how now the status code is 302, found, which is used for redirecting. If you call the same API from the browser, it will handle the redirect for you. So far so good.</p>\n\n<p>Once you get this working, adding a method for querying the Bitrise API is straightforward. A single <code class=\"language-plaintext highlighter-rouge\">URLRequest</code> call using <code class=\"language-plaintext highlighter-rouge\">URLSession</code> is enough:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">import</span> <span class=\"kt\">Foundation</span>\n<span class=\"kd\">import</span> <span class=\"kt\">AWSLambdaRuntime</span>\n<span class=\"kd\">import</span> <span class=\"kt\">AWSLambdaEvents</span>\n\n<span class=\"c1\">//1</span>\n<span class=\"cp\">#if canImport(FoundationNetworking)</span>\n<span class=\"kd\">import</span> <span class=\"kt\">FoundationNetworking</span>\n<span class=\"cp\">#endif</span>\n\n<span class=\"c1\">//2</span>\n<span class=\"kd\">struct</span> <span class=\"kt\">ErrorResponse</span><span class=\"p\">:</span> <span class=\"kt\">Codable</span> <span class=\"p\">{</span>\n\t<span class=\"k\">let</span> <span class=\"nv\">error</span><span class=\"p\">:</span> <span class=\"kt\">String</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">//3</span>\n<span class=\"k\">guard</span>\n\t<span class=\"k\">let</span> <span class=\"nv\">appSlug</span> <span class=\"o\">=</span> <span class=\"kt\">Lambda</span><span class=\"o\">.</span><span class=\"nf\">env</span><span class=\"p\">(</span><span class=\"s\">\"APP_SLUG\"</span><span class=\"p\">),</span>\n\t<span class=\"k\">let</span> <span class=\"nv\">bitriseToken</span> <span class=\"o\">=</span> <span class=\"kt\">Lambda</span><span class=\"o\">.</span><span class=\"nf\">env</span><span class=\"p\">(</span><span class=\"s\">\"BITRISE_TOKEN\"</span><span class=\"p\">)</span> <span class=\"k\">else</span> <span class=\"p\">{</span>\n\t<span class=\"nf\">fatalError</span><span class=\"p\">(</span><span class=\"s\">\"Environment variables not configured\"</span><span class=\"p\">)</span>\n<span class=\"p\">}</span>\n\n<span class=\"kt\">Lambda</span><span class=\"o\">.</span><span class=\"n\">run</span> <span class=\"p\">{</span> <span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"nv\">request</span><span class=\"p\">:</span> <span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Request</span><span class=\"p\">,</span> <span class=\"nv\">callback</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">(</span><span class=\"kt\">Result</span><span class=\"o\">&lt;</span><span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Response</span><span class=\"p\">,</span> <span class=\"kt\">Error</span><span class=\"o\">&gt;</span><span class=\"p\">)</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span> <span class=\"k\">in</span>\n\t<span class=\"c1\">//4</span>\n\t<span class=\"k\">guard</span> <span class=\"k\">let</span> <span class=\"nv\">workflowId</span> <span class=\"o\">=</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">queryStringParameters</span><span class=\"p\">?[</span><span class=\"s\">\"workflow_id\"</span><span class=\"p\">]</span> <span class=\"k\">else</span> <span class=\"p\">{</span>\n\t\t<span class=\"k\">let</span> <span class=\"nv\">error</span> <span class=\"o\">=</span> <span class=\"k\">try</span><span class=\"p\">?</span> <span class=\"kt\">JSONEncoder</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"nf\">encodeAsString</span><span class=\"p\">(</span><span class=\"kt\">ErrorResponse</span><span class=\"p\">(</span><span class=\"nv\">error</span><span class=\"p\">:</span> <span class=\"s\">\"Missing required workflow_id parameter\"</span><span class=\"p\">))</span>\n\t\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">badRequest</span><span class=\"p\">,</span> <span class=\"nv\">body</span><span class=\"p\">:</span> <span class=\"n\">error</span><span class=\"p\">)))</span>\n\t<span class=\"p\">}</span>\n\n\t<span class=\"c1\">//5</span>\n\t<span class=\"k\">let</span> <span class=\"nv\">urlString</span> <span class=\"o\">=</span> <span class=\"s\">\"https://api.bitrise.io/v0.1/apps/</span><span class=\"se\">\\(</span><span class=\"n\">appSlug</span><span class=\"se\">)</span><span class=\"s\">/builds?sort_by=created_at&amp;workflow=</span><span class=\"se\">\\(</span><span class=\"n\">workflowId</span><span class=\"se\">)</span><span class=\"s\">&amp;limit=10\"</span>\n\t<span class=\"k\">let</span> <span class=\"nv\">url</span> <span class=\"o\">=</span> <span class=\"kt\">URL</span><span class=\"p\">(</span><span class=\"nv\">string</span><span class=\"p\">:</span> <span class=\"n\">urlString</span><span class=\"p\">)</span><span class=\"o\">!</span>\n\t<span class=\"k\">var</span> <span class=\"nv\">urlRequest</span> <span class=\"o\">=</span> <span class=\"kt\">URLRequest</span><span class=\"p\">(</span><span class=\"nv\">url</span><span class=\"p\">:</span> <span class=\"n\">url</span><span class=\"p\">)</span>\n\t<span class=\"n\">urlRequest</span><span class=\"o\">.</span><span class=\"nf\">setValue</span><span class=\"p\">(</span><span class=\"n\">bitriseToken</span><span class=\"p\">,</span> <span class=\"nv\">forHTTPHeaderField</span><span class=\"p\">:</span> <span class=\"s\">\"Authorization\"</span><span class=\"p\">)</span>\n\n\t<span class=\"kt\">URLSession</span><span class=\"o\">.</span><span class=\"n\">shared</span><span class=\"o\">.</span><span class=\"nf\">dataTask</span><span class=\"p\">(</span><span class=\"nv\">with</span><span class=\"p\">:</span> <span class=\"n\">urlRequest</span><span class=\"p\">)</span> <span class=\"p\">{</span> <span class=\"n\">data</span><span class=\"p\">,</span> <span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"n\">error</span> <span class=\"k\">in</span>\n\t\t<span class=\"k\">guard</span>\n\t\t\t<span class=\"k\">let</span> <span class=\"nv\">data</span> <span class=\"o\">=</span> <span class=\"n\">data</span><span class=\"p\">,</span>\n\t\t\t<span class=\"n\">error</span> <span class=\"o\">==</span> <span class=\"kc\">nil</span><span class=\"p\">,</span>\n\t\t\t<span class=\"k\">let</span> <span class=\"nv\">buildResponse</span> <span class=\"o\">=</span> <span class=\"k\">try</span><span class=\"p\">?</span> <span class=\"n\">jsonDecoder</span><span class=\"o\">.</span><span class=\"nf\">decode</span><span class=\"p\">(</span><span class=\"kt\">BuildsResponse</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">from</span><span class=\"p\">:</span> <span class=\"n\">data</span><span class=\"p\">)</span> <span class=\"k\">else</span> <span class=\"p\">{</span>\n\t\t\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">badRequest</span><span class=\"p\">)))</span>\n\t\t<span class=\"p\">}</span>\n\n\t\t<span class=\"k\">guard</span> <span class=\"k\">let</span> <span class=\"nv\">build</span> <span class=\"o\">=</span> <span class=\"n\">buildResponse</span><span class=\"o\">.</span><span class=\"n\">builds</span><span class=\"o\">.</span><span class=\"nf\">first</span><span class=\"p\">(</span><span class=\"nv\">where</span><span class=\"p\">:</span> <span class=\"p\">{</span> <span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"mi\">3</span><span class=\"p\">,</span> <span class=\"mi\">4</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"nf\">contains</span><span class=\"p\">(</span><span class=\"nv\">$0</span><span class=\"o\">.</span><span class=\"n\">status</span><span class=\"p\">)</span> <span class=\"p\">})</span> <span class=\"k\">else</span> <span class=\"p\">{</span>\n\t\t\t<span class=\"k\">let</span> <span class=\"nv\">error</span> <span class=\"o\">=</span> <span class=\"k\">try</span><span class=\"p\">?</span> <span class=\"kt\">JSONEncoder</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"nf\">encodeAsString</span><span class=\"p\">(</span><span class=\"kt\">ErrorResponse</span><span class=\"p\">(</span><span class=\"nv\">error</span><span class=\"p\">:</span> <span class=\"s\">\"Build  </span><span class=\"se\">\\(</span><span class=\"n\">workflowId</span><span class=\"se\">)</span><span class=\"s\"> not found\"</span><span class=\"p\">))</span>\n\t\t\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">badRequest</span><span class=\"p\">,</span> <span class=\"nv\">body</span><span class=\"p\">:</span> <span class=\"n\">error</span><span class=\"p\">)))</span>\n\t\t<span class=\"p\">}</span>\n\n\t\t<span class=\"c1\">//6</span>\n\t\t<span class=\"k\">let</span> <span class=\"nv\">location</span><span class=\"p\">:</span> <span class=\"kt\">String</span>\n\t\t<span class=\"k\">if</span> <span class=\"n\">build</span><span class=\"o\">.</span><span class=\"n\">status</span><span class=\"o\">.</span><span class=\"nf\">contains</span><span class=\"p\">(</span><span class=\"s\">\"success\"</span><span class=\"p\">)</span> <span class=\"p\">{</span>\n\t\t\t<span class=\"n\">location</span> <span class=\"o\">=</span> <span class=\"s\">\"https://img.shields.io/badge/</span><span class=\"se\">\\(</span><span class=\"n\">workflowId</span><span class=\"se\">)</span><span class=\"s\">-Passing-green\"</span>\n\t\t<span class=\"p\">}</span> <span class=\"k\">else</span> <span class=\"p\">{</span>\n\t\t\t<span class=\"n\">location</span> <span class=\"o\">=</span> <span class=\"s\">\"https://img.shields.io/badge/</span><span class=\"se\">\\(</span><span class=\"n\">workflowId</span><span class=\"se\">)</span><span class=\"s\">-Failing-red\"</span>\n\t\t<span class=\"p\">}</span>\n\t\t\n\t\t<span class=\"k\">let</span> <span class=\"nv\">headers</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s\">\"Location\"</span><span class=\"p\">:</span> <span class=\"n\">location</span><span class=\"p\">]</span>\n\t\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">found</span><span class=\"p\">,</span> <span class=\"nv\">headers</span><span class=\"p\">:</span> <span class=\"n\">headers</span><span class=\"p\">)))</span>\n\t<span class=\"p\">}</span><span class=\"o\">.</span><span class=\"nf\">resume</span><span class=\"p\">()</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Notice a few things were added in this sample code:</p>\n\n<ol>\n  <li>On Linux, <code class=\"language-plaintext highlighter-rouge\">URLSession</code> is part of <code class=\"language-plaintext highlighter-rouge\">FoundationNetworking</code>, and not <code class=\"language-plaintext highlighter-rouge\">Foundation</code> as on iOS and macOS.</li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ErrorResponse</code> is a <code class=\"language-plaintext highlighter-rouge\">Codable</code> struct that wraps an error string. Because the API Gateway expects the <code class=\"language-plaintext highlighter-rouge\">body</code> parameter as a String, a <code class=\"language-plaintext highlighter-rouge\">encodeAsString</code> extension method is used on <code class=\"language-plaintext highlighter-rouge\">JSONEncoder</code>, as <a href=\"https://fabianfett.de/swift-on-aws-lambda-creating-your-first-http-endpoint\">described by Fabian</a> in the <em>Step 4: JSON</em> section.</li>\n  <li>The package provides a static function <code class=\"language-plaintext highlighter-rouge\">env(_ name: String) -&gt; String?</code>, which is ideal for accessing environment variables as API tokens and other sensitive parameters. Without these required values, a <code class=\"language-plaintext highlighter-rouge\">fatalError</code> is thrown and the Lambda cannot be initialized.</li>\n  <li>You can access the query string parameters of the URL with the <code class=\"language-plaintext highlighter-rouge\">queryStringParameters</code> property of <code class=\"language-plaintext highlighter-rouge\">APIGateway.V2.Request</code>. If no <code class=\"language-plaintext highlighter-rouge\">workflow_id</code> is provided, the function returns with a bad request 400 response.</li>\n  <li>Create the Bitrise API request, using the app slug defined in step 3, and workflow id from the previous step. Don’t forget to also set the HTTP header field <code class=\"language-plaintext highlighter-rouge\">Authorization</code> using the Bitrise API token, also defined in step 3.</li>\n  <li>Finally, after processing the status of the latest build for a given workflow ID, decide what Shields.io URL to redirect to.</li>\n</ol>\n\n<p>Once I deployed this function, I got exactly what I wanted. A URL for a badge with the correct status.</p>\n\n<p>After embedding the image URLs with each workflow as a parameter (for example, <code class=\"language-plaintext highlighter-rouge\">https://&lt;API-GATEWAY-ID&gt;.execute-api.us-east-1.amazonaws.com/badge?workflow_id=Consumer-OnCommit</code>), I started seeing the badges I wanted. I saw which builds were failing, and after fixing them, I was expecting to see them changing. Except they didn’t: by inspecting the HTML of the GitHub Readme, I noticed that all images had a different URL. Something in the form of <code class=\"language-plaintext highlighter-rouge\">http://camo.githubusercontent.com/&lt;Some-Long-ID&gt;...</code>. After a short research, it turned out that GitHub proxies and caches every media in the Readme, which is bad for build badges that constantly might change.</p>\n\n<p>As stated in the <a href=\"https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/about-anonymized-image-urls#an-image-that-changed-recently-is-not-updating\">GitHub docs</a>, setting the <code class=\"language-plaintext highlighter-rouge\">Cache-Control</code> header to <code class=\"language-plaintext highlighter-rouge\">no-cache</code> in the response should be enough to avoid caching. However, as my function’s URL only performed a redirect, and static Shields.io badges have <code class=\"language-plaintext highlighter-rouge\">max-age=86400</code> in their <code class=\"language-plaintext highlighter-rouge\">Cache-Control</code> header, doing so didn’t help in the end.</p>\n\n<p>I realized I would need to return my own images instead of relying on a redirect to a server I don’t control.</p>\n\n<h2 id=\"returning-binary-data-with-lambda-and-api-gateway\">Returning Binary Data with Lambda and API Gateway</h2>\n\n<p>The process to return the build badge as an image data would consist creating the images and figuring out what type of response I needed to provide API Gateway with. The first part was relatively easy: figuring out the best colors and shapes in Sketch.</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/20211401-BadgesInSketch.png\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/20211401-BadgesInSketch.png\" />\n  </a>\n\n</div>\n\n<p>After exporting them, I searched the correct way of returning binary data from a Lambda function with API Gateway. It turns out the data needs to be converted into a Base64 encoded string, and this string passed as the body parameter. Additionally, the key <code class=\"language-plaintext highlighter-rouge\">isBase64Encoded</code> needs to be set to <code class=\"language-plaintext highlighter-rouge\">true</code>, and API Gateway takes care of converting it from Base64 to binary. To make GitHub load the image correctly, the header <code class=\"language-plaintext highlighter-rouge\">Content-Type</code> should be set to <code class=\"language-plaintext highlighter-rouge\">image/png</code> or another valid content type.</p>\n\n<p>Because the images are small, and are only 4 in total, I decided to embed them as plain string variables into the code. I used an Xcode playground importing UIKit to convert a <code class=\"language-plaintext highlighter-rouge\">UIImage</code> from resources into Base64. I copied the results from the playground console into something like this:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">let</span> <span class=\"nv\">consumerPassing</span> <span class=\"o\">=</span> <span class=\"s\">\"iVBORw0KGgoAAAANSUhEUgA...\"</span> <span class=\"c1\">//a long string</span>\n<span class=\"k\">let</span> <span class=\"nv\">proPassing</span> <span class=\"o\">=</span> <span class=\"c1\">//similar</span>\n<span class=\"k\">let</span> <span class=\"nv\">consumerFailing</span> <span class=\"o\">=</span> <span class=\"c1\">//similar</span>\n<span class=\"k\">let</span> <span class=\"nv\">proPassing</span> <span class=\"o\">=</span> <span class=\"c1\">//similar</span>\n</code></pre></div></div>\n\n<p>Once the strings were ready, it was it was left to find the correct image and wrap it in the response:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">//decide the image based on the build response and workflow id</span>\n<span class=\"k\">let</span> <span class=\"nv\">base64Image</span> <span class=\"o\">=</span> <span class=\"n\">build</span><span class=\"o\">.</span><span class=\"n\">statusText</span> <span class=\"o\">==</span> <span class=\"s\">\"success\"</span> <span class=\"p\">?</span> <span class=\"nv\">consumerPassing</span> <span class=\"p\">:</span> <span class=\"n\">consumerFailing</span>\n\n<span class=\"k\">let</span> <span class=\"nv\">headers</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s\">\"Cache-Control\"</span><span class=\"p\">:</span> <span class=\"s\">\"no-cache\"</span><span class=\"p\">,</span> <span class=\"s\">\"Content-Type\"</span><span class=\"p\">:</span> <span class=\"s\">\"image/png\"</span><span class=\"p\">]</span>\n<span class=\"k\">let</span> <span class=\"nv\">response</span> <span class=\"o\">=</span> <span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Response</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">ok</span><span class=\"p\">,</span> <span class=\"nv\">headers</span><span class=\"p\">:</span> <span class=\"n\">headers</span><span class=\"p\">,</span> <span class=\"nv\">body</span><span class=\"p\">:</span> <span class=\"n\">base64Image</span><span class=\"p\">,</span> <span class=\"nv\">isBase64Encoded</span><span class=\"p\">:</span> <span class=\"kc\">true</span><span class=\"p\">)</span>\n<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">))</span>\n</code></pre></div></div>\n\n<p>With the code above deployed, calling my Lambda function returned an image which could be embedded in the Readme:</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/20211401-BadgesReadMe.png\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/20211401-BadgesReadMe.png\" />\n  </a>\n\n</div>\n\n<h2 id=\"bonus-points-linking-to-the-build-page\">Bonus Points: Linking to the Build Page</h2>\n\n<p>After the mini dashboard was live, I had another idea, which could be the cherry on top. What if clicking the badges would take the developer straight to the page of the build. This could save them from searching the build in the list of builds. And after all, by using the Bitrise API, I had all the information I needed.</p>\n\n<p>One of the advantages of using API Gateway, is that you can integrate your lambda with many routes. For example, you can have <code class=\"language-plaintext highlighter-rouge\">&lt;Url-Host&gt;/badge</code> and <code class=\"language-plaintext highlighter-rouge\">&lt;Url-Host&gt;/link</code> using the same lambda, and deal with the routing on the lambda itself. This is exactly what I did.</p>\n\n<p>On the API Gateway dashboard, I added two GET routes: one for <code class=\"language-plaintext highlighter-rouge\">/badge</code>, and another one for <code class=\"language-plaintext highlighter-rouge\">/link</code>. Under <em>Integrations</em>, I connected both routes to my lambda function, and inside my function, instead of returning the image right away, I did the following:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kt\">Lambda</span><span class=\"o\">.</span><span class=\"n\">run</span> <span class=\"p\">{</span> <span class=\"c1\">// ...</span>\n\t<span class=\"c1\">//decode workflow_id...</span>\n\t\n\t<span class=\"kt\">URLSession</span><span class=\"o\">.</span><span class=\"n\">shared</span><span class=\"o\">.</span><span class=\"nf\">dataTask</span><span class=\"p\">(</span><span class=\"nv\">with</span><span class=\"p\">:</span> <span class=\"n\">urlRequest</span><span class=\"p\">)</span> <span class=\"p\">{</span> <span class=\"n\">data</span><span class=\"p\">,</span> <span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"n\">error</span> <span class=\"k\">in</span>\n\t\t<span class=\"c1\">//decode build data...</span>\n\t\t\n\t\t<span class=\"k\">switch</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">http</span><span class=\"o\">.</span><span class=\"n\">path</span> <span class=\"p\">{</span>\n\t\t<span class=\"k\">case</span> <span class=\"s\">\"/badge\"</span><span class=\"p\">:</span>\n\t\t\t<span class=\"nf\">retrieveImage</span><span class=\"p\">(</span><span class=\"nv\">for</span><span class=\"p\">:</span> <span class=\"n\">build</span><span class=\"p\">,</span> <span class=\"nv\">workflowId</span><span class=\"p\">:</span> <span class=\"n\">workflowId</span><span class=\"p\">,</span> <span class=\"nv\">callback</span><span class=\"p\">:</span> <span class=\"n\">callback</span><span class=\"p\">)</span>\n\t\t<span class=\"k\">case</span> <span class=\"s\">\"/link\"</span><span class=\"p\">:</span>\n\t\t\t<span class=\"nf\">redirect</span><span class=\"p\">(</span><span class=\"nv\">to</span><span class=\"p\">:</span> <span class=\"n\">build</span><span class=\"o\">.</span><span class=\"n\">slug</span><span class=\"p\">,</span> <span class=\"nv\">callback</span><span class=\"p\">:</span> <span class=\"n\">callback</span><span class=\"p\">)</span>\n\t\t<span class=\"k\">default</span><span class=\"p\">:</span>\n\t\t\t<span class=\"k\">let</span> <span class=\"nv\">error</span> <span class=\"o\">=</span> <span class=\"k\">try</span><span class=\"p\">?</span> <span class=\"kt\">JSONEncoder</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"nf\">encodeAsString</span><span class=\"p\">(</span><span class=\"kt\">ErrorResponse</span><span class=\"p\">(</span><span class=\"nv\">error</span><span class=\"p\">:</span> <span class=\"s\">\"Invalid path: </span><span class=\"se\">\\(</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"o\">.</span><span class=\"n\">http</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"se\">)</span><span class=\"s\">\"</span><span class=\"p\">))</span>\n\t\t\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">notFound</span><span class=\"p\">,</span> <span class=\"nv\">body</span><span class=\"p\">:</span> <span class=\"n\">error</span><span class=\"p\">)))</span>\n\t\t<span class=\"p\">}</span>\n\t<span class=\"p\">}</span>\n<span class=\"p\">}</span>\n\n</code></pre></div></div>\n\n<p>Below that, I inserted the two functions called from the switch statement:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">func</span> <span class=\"nf\">redirect</span><span class=\"p\">(</span><span class=\"n\">to</span> <span class=\"nv\">buildSlug</span><span class=\"p\">:</span> <span class=\"kt\">String</span><span class=\"p\">,</span> <span class=\"nv\">callback</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">(</span><span class=\"kt\">Result</span><span class=\"o\">&lt;</span><span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Response</span><span class=\"p\">,</span> <span class=\"kt\">Error</span><span class=\"o\">&gt;</span><span class=\"p\">)</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span> <span class=\"p\">{</span>\n\t<span class=\"k\">let</span> <span class=\"nv\">headers</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s\">\"Cache-Control\"</span><span class=\"p\">:</span> <span class=\"s\">\"no-cache\"</span><span class=\"p\">,</span> <span class=\"s\">\"Location\"</span><span class=\"p\">:</span> <span class=\"s\">\"https://app.bitrise.io/build/</span><span class=\"se\">\\(</span><span class=\"n\">buildSlug</span><span class=\"se\">)</span><span class=\"s\">\"</span><span class=\"p\">]</span>\n\t<span class=\"k\">return</span> <span class=\"nf\">callback</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">success</span><span class=\"p\">(</span><span class=\"o\">.</span><span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">statusCode</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">found</span><span class=\"p\">,</span> <span class=\"nv\">headers</span><span class=\"p\">:</span> <span class=\"n\">headers</span><span class=\"p\">)))</span>\n<span class=\"p\">}</span>\n\n<span class=\"kd\">func</span> <span class=\"nf\">retrieveImage</span><span class=\"p\">(</span><span class=\"k\">for</span> <span class=\"nv\">build</span><span class=\"p\">:</span> <span class=\"kt\">Build</span><span class=\"p\">,</span> <span class=\"nv\">workflowId</span><span class=\"p\">:</span> <span class=\"kt\">String</span><span class=\"p\">,</span> <span class=\"nv\">callback</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">(</span><span class=\"kt\">Result</span><span class=\"o\">&lt;</span><span class=\"kt\">APIGateway</span><span class=\"o\">.</span><span class=\"kt\">V2</span><span class=\"o\">.</span><span class=\"kt\">Response</span><span class=\"p\">,</span> <span class=\"kt\">Error</span><span class=\"o\">&gt;</span><span class=\"p\">)</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span> <span class=\"p\">{</span>\n\t<span class=\"c1\">//move here the response initialization based on the correct image for `build`</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>After deploying the code above, and inserting the link URL for each image with the correct workflow ID, taking the user to the failing or passing build worked perfectly:</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/20211401-LinkToBitriseBuild.gif\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/20211401-LinkToBitriseBuild.gif\" />\n  </a>\n\n</div>\n\n<hr />\n\n<h5 id=\"in-a-paragraph\">In a Paragraph</h5>\n\n<p>AWS Lambda is a great (and probably cheap) resource for running specific computational tasks. With the official runtime package, Swift is a fantastic language to write your lambdas with. Be it due to its low memory foot, type safety, and also for being a language you might be familiar with already. With API Gateway you can expose your functions to the web and call them from anywhere (app client, readme), and don’t worry about server scaling and uptime.</p>",
            "summary": "During the last month, as part of my work as an iOS Infra engineer at Houzz, I was responsible for moving our CI from a in-house, bare metal setup running TeamCity, to Bitrise. The constant maintenance, hardware limitations, and lack of determinism were the main reasons for this change.",
            "date_published": "2021-01-19T09:00:00+00:00",
            "date_modified": "2021-01-19T09:00:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": ["Lambda","Swift","Server Side Swift"]},{
            "id": "https://blog.natanrolnik.me/RW-SSS-Debut",
            "url": "https://blog.natanrolnik.me/RW-SSS-Debut",
            "title": "My first tutorial at RayWenderlich.com: “SMS user authentication with Vapor and AWS”",
            "content_html": "<p>A few months ago, <a href=\"https://RayWenderlich.com\">RayWenderlich.com</a> launched a Server Side Swift section and they were looking for authors to join the team. As I believe that Swift on the server has a promising future - and not only amongst iOS developers - I decided to apply.</p>\n\n<p>After many weeks of effort and with the support of their great team (tech editors, editors, designers), the tutorial went live earlier this month and I couldn’t be more proud. I’ve been consuming content from RayWenderlich.com since 2013, be them tutorials, books and video courses. Joining their team is a dream coming true.</p>\n\n<p>In this tutorial, the reader will learn how to build an SMS user authentication API using <a href=\"https://vapor.codes\">Vapor</a> and Amazon’s AWS Simple Notification Service, SNS. Amongst the covered topics, are:</p>\n\n<ul>\n  <li>How models work in Fluent and Vapor;</li>\n  <li>How to register and use a protocol-based <code class=\"language-plaintext highlighter-rouge\">Service</code> in Vapor;</li>\n  <li>Token-based session authentication in Vapor;</li>\n  <li>Registering routes in your server’s API;</li>\n  <li>Using the AWS swift package, requesting SNS to send the SMS in your behalf;</li>\n</ul>\n\n<p><a href=\"https://www.raywenderlich.com/4379841-sms-user-authentication-with-vapor-and-aws\">The article is here, check it out!</a></p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/RW-SSS-Debut.png\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/RW-SSS-Debut.png\" />\n  </a>\n\n</div>",
            "summary": "A few months ago, RayWenderlich.com launched a Server Side Swift section and they were looking for authors to join the team. As I believe that Swift on the server has a promising future - and not only amongst iOS developers - I decided to apply.",
            "date_published": "2020-01-20T09:00:00+00:00",
            "date_modified": "2020-01-20T09:00:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": ["RayWenderlich","Server Side Swift","Vapor"]},{
            "id": "https://blog.natanrolnik.me/FindingRedundantElse",
            "url": "https://blog.natanrolnik.me/finding-redundant-else",
            "title": "Finding Usages of Redundant Else",
            "content_html": "<p>A few years ago, when I opened a Pull Request, one of my colleagues requested a change which seemed irrelevant. The code was something similar to this:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">func</span> <span class=\"nf\">someFunction</span><span class=\"p\">()</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">String</span> <span class=\"p\">{</span>\n  <span class=\"k\">if</span> <span class=\"n\">someCondition</span> <span class=\"p\">{</span>\n    <span class=\"k\">return</span> <span class=\"s\">\"Value when condition is true\"</span>\n  <span class=\"p\">}</span> <span class=\"k\">else</span> <span class=\"p\">{</span>\n    <span class=\"k\">return</span> <span class=\"s\">\"Some other value\"</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>What he pointed was the following: the <code class=\"language-plaintext highlighter-rouge\">else</code> key is redundant. Because there is a <code class=\"language-plaintext highlighter-rouge\">return</code> inside the <code class=\"language-plaintext highlighter-rouge\">if</code> block, <strong>what’s inside the <code class=\"language-plaintext highlighter-rouge\">else</code> block would not be called anyway when <code class=\"language-plaintext highlighter-rouge\">someCondition</code> is true</strong>. Therefore, the same code could be written this way:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">func</span> <span class=\"nf\">someFunction</span><span class=\"p\">()</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">String</span> <span class=\"p\">{</span>\n  <span class=\"k\">if</span> <span class=\"n\">someCondition</span> <span class=\"p\">{</span>\n    <span class=\"k\">return</span> <span class=\"s\">\"Value when condition is true\"</span>\n  <span class=\"p\">}</span>\n\n  <span class=\"k\">return</span> <span class=\"s\">\"Some other value\"</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>At a first glance, one can think: it doesn’t really matter. But there are two arguments that can be used against the usage of redundant <code class=\"language-plaintext highlighter-rouge\">else</code>s:</p>\n\n<ol>\n  <li>They are redundant, and therefore, only waste time while reading and parsing the code;</li>\n  <li>They add indentation to the code within the <code class=\"language-plaintext highlighter-rouge\">else</code> block.</li>\n</ol>\n\n<h1 id=\"find-usages-with-xcode-or-atom\">Find Usages with Xcode or Atom</h1>\n\n<p>Since that Pull Request, I’ve been a strong supporter of removing usages of it. As an iOS Developer, having a SwiftLint rule throwing warnings would be perfect. Until I or someone else manages to write it, I decided first to find how many ocurrences exist in the codebase I’m working at.</p>\n\n<p>To achieve that, I decided I should use a Regular Expression - even though a wise man once said <em>The person who solves a problem with RegEx has now two problems</em> - because they are extremely powerful. I opened up <a href=\"https://regex101.com\">Regex101</a>, and pasted <a href=\"https://gist.github.com/natanrolnik/26318bdb252049d20dfc25d1ffefc3df\">this gist</a> on the “Test String” area. After a few minutes iterating on the RegEx, I found that the following expression is what I wanted:</p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">(return|continue|break)\\s.*(\\s|\\n|\\t)*?\\}(|\\s)else</code></p>\n\n<p>You can also open Regex101 and paste the expression to understand what each token and group mean.</p>\n\n<p>To see how frequent it appears in your codebase, open Xcode, and by pressing <code class=\"language-plaintext highlighter-rouge\">cmd</code>+<code class=\"language-plaintext highlighter-rouge\">shift</code>+<code class=\"language-plaintext highlighter-rouge\">F</code> open the Find Navigator. Above the search field, click on Text to replace it to Regular Expression. Paste the expression above and hit search. To my surprise, the numbers I got were higher than what I expected:</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/20191218-RedundantElse.gif\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/20191218-RedundantElse.gif\" />\n  </a>\n\n</div>\n\n<p>The Atom editor also supports RegEx search - activate Find in Project with the same <code class=\"language-plaintext highlighter-rouge\">cmd</code>+<code class=\"language-plaintext highlighter-rouge\">shift</code>+<code class=\"language-plaintext highlighter-rouge\">F</code> shortcut, and in the right side enable RegEx by choosing the option Use Regex (the button with <code class=\"language-plaintext highlighter-rouge\">.*</code> as the icon).</p>",
            "summary": "A few years ago, when I opened a Pull Request, one of my colleagues requested a change which seemed irrelevant. The code was something similar to this:",
            "date_published": "2019-12-19T09:00:00+00:00",
            "date_modified": "2019-12-19T09:00:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": ["RegEx","SwiftLint","Style Guide"]},{
            "id": "https://blog.natanrolnik.me/CodableEnumsWithAssociatedValues",
            "url": "https://blog.natanrolnik.me/codable-enums-associated-values",
            "title": "Using Codable to make enums with associated values even more powerful",
            "content_html": "<p>One of Swift’s greatest features, and one of my favorites, are enums with associated values. The language itself uses them for its fundamentals, like <code class=\"language-plaintext highlighter-rouge\">Optional&lt;T&gt;</code>, which either has a <code class=\"language-plaintext highlighter-rouge\">.some(T)</code> or is <code class=\"language-plaintext highlighter-rouge\">.none</code>. Another example is the new since Swift 5 <code class=\"language-plaintext highlighter-rouge\">Result&lt;T, E&gt;</code>, which either contains a <code class=\"language-plaintext highlighter-rouge\">.success(T)</code> or a<code class=\"language-plaintext highlighter-rouge\">.failure(E)</code> case. In this post, we will go over cases (no pun intended) where an enum is more suitable than a struct or class, and also learn how one can make enums with associated values conform to Codable, achieving a better and safer usage of these data representations when they need to be encoded and decoded. You can scroll to the end of the post to get the final playground.</p>\n\n<p>Enums with associated values make sense when a type may hold only one value, instead of two or more optional values. A classic example for <code class=\"language-plaintext highlighter-rouge\">Result</code> is a network operation, which might return either an error or an object. They never should be <code class=\"language-plaintext highlighter-rouge\">nil</code> or not be <code class=\"language-plaintext highlighter-rouge\">nil</code> simultaneously: when one is <code class=\"language-plaintext highlighter-rouge\">nil</code>, the other should exist.</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">//in this case, the caller must check for nil for both values</span>\n<span class=\"kd\">func</span> <span class=\"n\">issueRequest</span><span class=\"o\">&lt;</span><span class=\"kt\">T</span><span class=\"o\">&gt;</span><span class=\"p\">(</span><span class=\"n\">_</span> <span class=\"nv\">request</span><span class=\"p\">:</span> <span class=\"kt\">URLRequest</span><span class=\"p\">,</span> <span class=\"nv\">completion</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">(</span><span class=\"kt\">T</span><span class=\"p\">?,</span> <span class=\"kt\">Error</span><span class=\"p\">?)</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span>\n\n<span class=\"c1\">//here, however, it will be either .success or .failure</span>\n<span class=\"kd\">func</span> <span class=\"n\">issueRequest</span><span class=\"o\">&lt;</span><span class=\"kt\">T</span><span class=\"o\">&gt;</span><span class=\"p\">(</span><span class=\"n\">_</span> <span class=\"nv\">request</span><span class=\"p\">:</span> <span class=\"kt\">URLRequest</span><span class=\"p\">,</span> <span class=\"nv\">completion</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">(</span><span class=\"kt\">Result</span><span class=\"o\">&lt;</span><span class=\"kt\">T</span><span class=\"p\">,</span> <span class=\"kt\">Error</span><span class=\"o\">&gt;</span><span class=\"p\">)</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span>\n</code></pre></div></div>\n\n<p>Now, let’s think of a more concrete example. Let’s imagine we have an app which allows users to confirm presence in some event, and the response from the server might have one out of three possibilites:</p>\n\n<ol>\n  <li>The user is confirmed in the event, and a list of users going is also returned</li>\n  <li>The event is full and the user is at a specific position in the waitlist, and a list of users going is also returned</li>\n  <li>The user cannot go to the event for some reason (it is too late or there is no waitlist, for example)</li>\n</ol>\n\n<p>The server returns a JSON encoded response, so these are the possibilities:</p>\n\n<div class=\"language-javascript highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">//1 - user is confirmed:</span>\n<span class=\"p\">{</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">status</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">confirmed</span><span class=\"dl\">\"</span><span class=\"p\">,</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">confirmedUsers</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span><span class=\"dl\">\"</span><span class=\"s2\">id</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">abc</span><span class=\"dl\">\"</span><span class=\"p\">,</span> <span class=\"dl\">\"</span><span class=\"s2\">name</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">Rachel</span><span class=\"dl\">\"</span><span class=\"p\">},</span>\n    <span class=\"p\">{</span><span class=\"dl\">\"</span><span class=\"s2\">id</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">def</span><span class=\"dl\">\"</span><span class=\"p\">,</span> <span class=\"dl\">\"</span><span class=\"s2\">name</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">John</span><span class=\"dl\">\"</span><span class=\"p\">}</span>\n  <span class=\"p\">]</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">//2 - user is in waitlist:</span>\n<span class=\"p\">{</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">status</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">waitlist</span><span class=\"dl\">\"</span><span class=\"p\">,</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">position</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"mi\">12</span><span class=\"p\">,</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">confirmedUsers</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span><span class=\"dl\">\"</span><span class=\"s2\">id</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">abc</span><span class=\"dl\">\"</span><span class=\"p\">,</span> <span class=\"dl\">\"</span><span class=\"s2\">name</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">Rachel</span><span class=\"dl\">\"</span><span class=\"p\">},</span>\n    <span class=\"p\">{</span><span class=\"dl\">\"</span><span class=\"s2\">id</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">def</span><span class=\"dl\">\"</span><span class=\"p\">,</span> <span class=\"dl\">\"</span><span class=\"s2\">name</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">John</span><span class=\"dl\">\"</span><span class=\"p\">}</span>\n  <span class=\"p\">]</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">//3 - user cannot go for a different reason</span>\n<span class=\"p\">{</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">status</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">not allowed</span><span class=\"dl\">\"</span><span class=\"p\">,</span>\n  <span class=\"dl\">\"</span><span class=\"s2\">reason</span><span class=\"dl\">\"</span><span class=\"p\">:</span> <span class=\"dl\">\"</span><span class=\"s2\">It is too late to confirm to this event.</span><span class=\"dl\">\"</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Now, in our client, we need to be able to represent this data and its possible values. If we would use a struct, it would probably look to something like this:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">struct</span> <span class=\"kt\">EventConfirmationResponse</span> <span class=\"p\">{</span>\n  <span class=\"k\">let</span> <span class=\"nv\">status</span><span class=\"p\">:</span> <span class=\"kt\">String</span>\n  <span class=\"k\">let</span> <span class=\"nv\">confirmedUsers</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"kt\">User</span><span class=\"p\">]?</span>\n  <span class=\"k\">let</span> <span class=\"nv\">position</span><span class=\"p\">:</span> <span class=\"kt\">Int</span><span class=\"p\">?</span>\n  <span class=\"k\">let</span> <span class=\"nv\">reason</span><span class=\"p\">:</span> <span class=\"kt\">String</span><span class=\"p\">?</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Can you imagine yourself checking for all the the possible states this struct might have?</p>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/OptionalsMeme.png\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/OptionalsMeme.png\" alt=\"Are you kidding me?\" />\n  </a>\n\n    <div style=\"text-align: center; font-weight: bolder; font-size: 60%; margin-bottom: 20px\">\n      Are you kidding me?\n    </div>\n\n</div>\n\n<p>In addition to that, in this case a property being present is not enough to determine what is the status: <code class=\"language-plaintext highlighter-rouge\">confirmed</code> is returned in both confirmed and waitlist states. Therefore, the <code class=\"language-plaintext highlighter-rouge\">status</code> property must be checked in association with the optional values. And if the API get more possibilities, it gets even worse.</p>\n\n<h2 id=\"enums-with-associated-values-️\">Enums with associated values ❤️</h2>\n\n<p>We can do better. It would be much safer and predictable to use the following enum:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">enum</span> <span class=\"kt\">EventConfirmationResponse</span> <span class=\"p\">{</span>\n  <span class=\"k\">case</span> <span class=\"nf\">confirmed</span><span class=\"p\">([</span><span class=\"kt\">User</span><span class=\"p\">])</span> <span class=\"c1\">//Contains an array of users going to the event</span>\n  <span class=\"k\">case</span> <span class=\"nf\">waitlist</span><span class=\"p\">(</span><span class=\"kt\">Int</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"kt\">User</span><span class=\"p\">])</span> <span class=\"c1\">//Contains the position in the waitlist and</span>\n  <span class=\"k\">case</span> <span class=\"nf\">notAllowed</span><span class=\"p\">(</span><span class=\"kt\">String</span><span class=\"p\">)</span> <span class=\"c1\">//Contains the reason why the user is not allowed</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Great! Now, whenever this response needs to be used for being displayed to the user, one can use a <code class=\"language-plaintext highlighter-rouge\">switch</code> statement to check each case and extract the associated values:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">switch</span> <span class=\"n\">confirmationResponse</span> <span class=\"p\">{</span>\n  <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nf\">confirmed</span><span class=\"p\">(</span><span class=\"k\">let</span> <span class=\"nv\">users</span><span class=\"p\">):</span>\n    <span class=\"k\">let</span> <span class=\"nv\">confirmedEventVC</span> <span class=\"o\">=</span> <span class=\"kt\">ConfirmedEventViewController</span><span class=\"p\">(</span><span class=\"nv\">event</span><span class=\"p\">:</span> <span class=\"n\">event</span><span class=\"p\">,</span> <span class=\"nv\">confirmed</span><span class=\"p\">:</span> <span class=\"n\">users</span><span class=\"p\">)</span>\n    <span class=\"nf\">present</span><span class=\"p\">(</span><span class=\"n\">confirmedEventVC</span><span class=\"p\">,</span> <span class=\"nv\">animated</span><span class=\"p\">:</span> <span class=\"kc\">true</span><span class=\"p\">)</span>\n  <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nf\">waitlist</span><span class=\"p\">(</span><span class=\"k\">let</span> <span class=\"nv\">position</span><span class=\"p\">,</span> <span class=\"k\">let</span> <span class=\"nv\">users</span><span class=\"p\">):</span>\n    <span class=\"k\">let</span> <span class=\"nv\">eventWaitlistVC</span> <span class=\"o\">=</span> <span class=\"kt\">EventWaitlistViewController</span><span class=\"p\">(</span><span class=\"nv\">event</span><span class=\"p\">:</span> <span class=\"n\">event</span><span class=\"p\">,</span> <span class=\"nv\">position</span><span class=\"p\">:</span> <span class=\"n\">position</span><span class=\"p\">,</span> <span class=\"nv\">confirmed</span><span class=\"p\">:</span> <span class=\"n\">users</span><span class=\"p\">)</span>\n    <span class=\"nf\">present</span><span class=\"p\">(</span><span class=\"n\">eventWaitlistVC</span><span class=\"p\">,</span> <span class=\"nv\">animated</span><span class=\"p\">:</span> <span class=\"kc\">true</span><span class=\"p\">)</span>\n  <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nf\">notAllowed</span><span class=\"p\">(</span><span class=\"k\">let</span> <span class=\"nv\">reason</span><span class=\"p\">):</span>\n    <span class=\"nf\">presentNotAllowedAlert</span><span class=\"p\">(</span><span class=\"nv\">with</span><span class=\"p\">:</span> <span class=\"n\">reason</span><span class=\"p\">)</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>This looks much better. Now, we want to provide the <code class=\"language-plaintext highlighter-rouge\">EventConfirmationResponse</code> enum to our HTTP client, so it can convert the JSON response directly into the enum: we want it to be <code class=\"language-plaintext highlighter-rouge\">Decodable</code>, which has a great advantage: we hand over the different possibilites to the <code class=\"language-plaintext highlighter-rouge\">JSONDecoder</code>, and if there is any field missing or incompatible with what we described above, the decoding fails. Failing early, in the decoding stage, is better than failing at a UI display stage. Also, it’s worth noting, if the server is also being written in Swift (e.g., with <a href=\"https://vapor.codes\">Vapor</a>), we can make it conform to <code class=\"language-plaintext highlighter-rouge\">Encodable</code>, and <code class=\"language-plaintext highlighter-rouge\">JSONEncoder</code> will take care of converting it exactly into the expected response.</p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">Encodable &amp; Decodable</code> is the exact definition of <code class=\"language-plaintext highlighter-rouge\">Codable</code>. If we add it to our enum and try to compile, we will get the following error:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">extension</span> <span class=\"kt\">EventConfirmationResponse</span><span class=\"p\">:</span> <span class=\"kt\">Codable</span> <span class=\"p\">{}</span>\n\n<span class=\"c1\">//type 'EventConfirmationResponse' does not conform to protocol 'Decodable'</span>\n<span class=\"c1\">//protocol requires initializer 'init(from:)' with type '(from: Decoder)'</span>\n<span class=\"c1\">//type 'EventConfirmationResponse' does not conform to protocol 'Codable'</span>\n<span class=\"c1\">//protocol requires function 'encode(to:)' with type '(Encoder) throws -&gt; ()'</span>\n</code></pre></div></div>\n\n<p>The message is pretty clear. Because Swift doesn’t know how one wants the associated values to be encoded, and there is no defined standard, it doesn’t know what to do, and, consequently, asks the developer to implement them.</p>\n\n<h2 id=\"implementing-the-encodable--decodable-protocols\">Implementing the Encodable &amp; Decodable protocols</h2>\n\n<h4 id=\"encodable\">Encodable</h4>\n\n<p>As the errors stated, there are two methods that need to be implemented. Let’s first do the encoding part, thinking about the JSON declared above, and move to the decoding later on.</p>\n\n<p>The required method by <code class=\"language-plaintext highlighter-rouge\">Encodable</code> is <code class=\"language-plaintext highlighter-rouge\">encode(to encoder: Encoder)</code>. The parameter is a <code class=\"language-plaintext highlighter-rouge\">Encoder</code>, which might be Foundation’s <code class=\"language-plaintext highlighter-rouge\">JSONEncoder</code>, or a custom <code class=\"language-plaintext highlighter-rouge\">XMLEncoder</code>, for example. In order to encode the data, the <code class=\"language-plaintext highlighter-rouge\">Encoder</code> provides three types of encoding containers:</p>\n\n<ol>\n  <li><code class=\"language-plaintext highlighter-rouge\">KeyedEncodingContainer&lt;Key&gt;</code>: to be used when the encoding will have a key-value format, using a <code class=\"language-plaintext highlighter-rouge\">CodingKey</code> enum to access the possible keys, as used when encoding a dictionary. Types that automatically conform to <code class=\"language-plaintext highlighter-rouge\">Encodable</code> will have the <code class=\"language-plaintext highlighter-rouge\">CodingKey</code> generated automatically as well.</li>\n  <li><code class=\"language-plaintext highlighter-rouge\">UnkeyedEncodingContainer</code>: to be used when encoding multiple, unkeyed values, as used when encoding an array, for example.</li>\n  <li><code class=\"language-plaintext highlighter-rouge\">SingleValueEncodingContainer</code>: to be used when a single primitive value, like a string.</li>\n</ol>\n\n<p>The documentation says: <em>You must use only one kind of top-level encoding container</em>. This means that when encoding a value, only one container must be used, and not more than one simultaneously. In our case, we will choose the keyed container, because we will encode our enum into a key-value JSON object.</p>\n\n<p>As mentioned in the explanation of the keyed container, we need to create a <code class=\"language-plaintext highlighter-rouge\">CodingKey</code>-conforming type. We will create a case for each possible key in the JSON. Also, because there are only three acceptable statuses (confirmed, waitlist, and not allowed), we can use a simple enum to ensure the <code class=\"language-plaintext highlighter-rouge\">status</code> value is one of them.</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">//declare which keys in the JSON we are interested in</span>\n<span class=\"kd\">enum</span> <span class=\"kt\">CodingKeys</span><span class=\"p\">:</span> <span class=\"kt\">String</span><span class=\"p\">,</span> <span class=\"kt\">CodingKey</span> <span class=\"p\">{</span>\n    <span class=\"k\">case</span> <span class=\"n\">status</span>\n    <span class=\"k\">case</span> <span class=\"n\">confirmedUsers</span>\n    <span class=\"k\">case</span> <span class=\"n\">position</span>\n    <span class=\"k\">case</span> <span class=\"n\">reason</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">//declare the possible values os the status key</span>\n<span class=\"kd\">private</span> <span class=\"kd\">enum</span> <span class=\"kt\">EventConfirmationStatus</span><span class=\"p\">:</span> <span class=\"kt\">String</span><span class=\"p\">,</span> <span class=\"kt\">Codable</span> <span class=\"p\">{</span>\n    <span class=\"k\">case</span> <span class=\"n\">confirmed</span>\n    <span class=\"k\">case</span> <span class=\"n\">waitlist</span>\n    <span class=\"k\">case</span> <span class=\"n\">notAllowed</span> <span class=\"o\">=</span> <span class=\"s\">\"not allowed\"</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Notice that in both enums, where the raw value is a string, there is no need to actually declare it - the cases are compiled into the raw values (except the <code class=\"language-plaintext highlighter-rouge\">notAllowed</code> case). Now it’s left to implement the encoding itself. We will need to do two things: (1) get the keyed container from the encoder, and (2) iterate over the event confirmation enum in order to encode each case, separately:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">extension</span> <span class=\"kt\">EventConfirmationResponse</span><span class=\"p\">:</span> <span class=\"kt\">Encodable</span> <span class=\"p\">{</span>\n  <span class=\"kd\">func</span> <span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"n\">to</span> <span class=\"nv\">encoder</span><span class=\"p\">:</span> <span class=\"kt\">Encoder</span><span class=\"p\">)</span> <span class=\"k\">throws</span> <span class=\"p\">{</span>\n      <span class=\"c1\">//access the keyed container</span>\n      <span class=\"k\">var</span> <span class=\"nv\">container</span> <span class=\"o\">=</span> <span class=\"n\">encoder</span><span class=\"o\">.</span><span class=\"nf\">container</span><span class=\"p\">(</span><span class=\"nv\">keyedBy</span><span class=\"p\">:</span> <span class=\"kt\">CodingKeys</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">)</span>\n\n      <span class=\"c1\">//iterate over self and encode (1) the status and (2) the associated value(s)</span>\n      <span class=\"k\">switch</span> <span class=\"k\">self</span> <span class=\"p\">{</span>\n      <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nf\">confirmed</span><span class=\"p\">(</span><span class=\"k\">let</span> <span class=\"nv\">users</span><span class=\"p\">):</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"kt\">EventConfirmationStatus</span><span class=\"o\">.</span><span class=\"n\">confirmed</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">status</span><span class=\"p\">)</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"n\">users</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">confirmedUsers</span><span class=\"p\">)</span>\n      <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nf\">waitlist</span><span class=\"p\">(</span><span class=\"k\">let</span> <span class=\"nv\">position</span><span class=\"p\">,</span> <span class=\"k\">let</span> <span class=\"nv\">users</span><span class=\"p\">):</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"kt\">EventConfirmationStatus</span><span class=\"o\">.</span><span class=\"n\">waitlist</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">status</span><span class=\"p\">)</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"n\">users</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">confirmedUsers</span><span class=\"p\">)</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"n\">position</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">position</span><span class=\"p\">)</span>\n      <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nf\">notAllowed</span><span class=\"p\">(</span><span class=\"k\">let</span> <span class=\"nv\">reason</span><span class=\"p\">):</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"kt\">EventConfirmationStatus</span><span class=\"o\">.</span><span class=\"n\">notAllowed</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">status</span><span class=\"p\">)</span>\n          <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"n\">reason</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">reason</span><span class=\"p\">)</span>\n      <span class=\"p\">}</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>We can now use <code class=\"language-plaintext highlighter-rouge\">JSONEncoder().encode(confirmation)</code> and get a JSON representation of our enum.</p>\n\n<h4 id=\"decodable\">Decodable</h4>\n\n<p>To finally conform do <code class=\"language-plaintext highlighter-rouge\">Codable</code>, there’s left the <code class=\"language-plaintext highlighter-rouge\">Decodable</code> protocol. To achieve it, we need to initialize our enum given a <code class=\"language-plaintext highlighter-rouge\">Decoder</code> with <code class=\"language-plaintext highlighter-rouge\">init(from decoder: Decoder)</code>.</p>\n\n<p>Similar <code class=\"language-plaintext highlighter-rouge\">Encoder</code>, <code class=\"language-plaintext highlighter-rouge\">Decoder</code> also has the three analogue containers. As all 3 states have a <code class=\"language-plaintext highlighter-rouge\">status</code> key and we need it to define which state will be initialized, we will look for it first by trying to decode a <code class=\"language-plaintext highlighter-rouge\">String</code> for the <code class=\"language-plaintext highlighter-rouge\">.status</code> coding key. Then, we iterate on the status value, and look for the other values for the relevant keys:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">extension</span> <span class=\"kt\">EventConfirmationResponse</span><span class=\"p\">:</span> <span class=\"kt\">Decodable</span> <span class=\"p\">{</span>\n    <span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"n\">from</span> <span class=\"nv\">decoder</span><span class=\"p\">:</span> <span class=\"kt\">Decoder</span><span class=\"p\">)</span> <span class=\"k\">throws</span> <span class=\"p\">{</span>\n        <span class=\"c1\">//access the keyed container</span>\n        <span class=\"k\">let</span> <span class=\"nv\">container</span> <span class=\"o\">=</span> <span class=\"k\">try</span> <span class=\"n\">decoder</span><span class=\"o\">.</span><span class=\"nf\">container</span><span class=\"p\">(</span><span class=\"nv\">keyedBy</span><span class=\"p\">:</span> <span class=\"kt\">CodingKeys</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">)</span>\n\n        <span class=\"c1\">//decode the value for the status key into the EventConfirmationStatus enum</span>\n        <span class=\"k\">let</span> <span class=\"nv\">status</span> <span class=\"o\">=</span> <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">decode</span><span class=\"p\">(</span><span class=\"kt\">EventConfirmationStatus</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">status</span><span class=\"p\">)</span>\n\n        <span class=\"c1\">//iterate over the received status, and try to decode the other relevant values</span>\n        <span class=\"k\">switch</span> <span class=\"n\">status</span> <span class=\"p\">{</span>\n        <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nv\">confirmed</span><span class=\"p\">:</span>\n            <span class=\"k\">let</span> <span class=\"nv\">users</span> <span class=\"o\">=</span> <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">decode</span><span class=\"p\">([</span><span class=\"kt\">User</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">confirmedUsers</span><span class=\"p\">)</span>\n            <span class=\"k\">self</span> <span class=\"o\">=</span> <span class=\"o\">.</span><span class=\"nf\">confirmed</span><span class=\"p\">(</span><span class=\"n\">users</span><span class=\"p\">)</span>\n        <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nv\">waitlist</span><span class=\"p\">:</span>\n            <span class=\"k\">let</span> <span class=\"nv\">users</span> <span class=\"o\">=</span> <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">decode</span><span class=\"p\">([</span><span class=\"kt\">User</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">confirmedUsers</span><span class=\"p\">)</span>\n            <span class=\"k\">let</span> <span class=\"nv\">position</span> <span class=\"o\">=</span> <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">decode</span><span class=\"p\">(</span><span class=\"kt\">Int</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">position</span><span class=\"p\">)</span>\n            <span class=\"k\">self</span> <span class=\"o\">=</span> <span class=\"o\">.</span><span class=\"nf\">waitlist</span><span class=\"p\">(</span><span class=\"n\">position</span><span class=\"p\">,</span> <span class=\"n\">users</span><span class=\"p\">)</span>\n        <span class=\"k\">case</span> <span class=\"o\">.</span><span class=\"nv\">notAllowed</span><span class=\"p\">:</span>\n            <span class=\"k\">let</span> <span class=\"nv\">reason</span> <span class=\"o\">=</span> <span class=\"k\">try</span> <span class=\"n\">container</span><span class=\"o\">.</span><span class=\"nf\">decode</span><span class=\"p\">(</span><span class=\"kt\">String</span><span class=\"o\">.</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">forKey</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">reason</span><span class=\"p\">)</span>\n            <span class=\"k\">self</span> <span class=\"o\">=</span> <span class=\"o\">.</span><span class=\"nf\">notAllowed</span><span class=\"p\">(</span><span class=\"n\">reason</span><span class=\"p\">)</span>\n        <span class=\"p\">}</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Done! Our enum is now ready to be encoded and decoded. If you want to test and see all the code in a single place, I’ve prepared a <a href=\"https://files.natanrolnik.me/blog-downloads/CodableEnumsWithAssociatedValues.playground.zip\">playground which you can download here</a>.</p>\n\n<hr />\n\n<h5 id=\"in-a-paragraph\">In a Paragraph</h5>\n\n<p>Enums with associated values provide expected scenarios to the developer dealing with it, leaving out uncertainties and ambiguities. Leveraging the <code class=\"language-plaintext highlighter-rouge\">Codable</code> protocol by implementing only 2 methods, server or client side Swift apps can send and receive the enums data representations in a standardized way, making things more predictable and safe. You can <a href=\"https://files.natanrolnik.me/blog-downloads/CodableEnumsWithAssociatedValues.playground.zip\">download the playground</a> to play with it.</p>\n\n<hr />\n\n<p><em>Thanks to <a href=\"https://twitter.com/rockthebruno\">Bruno Rocha</a> and <a href=\"https://twitter.com/twannl\">Antoine v.d. Lee</a> for reviewing this post</em></p>",
            "summary": "One of Swift’s greatest features, and one of my favorites, are enums with associated values. The language itself uses them for its fundamentals, like Optional&lt;T&gt;, which either has a .some(T) or is .none. Another example is the new since Swift 5 Result&lt;T, E&gt;, which either contains a .success(T) or a.failure(E) case. In this post, we will go over cases (no pun intended) where an enum is more suitable than a struct or class, and also learn how one can make enums with associated values conform to Codable, achieving a better and safer usage of these data representations when they need to be encoded and decoded. You can scroll to the end of the post to get the final playground.",
            "date_published": "2019-05-15T09:00:00+00:00",
            "date_modified": "2019-05-15T09:00:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": ["Codable","Enum"]},{
            "id": "https://blog.natanrolnik.me/ProtocolsWithObjcFunctions",
            "url": "https://blog.natanrolnik.me/protocols-default-impl-control-handling",
            "title": "Protocols Default Implementations with UIControl.Event handling",
            "content_html": "<p>Since Swift’s introduction, a lot was covered about Protocol Oriented Programming (aka POP). In contrast to Object Oriented design, which is based in inheritance, POP allows your objects and types to “wear many hats”. Instead of making an object inherit functions from its superclass(es), using protocols can make it more flexible and modular by implementing a protocol’s methods.</p>\n\n<p>Swift 2 introduced a huge factor in favor of using protocols: default implementation. Let’s start with an example. <code class=\"language-plaintext highlighter-rouge\">ScrollRefreshable</code> will make it easier to add a <code class=\"language-plaintext highlighter-rouge\">UIRefreshControl</code> to our <code class=\"language-plaintext highlighter-rouge\">UIScrollView</code>s and handle the refresh action.</p>\n\n<p><em>(If you already know about default implementations, you can skip to the ‘Refining The Protocol’ or the ‘The Roadblocks’ section)</em></p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">protocol</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n  <span class=\"k\">var</span> <span class=\"nv\">scrollView</span><span class=\"p\">:</span> <span class=\"kt\">UIScrollView</span> <span class=\"p\">{</span> <span class=\"k\">get</span> <span class=\"p\">}</span>\n  <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">()</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Before default implementation became available, we would implement it this way:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">// Make MyViewController implement the scrollView property and the addRefreshControl method</span>\n<span class=\"kd\">extension</span> <span class=\"kt\">MyViewController</span><span class=\"p\">:</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n  <span class=\"k\">var</span> <span class=\"nv\">scrollView</span><span class=\"p\">:</span> <span class=\"kt\">UIScrollView</span> <span class=\"p\">{</span>\n    <span class=\"k\">return</span> <span class=\"n\">collectionView</span>\n  <span class=\"p\">}</span>\n\n  <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n    <span class=\"k\">let</span> <span class=\"nv\">refreshControl</span> <span class=\"o\">=</span> <span class=\"kt\">UIRefreshControl</span><span class=\"p\">()</span>\n    <span class=\"n\">refreshControl</span><span class=\"o\">.</span><span class=\"nf\">addTarget</span><span class=\"p\">(</span><span class=\"k\">self</span><span class=\"p\">,</span>\n                             <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"kd\">#selector(</span><span class=\"nf\">refreshTriggered</span><span class=\"kd\">)</span><span class=\"p\">,</span>\n                             <span class=\"nv\">for</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">valueChanged</span><span class=\"p\">)</span>\n    <span class=\"n\">scrollView</span><span class=\"o\">.</span><span class=\"n\">refreshControl</span> <span class=\"o\">=</span> <span class=\"n\">refreshControl</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n\n<span class=\"kd\">extension</span> <span class=\"kt\">MyViewController</span> <span class=\"p\">{</span>\n  <span class=\"kd\">@objc</span> <span class=\"kd\">func</span> <span class=\"nf\">refreshTriggered</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n    <span class=\"c1\">//call server and fetch data</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Now, with protocol default implementations, we could change things a bit:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">protocol</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n  <span class=\"k\">var</span> <span class=\"nv\">scrollView</span><span class=\"p\">:</span> <span class=\"kt\">UIScrollView</span> <span class=\"p\">{</span> <span class=\"k\">get</span> <span class=\"p\">}</span>\n  <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">(</span><span class=\"nv\">target</span><span class=\"p\">:</span> <span class=\"kt\">Any</span><span class=\"p\">,</span> <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"kt\">Selector</span><span class=\"p\">)</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">//add a default implementation for adding the control</span>\n<span class=\"kd\">extension</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n  <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">(</span><span class=\"nv\">target</span><span class=\"p\">:</span> <span class=\"kt\">Any</span><span class=\"p\">,</span> <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"kt\">Selector</span><span class=\"p\">)</span> <span class=\"p\">{</span>\n    <span class=\"k\">let</span> <span class=\"nv\">refreshControl</span> <span class=\"o\">=</span> <span class=\"kt\">UIRefreshControl</span><span class=\"p\">()</span>\n    <span class=\"n\">refreshControl</span><span class=\"o\">.</span><span class=\"nf\">addTarget</span><span class=\"p\">(</span><span class=\"n\">target</span><span class=\"p\">,</span> <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"n\">action</span><span class=\"p\">,</span> <span class=\"nv\">for</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">valueChanged</span><span class=\"p\">)</span>\n    <span class=\"n\">scrollView</span><span class=\"o\">.</span><span class=\"n\">refreshControl</span> <span class=\"o\">=</span> <span class=\"n\">refreshControl</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">// Make MyViewController conform to ScrollRefreshable</span>\n<span class=\"kd\">extension</span> <span class=\"kt\">MyViewController</span><span class=\"p\">:</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n  <span class=\"k\">var</span> <span class=\"nv\">scrollView</span><span class=\"p\">:</span> <span class=\"kt\">UIScrollView</span> <span class=\"p\">{</span>\n    <span class=\"k\">return</span> <span class=\"n\">collectionView</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\">//Add a method that we will pass to addRefreshControl in the action parameter</span>\n<span class=\"kd\">extension</span> <span class=\"kt\">MyViewController</span> <span class=\"p\">{</span>\n  <span class=\"kd\">@objc</span> <span class=\"kd\">func</span> <span class=\"nf\">refreshTriggered</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n    <span class=\"c1\">//call server and fetch data</span>\n  <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Now, anyone who wants to conform to <code class=\"language-plaintext highlighter-rouge\">ScrollRefreshable</code> won’t need to implement the addRefreshControl function. This is nice, but it’s been around for a few years, and also, we can do more to improve it.</p>\n\n<h2 id=\"refining-the-protocol\">Refining the Protocol</h2>\n\n<p>The above protocol might be a better solution in some cases (by passing target and action), but for the exercise, we will try to add <code class=\"language-plaintext highlighter-rouge\">refreshTriggered()</code> to the protocol, and passing it as the action. The following code <strong>will not compile</strong>:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">protocol</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n    <span class=\"k\">var</span> <span class=\"nv\">scrollView</span><span class=\"p\">:</span> <span class=\"kt\">UIScrollView</span> <span class=\"p\">{</span> <span class=\"k\">get</span> <span class=\"p\">}</span>\n    <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">()</span>\n    <span class=\"kd\">func</span> <span class=\"nf\">refreshTriggered</span><span class=\"p\">()</span>\n<span class=\"p\">}</span>\n\n<span class=\"kd\">extension</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n    <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n        <span class=\"k\">let</span> <span class=\"nv\">refreshControl</span> <span class=\"o\">=</span> <span class=\"kt\">UIRefreshControl</span><span class=\"p\">()</span>\n        <span class=\"n\">refreshControl</span><span class=\"o\">.</span><span class=\"nf\">addTarget</span><span class=\"p\">(</span><span class=\"k\">self</span><span class=\"p\">,</span> <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"kd\">#selector(</span><span class=\"nf\">refreshTriggered</span><span class=\"kd\">)</span><span class=\"p\">,</span> <span class=\"nv\">for</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">valueChanged</span><span class=\"p\">)</span> <span class=\"c1\">//DOESN'T COMPILE</span>\n        <span class=\"n\">scrollView</span><span class=\"o\">.</span><span class=\"n\">refreshControl</span> <span class=\"o\">=</span> <span class=\"n\">refreshControl</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Can you try guessing why? It’s because <code class=\"language-plaintext highlighter-rouge\">refreshTriggered</code>is not exposed to the Objective C runtime. This is what the compiler says: <code class=\"language-plaintext highlighter-rouge\">Argument of '#selector' refers to instance method 'refreshTriggered()' that is not exposed to Objective-C</code>.</p>\n\n<p>To fix it, we could try adding <code class=\"language-plaintext highlighter-rouge\">@objc</code> to the function in the protocol definition, which gives us another error: <code class=\"language-plaintext highlighter-rouge\">@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes</code>.  The solution for this is adding <code class=\"language-plaintext highlighter-rouge\">@objc</code> to the protocol itself, as suggested by the compiler’s message.</p>\n\n<h2 id=\"the-roadblocks\">The Roadblocks</h2>\n\n<p>The approach of making our protocol <code class=\"language-plaintext highlighter-rouge\">@objc</code> has a few different problems: if the protocol has any features not available in Objective C, it won’t work. These might be:</p>\n\n<ul>\n  <li><a href=\"https://www.hackingwithswift.com/example-code/language/what-is-a-protocol-associated-type\"><strong>associated types</strong></a>: results in <code class=\"language-plaintext highlighter-rouge\">Associated type 'Item' cannot be declared inside '@objc' protocol 'ScrollRefreshable'</code>;</li>\n  <li><strong>Swift enums or another non-objc protocol/type</strong>: results in<code class=\"language-plaintext highlighter-rouge\">Method cannot be a member of an @objc protocol because the type of the parameter cannot be represented in Objective-C</code> or <code class=\"language-plaintext highlighter-rouge\">Method cannot be a member of an @objc protocol because its result type cannot be represented in Objective-C</code>;</li>\n  <li><strong>trying to implement the protocol in a struct</strong>: results in <code class=\"language-plaintext highlighter-rouge\">Non-class type 'MyStruct' cannot conform to class protocol 'AnotherScrollRefreshable'</code></li>\n</ul>\n\n<p>Ideally, we should automatically call <code class=\"language-plaintext highlighter-rouge\">refreshTriggered()</code> while keeping our protocol not constrained to be <code class=\"language-plaintext highlighter-rouge\">@objc</code>.</p>\n\n<h2 id=\"objective-c-runtime-to-the-rescue\">Objective-C runtime to the rescue</h2>\n\n<p>Fortunately, we can still use the default implementation of <code class=\"language-plaintext highlighter-rouge\">addRefreshControl()</code> while keeping our protocol away from being @objc only. And we will use the Objective-C runtime for that. If we add support for passing a block to execute when a <code class=\"language-plaintext highlighter-rouge\">UIControl.Event</code> happens, we don’t need to rely on the target-action pattern from within the protocol extension directly.</p>\n\n<p>To do so, let’s create a wrapper, that receives a simple <code class=\"language-plaintext highlighter-rouge\">() -&gt; Void</code> block:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">class</span> <span class=\"kt\">ClosureWrapper</span> <span class=\"p\">{</span>\n    <span class=\"k\">let</span> <span class=\"nv\">closure</span><span class=\"p\">:</span> <span class=\"p\">()</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span>\n\n    <span class=\"nf\">init</span><span class=\"p\">(</span><span class=\"nv\">closure</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">()</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span> <span class=\"p\">{</span>\n        <span class=\"k\">self</span><span class=\"o\">.</span><span class=\"n\">closure</span> <span class=\"o\">=</span> <span class=\"n\">closure</span>\n    <span class=\"p\">}</span>\n\n    <span class=\"kd\">@objc</span> <span class=\"kd\">func</span> <span class=\"nf\">invoke</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n        <span class=\"nf\">closure</span><span class=\"p\">()</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>The code above simply receives a block and runs it when <code class=\"language-plaintext highlighter-rouge\">invoke()</code> is called. Now, we will add it as the target of our <code class=\"language-plaintext highlighter-rouge\">UIRefreshControl</code> with this handy <code class=\"language-plaintext highlighter-rouge\">UIControl</code> extension:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">extension</span> <span class=\"kt\">UIControl</span> <span class=\"p\">{</span>\n    <span class=\"kd\">func</span> <span class=\"nf\">addAction</span><span class=\"p\">(</span><span class=\"k\">for</span> <span class=\"nv\">controlEvents</span><span class=\"p\">:</span> <span class=\"kt\">UIControl</span><span class=\"o\">.</span><span class=\"kt\">Event</span><span class=\"p\">,</span> <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"kd\">@escaping</span> <span class=\"p\">()</span> <span class=\"o\">-&gt;</span> <span class=\"kt\">Void</span><span class=\"p\">)</span> <span class=\"p\">{</span>\n        <span class=\"k\">let</span> <span class=\"nv\">wrapper</span> <span class=\"o\">=</span> <span class=\"kt\">ClosureWrapper</span><span class=\"p\">(</span><span class=\"nv\">closure</span><span class=\"p\">:</span> <span class=\"n\">action</span><span class=\"p\">)</span>\n        <span class=\"nf\">addTarget</span><span class=\"p\">(</span><span class=\"n\">wrapper</span><span class=\"p\">,</span> <span class=\"nv\">action</span><span class=\"p\">:</span> <span class=\"kd\">#selector(</span><span class=\"nf\">ClosureWrapper.invoke</span><span class=\"kd\">)</span><span class=\"p\">,</span> <span class=\"nv\">for</span><span class=\"p\">:</span> <span class=\"n\">controlEvents</span><span class=\"p\">)</span>\n        <span class=\"nf\">objc_setAssociatedObject</span><span class=\"p\">(</span><span class=\"k\">self</span><span class=\"p\">,</span>\n                           <span class=\"s\">\"[</span><span class=\"se\">\\(</span><span class=\"nf\">arc4random</span><span class=\"p\">()</span><span class=\"se\">)</span><span class=\"s\">]\"</span><span class=\"p\">,</span>\n                           <span class=\"n\">wrapper</span><span class=\"p\">,</span>\n                           <span class=\"o\">.</span><span class=\"kt\">OBJC_ASSOCIATION_RETAIN</span><span class=\"p\">)</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<p>Let’s see what this <code class=\"language-plaintext highlighter-rouge\">UIControl</code> extension method does:</p>\n\n<ol>\n  <li>Wrap the receive <code class=\"language-plaintext highlighter-rouge\">action</code> block in a <code class=\"language-plaintext highlighter-rouge\">ClosureWrapper</code>;</li>\n  <li>Add it as the target and action of the <code class=\"language-plaintext highlighter-rouge\">UIControl</code> (in this case, <code class=\"language-plaintext highlighter-rouge\">self</code>);</li>\n  <li>And here comes the most important detail. Because <code class=\"language-plaintext highlighter-rouge\">wrapper</code> was created in the function scope, it would go away at the end of the function. To avoid that, we attach it to the <code class=\"language-plaintext highlighter-rouge\">UIControl</code> itself using <code class=\"language-plaintext highlighter-rouge\">objc_setAssociatedObject</code> - so whenever the <code class=\"language-plaintext highlighter-rouge\">UIControl</code> is alive, the <code class=\"language-plaintext highlighter-rouge\">wrapper</code> we just created will be kept in the memory as well.</li>\n</ol>\n\n<p>With this, we can solve our problem in an elegant way, instead of using target-action:</p>\n\n<div class=\"language-swift highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">extension</span> <span class=\"kt\">ScrollRefreshable</span> <span class=\"p\">{</span>\n    <span class=\"kd\">func</span> <span class=\"nf\">addRefreshControl</span><span class=\"p\">()</span> <span class=\"p\">{</span>\n              <span class=\"k\">let</span> <span class=\"nv\">refreshControl</span> <span class=\"o\">=</span> <span class=\"kt\">UIRefreshControl</span><span class=\"p\">()</span>\n        <span class=\"n\">refreshControl</span><span class=\"o\">.</span><span class=\"nf\">addAction</span><span class=\"p\">(</span><span class=\"nv\">for</span><span class=\"p\">:</span> <span class=\"o\">.</span><span class=\"n\">valueChanged</span><span class=\"p\">)</span> <span class=\"p\">{</span> <span class=\"p\">[</span><span class=\"k\">weak</span> <span class=\"k\">self</span><span class=\"p\">]</span> <span class=\"k\">in</span>\n            <span class=\"k\">self</span><span class=\"p\">?</span><span class=\"o\">.</span><span class=\"nf\">refreshControlTriggered</span><span class=\"p\">()</span>\n        <span class=\"p\">}</span>\n        <span class=\"n\">scrollView</span><span class=\"o\">.</span><span class=\"n\">refreshControl</span> <span class=\"o\">=</span> <span class=\"n\">refreshControl</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div></div>\n\n<hr />\n\n<h5 id=\"in-a-paragraph\">In a Paragraph</h5>\n\n<p>Protocols allow us to make our objects more flexible, and default implementations helps implementing them in a concise way. With a bit of creativity and using the Objective C runtime, we can get rid of the <code class=\"language-plaintext highlighter-rouge\">@objc</code> protocol constraint whenever the target-action pattern is required in a protocol extension (as in  <code class=\"language-plaintext highlighter-rouge\">UIButton</code> or any other <code class=\"language-plaintext highlighter-rouge\">UIControl</code>).</p>\n\n<p>Feel free to add any comments below, or ping me on twitter if you have any suggestions or ideas: <a href=\"https://twitter.com/natanrolnik\">@natanrolnik</a></p>",
            "summary": "Since Swift’s introduction, a lot was covered about Protocol Oriented Programming (aka POP). In contrast to Object Oriented design, which is based in inheritance, POP allows your objects and types to “wear many hats”. Instead of making an object inherit functions from its superclass(es), using protocols can make it more flexible and modular by implementing a protocol’s methods.",
            "date_published": "2019-04-01T09:00:00+00:00",
            "date_modified": "2019-04-01T09:00:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": []},{
            "id": "https://blog.natanrolnik.me/DispatchWorkItem",
            "url": "https://blog.natanrolnik.me/dispatch-work-item",
            "title": "Using DispatchWorkItem to delay (and cancel) tasks",
            "content_html": "<p>Performing delayed tasks and working with multithreading in Cocoa became much simpler since the introduction of GCD - Grand Central Dispatch. Before it existed, delaying a task would require using <code class=\"language-plaintext highlighter-rouge\">NSThread</code> and/or <code class=\"language-plaintext highlighter-rouge\">NSOperationQueue</code>, or the simple but limited <code class=\"language-plaintext highlighter-rouge\">performSelector:withObject:afterDelay:</code> method available in <code class=\"language-plaintext highlighter-rouge\">NSObject</code>.</p>\n\n<p>While <code class=\"language-plaintext highlighter-rouge\">NSOperation</code>s are better, in general, when you need to manage multiple tasks that can be added to a queue (like sequential image downloads, for example), GCD allows a simpler API to run blocks of code with the <code class=\"language-plaintext highlighter-rouge\">dispatch_after</code> (Objective-C) and <code class=\"language-plaintext highlighter-rouge\">DispatchQueue.main.asyncAfter</code> methods.</p>\n\n<h3 id=\"when-to-use-a-dispatchworkitem\">When to use a <code class=\"language-plaintext highlighter-rouge\">DispatchWorkItem</code></h3>\n\n<p>With a practical example in mind, assuming we want to show a hint indicating that our messenger app supports voice messages now. To do so, we’ll make the microphone button jump:</p>\n\n<noscript><pre>400: Invalid request</pre></noscript>\n<script src=\"https://gist.github.com/fe41bce3c4f6f9e973999d8069724f87.js\"> </script>\n\n<p>If you’ve been developing with Swift for a while, chances are high you already used this API. Now, imagine that, if the user found the button before it jumped - we definitely don’t want to trigger the hint. We could do it in a way - not the cleanest one:</p>\n\n<noscript><pre>400: Invalid request</pre></noscript>\n<script src=\"https://gist.github.com/6dbeaaef228253824457910a2f335831.js\"> </script>\n\n<p>This is how we would to it before knowing about <a href=\"https://developer.apple.com/documentation/dispatch/dispatchworkitem\"><code class=\"language-plaintext highlighter-rouge\">DispatchWorkItem</code></a>. Let’s compare with how this can be achieved, but using <code class=\"language-plaintext highlighter-rouge\">DispatchWorkItem</code>:</p>\n\n<noscript><pre>400: Invalid request</pre></noscript>\n<script src=\"https://gist.github.com/96f28038cd67ec740584c6446a498f41.js\"> </script>\n\n<p>Isn’t it much better? I believe so, for a few reasons. First, every task can be assigned to a different work item. Secondly, in case we want to cancel it, there is no need to keep one state variable for each task.</p>\n\n<p>It is worth noting that, although GCD is available in both Objective-C and Swift, <code class=\"language-plaintext highlighter-rouge\">DispatchWorkItem</code> Swift only.</p>\n\n<h3 id=\"diy---keep-things-simple-while-you-can\">DIY - Keep things simple while you can</h3>\n\n<p>A few months ago, <a href=\"https://twitter.com/_inside\">Guilherme Rambo</a> tweeted a great example of <strong>how easily</strong> this API can be used to create things that, often, we consider using a framework for.</p>\n\n<div class=\"jekyll-twitter-plugin\" style=\"text-align: center;\"><blockquote class=\"twitter-tweet\"><p lang=\"en\" dir=\"ltr\">DispatchWorkItem ❤️ <a href=\"https://t.co/6gxCLA4Wmo\">pic.twitter.com/6gxCLA4Wmo</a></p>&mdash; Guilherme Rambo (@_inside) <a href=\"https://twitter.com/_inside/status/984827954432798723?ref_src=twsrc%5Etfw\">April 13, 2018</a></blockquote>\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n\n</div>\n\n<p>With less than 30 lines, Guilherme showed us how to create a simple throttler for a specific UI event. Within his tweet’s replies, some people suggested he should try RxSwift, as it offers the built in <code class=\"language-plaintext highlighter-rouge\">.throttle()</code> and <code class=\"language-plaintext highlighter-rouge\">.debounce()</code> operators. Well, if we have a project that is already using it, fine. But if we don’t want to add to our app a new dependency, I believe it makes more sense to <a href=\"https://twitter.com/RebeccaSlatkin/status/1093775699905785856\">keep things simple</a>. My rule of thumb is: <strong>Always prefer system APIs and simplicity over 3rd party frameworks when possible</strong>.</p>\n\n<p>Of course, Gui’s example is a specific use case. But with little effort we could make it something more generic. For example, that listens to <code class=\"language-plaintext highlighter-rouge\">NotificationCenter</code> and throttles a <code class=\"language-plaintext highlighter-rouge\">Notification</code> when it’s posted:</p>\n\n<noscript><pre>400: Invalid request</pre></noscript>\n<script src=\"https://gist.github.com/398b1ee0bda3995a8f6a99d2084513ca.js\"> </script>\n\n<h3 id=\"managing-multiple-work-items\">Managing multiple work items</h3>\n\n<p>If we end up having multiple work items managed by the same view controller, we should think if the current design is correct. One way to fix it is splitting the responsibilities of a view controller in multiple child view controllers. If we tried doing so and still have 3 or 4 work items that need to be managed by the same view controller, having them as multiple references is far from ideal.</p>\n\n<p>A solution that I came up with, was creating a <code class=\"language-plaintext highlighter-rouge\">Dispatcher</code> object, that would manage the work items according to an identifier. It should allow:</p>\n\n<ol>\n  <li>Scheduling multiple tasks by identifier (a string) and delay (time interval);</li>\n  <li>Overwriting (cancelling and rescheduling) a scheduled task if a task with the same identifier already exists;</li>\n  <li>Cancelling tasks by identifier;</li>\n  <li>Cancel all tasks when it is deallocated</li>\n</ol>\n\n<p>After a few iterations and inputs from friends, I was able to get to this (you can see the <a href=\"https://gist.github.com/natanrolnik/6c1d9baa04ebc163f52bd5224db32d07\">playground version here</a>):</p>\n\n<noscript><pre>400: Invalid request</pre></noscript>\n<script src=\"https://gist.github.com/1a5d07ea79ba529eafb9b03d21111705.js\"> </script>\n\n<hr />\n\n<h5 id=\"in-a-paragraph\">In a Paragraph</h5>\n\n<p>GCD and <code class=\"language-plaintext highlighter-rouge\">DispatchWorkItem</code>s are provide us a simple way to perform powerful and complex tasks, that would require us using different or older APIs. Sticking to it might save us from unnecessary frameworks or wrong abstractions and architectures.</p>\n\n<p>Feel free to add any comments below, or ping me on twitter if you have any suggestions or ideas: <a href=\"https://twitter.com/natanrolnik\">@natanrolnik</a></p>",
            "summary": "Performing delayed tasks and working with multithreading in Cocoa became much simpler since the introduction of GCD - Grand Central Dispatch. Before it existed, delaying a task would require using NSThread and/or NSOperationQueue, or the simple but limited performSelector:withObject:afterDelay: method available in NSObject.",
            "date_published": "2019-02-14T13:10:00+00:00",
            "date_modified": "2019-02-14T13:10:00+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": []},{
            "id": "https://blog.natanrolnik.me/wwdc-16-past-and-future",
            "url": "https://blog.natanrolnik.me/wwdc16-past-and-future",
            "title": "WWDC 16 - Past and Future",
            "content_html": "<p>I can’t believe it’s already been three years since I visited San Francisco for the first and only time. In the same way that the tickets that year were sold out in 70 seconds, that unforgettable week, where Apple announced iOS 7 and Mavericks, passed like lightning. It’s hard to to express how much I’m excited for the next week, both as a member of the iOS worldwide community and as a programmer. <em>Yes, Dub Dub is already in the next week!</em>\nIn three years, <em>generally speaking</em>, a lot can happen in someone’s life. But in tech, things move faster, and in three years things change a LOT more. Just to understand to what degree iOS is maturing and the community is evolving together, I’ll list a few jaw dropping facts that were reality right before WWDC 13.</p>\n\n<p>In the iOS/OS X world:</p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">UIAlertView</code>s and <code class=\"language-plaintext highlighter-rouge\">UIActionSheet</code>s and their delegates weren’t deprecated yet 😩</li>\n  <li><a href=\"http://core0.staticworld.net/images/article/2013/06/photo-jun-17-3-34-21-pm-100042569-large.png\">Skeumorphism was</a> <a href=\"http://core0.staticworld.net/images/article/2013/06/photo-jun-17-6-03-18-pm-100042568-orig.png\">awesome</a></li>\n  <li>AutoLayout in Interface Builder wasn’t as easy as it is today and had tons of bugs</li>\n  <li>Stack Views? I’m still using Auto Resizing masks 🙈</li>\n  <li>Creating a CGRect with a 320 width was “ok”</li>\n  <li>The sandbox world was merciless and app extensions was a mere dream</li>\n  <li>Hosted Parse.com (RIP 😢) was the best option to effortlessly save data in the cloud, and there was no CloudKit</li>\n  <li>Networking was done with NSURLConnection</li>\n  <li>And of course… There was no Swift 😱</li>\n</ul>\n\n<p>And in the iOS community:</p>\n<ul>\n  <li><a href=\"https://cocoapods.org\">CocoaPods</a> was around version 0.20 - it took a lot of effort to reach 1.0 a few weeks ago. Congratulations to the CocoaPods team for reaching this huge milestone!</li>\n  <li><a href=\"https://fastlane.tools\">Fastlane</a> would be crazier than any dream - yes, or you had to write ugly scripts, or to do it manually, again and again. Felix, you rock! In the name of the iOS community: we ❤️ you.</li>\n  <li><a href=\"https://realm.io\">Realm</a> didn’t exist yet - congratulations to the team for the 1.0 launch! The incredible work they do for the iOS community, posting good quality videos (with captions and summary!) also needs to be mentioned. Thank you 👏</li>\n  <li><a href=\"https://fabric.io\">Crashlytics</a> was still in Beta</li>\n  <li>We didn’t have <a href=\"https://littlebitesofcocoa.com\">Little Bites Of Cocoa</a> to sweeten our days 🍫</li>\n  <li>You or the designer you work with, probably still used Photoshop. <a href=\"https://sketchapp.com\">Sketch</a> FTW!</li>\n  <li><a href=\"https://nsscreencast.com\">NSScreencast</a> had almost 25% the amount of videos available today</li>\n  <li><a href=\"https://github.com/carthage/carthage\">Carthage</a> also didn’t exist!</li>\n</ul>\n\n<p>Is it only me, or when you look back to all these changes, knowing how things were different and hard before, you are also proud to experience all these changes while they happen? How cool is to <a href=\"https://www.youtube.com/watch?v=LcGPI2tV2yY\">watch this video</a> again and again, and to remember the excitement for the new iOS that was coming?</p>\n\n<p>As a pre-WWDC post, I also can’t skip my (humble, I admit) wishlist:</p>\n<ul>\n  <li>A dark mode on iOS. Is the updated WWDC app a hint for that? Like the feature we have in Tweetbot: if the ambient is dark, the app automatically transitions to the dark mode;</li>\n  <li>Some way to customize UIAlertController’s appearance, like what happens in the <a href=\"http://cl.ly/2D1z2F2o1Q1n\">Apple</a> <a href=\"http://cl.ly/0f033L0a3E0b\">Music</a> app and similar to [Dropbox(http://cl.ly/1z2M3v1C2x0E). (As a side note, I remember that, in 2013, Apple announced that the first beta of iOS 7 would have some property that would allow adding custom views, like a image view, to UIAlertView. No one heard about it anymore in the other betas 🙊);</li>\n  <li>Customize the haptic feedback for notifications on the Watch. For example, only Messages, Calendar and Health notifications have that subtle tap in your wrist; what if we could identify which app wants our attention only by the pattern of the feedback? Besides that, having the default “vibration” is too obnoxious when happens frequently in other messaging apps;</li>\n  <li>What everybody is talking about: Siri on OS X and some sort of Siri API for 3rd party apps;</li>\n  <li>Better implementations and discoverability of 3D Touch. I believe that the low usage (both by users and developers) of the 3D Touch APIs are related to Apple not using it enough in their own apps, and for not marketing/making it visible enough;</li>\n  <li>More system apps implementing multitasking on the iPad. Again, how Apple wants us to make apps using some technologies, when they don’t adopt it completely?</li>\n  <li>Handoff on Apple Music? (Again, I’m looking at you, Apple!)</li>\n</ul>\n\n<p>Of course, the Keynote and the State of the Union presentations will come and (I hope) surprise everyone. This is part of the magic. In the last days I’ve been literally dreaming about this magic.</p>\n\n<p>I can’t wait to meet personally the people who I only know from the internet; to see other friends who I’ve met before and I’m in touch with; and specially to meet new people. Thousands of different people, from different backgrounds and locations, with a shared passion.</p>\n\n<p>I can’t wait to hear in first hand what’s coming to iOS 10, OS X, watchOS,  tvOS, Xcode and Swift 3. I can’t wait to get emotional for making a dream come true, once again, after being present on a Keynote with more than 5 thousand people. <em>I can’t wait for WWDC to start!</em></p>\n\n<p>PS: If you want to start getting into the mood, I recommend <a href=\"https://itunes.apple.com/br/playlist/wwdc-waiting-list/idpl.6c523103c9944b358a5f40e65af038f9\">this playlist on Apple Music</a>!</p>",
            "summary": "I can’t believe it’s already been three years since I visited San Francisco for the first and only time. In the same way that the tickets that year were sold out in 70 seconds, that unforgettable week, where Apple announced iOS 7 and Mavericks, passed like lightning. It’s hard to to express how much I’m excited for the next week, both as a member of the iOS worldwide community and as a programmer. Yes, Dub Dub is already in the next week! In three years, generally speaking, a lot can happen in someone’s life. But in tech, things move faster, and in three years things change a LOT more. Just to understand to what degree iOS is maturing and the community is evolving together, I’ll list a few jaw dropping facts that were reality right before WWDC 13.",
            "date_published": "2016-06-05T12:35:38+00:00",
            "date_modified": "2016-06-05T12:35:38+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": []},{
            "id": "https://blog.natanrolnik.me/migrating-my-data-from-parse",
            "url": "https://blog.natanrolnik.me/migrating-my-parse-data",
            "title": "Migrating My Data From Parse",
            "content_html": "<p>As you probably already know, Parse announced it’s ending their hosting services on January 28, 2017. The migration plan was <a href=\"https://github.com/ParsePlatform/parse-server/wiki/Migrating-an-Existing-Parse-App\">divided in two steps</a>: first, we need to host the databases of our apps, and later on we should deploy our own, open source, Parse Server. During the first stage, the clients (iOS, Android, etc.) will keep hitting Parse’s servers, and they will access the newly migrated data; after the second stage is done and your server is up and running, the clients should be updated to point to the new server. The recommended schedule by the Parse team is to migrate the database by April 28, and finish setting up your self-hosted Parse Server by July 28. Yes, you read it right - if you haven’t migrated your database, <a href=\"https://github.com/ParsePlatform/parse-server/wiki/Migrating-an-Existing-Parse-App#what-happens-if-i-dont-migrate-my-data-by-april-28-2016\">you have less than a month to do so</a>.</p>\n\n<p>“<em>But where should I start from?</em>”. As any decision, the pros and cons must to be taken into account, also considering the different conditions: do you have only one or multiple apps on Parse? They store huge amounts of data, or not so much? Do you have experience managing databases, specially MongoDB? How sensitive is your data? What is your budget?</p>\n\n<p>As most of my apps have a small, niche audience, the amounts of data are really small. None of the databases is higher than 10 MB, even with a few thousand users, installation, and other objects. Also, most of them are free, with some humble contributions or donations occasionally. Therefore, I have a small budget to keep them functioning. As I have zero experience managing databases, I can’t build all the MongoDB server by myself (for example, I didn’t even know of some concepts like sharding, replica sets, and more). I started researching all the different options available in the market, to find what would fit my needs.</p>\n\n<h2 id=\"ok-so-what-are-my-options-now\">Ok, so what are my options now?</h2>\n\n<p>Suggested by the Parse Team, there are <a href=\"http://docs.mlab.com/migrating-from-parse/\">mLab</a> and <a href=\"https://objectrocket.com/parse\">ObjectRocket</a>, who provide - from what I’ve read - excellent DB-as-a-service. mLab would be a good fit for me, their prices start from U$15 per GB/database/month (the free tier is not intended for production usage). I have around 6 apps in production, and they require different databases, so the monthly cost would be almost U$100 per month, and we aren’t even talking about hosting the Parse Server yet. (Actually, if you are using only Parse Server, and not migrating from hosted Parse, you can use only one database for different apps, by defining a <a href=\"https://github.com/ParsePlatform/parse-server/blob/ef08dcf76cb91131ff63dfbdba67a65ccf75b557/src/ParseServer.js#L70\">collectionPrefix</a>).</p>\n\n<p>Unfortunately, the prices and sizes that ObjectRocket offer aren’t for indie/side projects, so I needed to cross them as well from my list, together with mLab and <a href=\"https://compose.io/\">Compose.io</a>. While reading the <a href=\"https://github.com/ParsePlatform/parse-server/wiki#community-links\">community links</a> and googling more, I’ve found <a href=\"https://www.clever-cloud.com/\">Clever Cloud</a>. I almost chose them to host my DBs: you can host as many mongo dbs you want, and it’s free up to 500 MB; but if you need more than that, it jumps from a free 500 MB, to a 75 €/month for 30 GB, and I needed something in the middle.</p>\n\n<p>Also, as an option for a replacement of all Parse services, there are also <a href=\"http://nodechef.com/parse-server\">NodeChef</a>, <a href=\"http://www.parseground.com/\">ParseGround</a>, <a href=\"https://www.backand.com/parse-alternative/\">Backand</a> and <a href=\"http://blog.back4app.com/2016/03/01/quick-wizard-migration/\">Back4app</a>. But as now I have the possibility to have control over the whole parse stack, I preferred not to depend too much again on another service. It’s a personal decision; check them out because they may be a good fit for you, if you don’t want to worry at all with the backend.</p>\n\n<p>After a few weeks, when I was about to give up, I found <a href=\"https://scalegrid.io\">Scalegrid.io</a>, that provided exactly what I needed: a place where I can create many Mongo DBs under the same infrastructure (a cluster). Someone to manage the hard part, but with the control that I want. Similarly, there is also <a href=\"https://www.mongodb.com/migrate-from-parse-to-mongodb-cloud-manager-and-aws\">MongoDB Cloud Manager</a>, which is an excellent product from MongoDB Inc. itself. I preferred to go with Scalegrid, but the process I describe in the next section is very similar for both solutions.</p>\n\n<h2 id=\"setting-up-my-first-mongodb-server\">Setting up my first MongoDB server</h2>\n\n<p>After signing up for a 30 day free trial, I checked which one of the services would fit me better: (1) hosting, where I provide my AWS keys or own hardware, and they manage it, or (2) management, where I don’t need to worry about the hardware that will host the dbs. In my case, I preferred to have control also over the underlying instances, so I chose the first option. Price-wise, they are very similar at the end of the day - in the first, you need to pay AWS and Scalegrid.io, while in the second you pay a little more but only for Scalegrid.io. According to my calculations, it would be something very close. So this is what I did, and what you should do to set it up:</p>\n\n<ol>\n  <li>Create a new user the AWS account and generate the keys (Acces Key Id and Secret Acces Key). Remember to save this keys, as you won’t get them again from AWS.</li>\n  <li>Created a new “Cloud Profile” in the Scalegrid console using the AWS keys.</li>\n  <li>Created a new cluster using this profile. It means that the AWS EC2 instances will be created, by Scalegrid, in your AWS account. Bear in mind that you will need to choose a few options:\n    <ol>\n      <li>Size (micro gives you 10GB of storage);</li>\n      <li>The version of Mongo (Parse only supports officially 2.6 and 3.0 for now);</li>\n      <li>To enable <a href=\"https://docs.mongodb.org/manual/core/replication-introduction/\">replica sets</a> and <a href=\"https://docs.mongodb.org/manual/core/sharding-introduction/\">sharding</a> - if you don’t have high traffic and don’t need redundancy, you probably don’t need;</li>\n      <li>To encrypt and compress the data - I suggest to set both to yes;</li>\n      <li>To enable SSL (more on the last paragraph) - it’s recommended, but not required.</li>\n    </ol>\n  </li>\n  <li>Wait for a few minutes (you can see the instance being created in the AWS console), and your cluster will be ready to go.</li>\n  <li>Now you should be able to get the connection string, needed for migrating your Parse apps, but we are almost done.</li>\n  <li>For each app, you will need a new database in your cluster. So for each app you have:\n    <ol>\n      <li>Create a new database</li>\n      <li>add a user (I called mine <em>parse-access</em>) and set a password</li>\n    </ol>\n  </li>\n  <li>Get the connection string, and append the database name at the end. For example, if the database name is SuperApp, your connection string should be: mongodb://user<strong>:</strong>password@hostaddress<strong>:</strong>port**/SuperApp. (the default port is 27017, and remember to append <em>?ssl=true</em> at the end).</li>\n</ol>\n\n<p>Finally, an important detail: as one of my apps stores medical data, I wanted SSL to be required. Scalegrid offers two options: <a href=\"https://scalegrid.io/blog/mongodb-ssl-with-self-signed-certificates-in-node-js/\">self-signed certificates</a>, or use your own, trusted certificates. If you are running only your own Parse Server, the self-signed certificate is enough; if you are migrating from Parse, you will need to get a certificate from a trusted Certificate Authority, or disable SSL at all in your mongo server. I chose the first option:</p>\n\n<ol>\n  <li>Purchase a certificate for a subdomain that you own:\n    <ol>\n      <li>You can get a wildcard certificate, for more than one subdomain, or get a certificate for a specific subdomain. (The latter is cheaper and may be enough, so that’s what I did: a $10 certificate via Namecheap/Comodo);</li>\n      <li>In order to create the certificate, you will need to create a .csr file. Use ssh to connect to the AWS instance and <a href=\"https://support.comodo.com/index.php?/Default/Knowledgebase/Article/View/1/19/csr-generation-using-openssl-apache-wmod_ssl-nginx-os-x\">create the .csr</a>;</li>\n      <li>Provide the .csr file to the Certificate Authority;</li>\n      <li>Prove that you own the domain (this can be done by e-mail @yourdomain, or using DNS records).</li>\n      <li>In a few minutes you should receive the certificate files.</li>\n    </ol>\n  </li>\n  <li>In your DNS records, make the certified subdomain point to the Scalegrid server</li>\n  <li>Finally, <a href=\"https://scalegrid.io/blog/bring-your-own-ssl-certificates/\">install the certificate</a> in the mongo server. (the great Scalegrid support team helped me doing so)</li>\n  <li>When I thought the SSL journey was over, the migration tool from Parse still wasn’t reaching the servers, showing “No reachable servers”, because the setup wasn’t complete. After researching for a few hours, I discovered that we forgot to add the <a href=\"https://uk.godaddy.com/help/what-is-an-intermediate-certificate-868\">intermediate certificate</a>.</li>\n</ol>\n\n<h3 style=\"text-align: center;\" id=\"im-very-happy-with-the-solution-ive-found-but-my-advice-to-you-is-study-the-available-options-define-your-priorities-and-budget-and-start-the-migration-process-once-you-chose-how-to-store-your-data-be-prepared-and-dont-leave-it-to-the-last-minute\">I’m very happy with the solution I’ve found, but my advice to you is: <strong>study</strong> the available options<strong>, define</strong> your priorities and budget, <strong>and start the migration process</strong> once you chose how to store your data. Be prepared and don’t leave it to the last minute!</h3>\n\n<div style=\"margin: 40px 0;\">\n  <a href=\"/assets/posts-images/parse-db-migrated.jpeg\">\n    <img style=\"margin: auto; display: block;\" src=\"/assets/posts-images/parse-db-migrated.jpeg\" />\n  </a>\n\n</div>\n\n<p style=\"text-align: center;\">If you have any troubles, you can ping me <a href=\"https://www.twitter.com/natanrolnik\">@natanrolnik</a>, or e-mail me at <a href=\"mailto:me+b@natanrolnik.me\">me+b@natanrolnik.me</a>.<br />\nThanks to <a href=\"https://www.twitter.com/newFosco\">@newFosco</a>, <a href=\"https://www.twitter.com/MarcioK\">@MarcioK</a> and <a href=\"https://www.twitter.com/ofermorag24\">@ofermorag24</a>  for reviewing this post</p>\n\n<h3 id=\"update-3-months-after-this-post-was-published-mongodb-itself-introduced-atlas-their-own-hosted-mongodb-as-a-service-with-an-excellent-pricing-and-reliability-i-really-recommend-you-checking-it-out\">UPDATE: 3 months after this post was published, MongoDB itself <a href=\"https://www.mongodb.com/blog/post/announcing-mongodb-atlas-database-as-a-service-for-mongodb\">introduced Atlas</a>, their own hosted <a href=\"https://http://mongodb.com/atlas\">MongoDB-as-a-service</a>, with an excellent <a href=\"https://www.mongodb.com/cloud/atlas/pricing\">pricing</a> and reliability. I really recommend you checking it out!</h3>",
            "summary": "As you probably already know, Parse announced it’s ending their hosting services on January 28, 2017. The migration plan was divided in two steps: first, we need to host the databases of our apps, and later on we should deploy our own, open source, Parse Server. During the first stage, the clients (iOS, Android, etc.) will keep hitting Parse’s servers, and they will access the newly migrated data; after the second stage is done and your server is up and running, the clients should be updated to point to the new server. The recommended schedule by the Parse team is to migrate the database by April 28, and finish setting up your self-hosted Parse Server by July 28. Yes, you read it right - if you haven’t migrated your database, you have less than a month to do so.",
            "date_published": "2016-03-31T06:34:25+00:00",
            "date_modified": "2016-03-31T06:34:25+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": []},{
            "id": "https://blog.natanrolnik.me/thoughts-on-the-parse-shutdown-how-the-terrible-news-became-the-best-thing-to-happen-to-my-app",
            "url": "https://blog.natanrolnik.me/parse-shutdown",
            "title": "Thoughts on the Parse shutdown - how the terrible news became the best thing to happen to my app (and my career)",
            "content_html": "<p>Friday morning, Israel time. After I wake up and look to my iPhone, I see 3 notifications from friends (fellow developers that know how much I love Parse), sending me the link to <a href=\"http://blog.parse.com/announcements/moving-on/\">Kevin Lacker’s post</a>. When I saw the title, “Moving On”, I froze. Only a few days after releasing <a href=\"http://www.DoctorBuddyApp.com\">my side project</a>, an app I’ve worked on for over than a year and a half, using Parse as backend, would I read the worst thing to happen to that and to a few other smaller projects?</p>\n\n<h3 id=\"why-i-loved-it-so-much\">Why I loved it so much?</h3>\n\n<p>In the last two years, I’ve been using it in almost every single project, in many different ways for each app:</p>\n\n<ul>\n  <li>as a complete backend for user management, data and file storage in the cloud, including Cloud Code functions and Background Jobs;</li>\n  <li>hosting in app purchases content;</li>\n  <li>as a simple and quick tool that gives powerful analytics;</li>\n  <li>to send Push notifications in a relatively very simple way;</li>\n  <li>and more using the other solutions and products they provide.</li>\n</ul>\n\n<p>For me, nothing describes Parse better than the following quote from <a href=\"https://www.youtube.com/watch?v=89xIe8FbR2g\">their last marketing video</a>, part of a complete and recent redesign and rebranding: <em>“You can definitely handle the frontend, but what about the backend? Configuring servers, managing databases, writing APIs, storing videos, authenticating users, building deployment processes, and so on, and so on. Sure, you can figure out how to do that stuff yourself, maybe hire someone to deal with it for you, but here is a better way: Parse”</em>. For sure, if I had all the time and resources in the world, of course I would like to take care of every single part of my app, doesn’t matter if it’s frontend or backend. <strong>I am, more than an iOS developer, a programmer.</strong> <strong>We deal with solving problems, no matter the language or the ecosystem.</strong> But our resources and time are limited.</p>\n\n<p>There are two main reasons developers liked it so much and got pissed off with the news. First, it allowed us to make more complex apps in a <strong>easy, fast, and reliable way</strong>, even without the need to master another programming language. Additionally, if you are working in a side project where you may even know how to build the server side - you may be constrained by time and need to get out with something faster, focusing on the app experience. We loved Parse because it made the heavy lifting. If my side project took an year and a half with client code only (and minimal Cloud Code), I don’t think I would have ever finished it if I needed to take care of writing the API, managing databases and deploy processes.</p>\n\n<p>In total, 6 friends have sent me the link to the shutdown post, and they all did it because I’m sure I’ve talked enough about it (recommending) and telling how much it helped me accomplishing this app. Even a few of my friends who don’t code know what is Parse.</p>\n\n<h3 id=\"what-now\">What now?</h3>\n\n<p>Of course, the first thing that popped in my mind as I read the shut down post was: <em>“Ok, what should I do now?!”</em>. I couldn’t believe what my eyes were reading. In the following hours, I got <strong>really sad</strong> (ask my wife!)<strong>,</strong> and felt as if I was loosing something cherished - after all, I’ve been a user for almost 3 years since I first heard about in the <a href=\"https://twitter.com/natanrolnik/status/693063083758088192\">WWDC 2013 party,</a> and after following how much it changed and improved since then.</p>\n\n<p>Finally, I reached the stage of acceptance and tried to follow the <a href=\"https://parse.com/docs/server/guide#overview\">excellent migration guide</a> they prepared. After around one hour, I had the development database migrated to mongolab, and after around another hour I had the Parse Server deployed in Heroku.</p>\n\n<h3 id=\"so-why-is-it-good-news\">So why is it good news?</h3>\n\n<p>Well, it’s definitely not yet there, and the server has still a <a href=\"https://parse.com/docs/server/guide#migrating\">few limitations</a> and <a href=\"https://github.com/parseplatform/parse-server\">issues</a>, but I started feeling that the “backup plan” may end up being a better solution in the end of the day (specially if you client app is mostly done):</p>\n\n<ul>\n  <li><strong>Parse Server is open source:</strong> now, every one of us can contribute to improve the server side (go and create your first PR!), and not only that - we can deploy the same Cloud Code app and logic to wherever we want: AWS, DigitalOcean, Heroku, and more;</li>\n  <li><strong>We own the stack:</strong> we can create our own deployment processes, connect them to the app source repo; not satisfied with the server? change it to some other place;</li>\n  <li><strong>We have greater control over the database:</strong> now, there is no one between you and the access to the database. With mongoldb, for example, there is an option to schedule recurring or one off backups;</li>\n  <li><strong>In case you need to scale, it will propably be much cheaper;</strong></li>\n  <li><strong>And finally, and most important, you don’t depend anymore on Facebook’s volatile strategic interests.</strong></li>\n</ul>\n\n<p>(This, considering you won’t do significant API changes and still want to use Parse’s SDK in the client code. If your client app’s architecture is not tied to _PFObject_s everywhere, even better.)</p>\n\n<p>It’s more work, for sure. Deploying, monitoring, scaling. But that’s an amazing opportunity to learn more stuff, and keep using the same client code (only changing the server URL).</p>\n\n<p>A <strong>huge thanks</strong> to everyone who was involved in creating the idea, implementing the initial products, and the ones who took it to another level. With the tool you created, I did apps that could do much more, and also I could focus and finish a big project I’ve been dreaming of for around 3 years. Another special thanks to the folks (Fosco Marotto <em>et al</em>) who are working around the clock to make Parse Server and the migration stable and reliable, and as smooth as possible for us!</p>\n\n<h3 id=\"hosted-parse-ill-miss-you-long-live-parse-server\"><strong><em>Hosted</em> Parse, I’ll miss you! Long live Parse-Server!</strong></h3>\n\n<h3 id=\"other-interesting-readslinks\">Other interesting reads/links:</h3>\n\n<ul>\n  <li><a href=\"http://venturebeat.com/2016/01/30/why-facebooks-parse-shutdown-is-good-news-for-all-of-us/?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+Venturebeat+(VentureBeat)\">Why Facebook’s Parse shutdown is good news for all of us?</a> by <a href=\"http://www.layer.com\">Layer</a> Co-Founder <a href=\"http://twitter.com/RonP\">Ron Palmeri</a></li>\n  <li><a href=\"https://medium.com/@ishabazz/i-thought-we-were-cool-facebook-i-thought-you-had-my-back-end-f68e2fa15867#.55e86ruvx\">I thought we were cool Facebook. I thought you had my back(end)</a> by <a href=\"http://twitter.com/ishabazz\">@ishabazz</a></li>\n  <li><a href=\"http://mjtsai.com/blog/2016/01/30/sunsetting-parse/\">Michael Tsai’s roundup</a></li>\n  <li><strong><a href=\"https://github.com/relatedcode/ParseAlternatives\">Parse Alternatives GitHub repo</a></strong></li>\n</ul>",
            "summary": "Friday morning, Israel time. After I wake up and look to my iPhone, I see 3 notifications from friends (fellow developers that know how much I love Parse), sending me the link to Kevin Lacker’s post. When I saw the title, “Moving On”, I froze. Only a few days after releasing my side project, an app I’ve worked on for over than a year and a half, using Parse as backend, would I read the worst thing to happen to that and to a few other smaller projects?",
            "date_published": "2016-01-31T19:51:21+00:00",
            "date_modified": "2016-01-31T19:51:21+00:00",
            "author": {
              "name": "Natan Rolnik", "url": "https://natanrolnik.me"},
            "tags": []}]
}