<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Simon Rice</title>
    <description>The latest articles on Forem by Simon Rice (@simonrice).</description>
    <link>https://forem.com/simonrice</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F10425%2F9e92d30a-0455-4969-b3c2-b139eb635a3c.png</url>
      <title>Forem: Simon Rice</title>
      <link>https://forem.com/simonrice</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/simonrice"/>
    <language>en</language>
    <item>
      <title>CarPlay: Linking to the Maps App</title>
      <dc:creator>Simon Rice</dc:creator>
      <pubDate>Sun, 18 Oct 2020 14:28:52 +0000</pubDate>
      <link>https://forem.com/simonrice/carplay-linking-to-maps-app-1i6n</link>
      <guid>https://forem.com/simonrice/carplay-linking-to-maps-app-1i6n</guid>
      <description>&lt;p&gt;I've recently been granted a CarPlay developer entitlement from Apple 🎉 and as a result been working on a little app for this platform.  On first impression, its development platform has shades of legacy WatchKit development due to the heavy reliance of adding views (or, in this instance, populated templates) to an "interface controller", except without any use of Interface Builder, and definitely no form of SwiftUI at the time of writing!  Indeed the best way of seeing CarPlay is like a second display for your app the provides a &lt;strong&gt;very specific&lt;/strong&gt; set of functionality - that in itself sounds a lot like the early days of Apple Watch!&lt;/p&gt;

&lt;p&gt;When being granted your CarPlay entitlement, you get pointed to two resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://developer.apple.com/carplay/documentation/CarPlay-App-Programming-Guide.pdf" rel="noopener noreferrer"&gt;Apple's CarPlay Programming Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://developer.apple.com/videos/play/wwdc2020/10635/" rel="noopener noreferrer"&gt;WWDC 2020: Accelerate Your App with CarPlay&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From my experience, combined together these give an extensive guide to developing on CarPlay.  However, I've noticed a small omission that I'd like to write about.&lt;/p&gt;

&lt;p&gt;One template for CarPlay I've been using is the Point of Interest template (&lt;code&gt;CPPointOfInterestTemplate&lt;/code&gt;), for which there literally is a point of interest about this template in the WWDC video:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a location is selected from a list, you may choose to show a secondary card for that point, revealing additional information and up to two buttons.&lt;/p&gt;

&lt;p&gt;These buttons could be used for a variety of tasks. For instance, they &lt;em&gt;may signal you to switch to a navigation app for driving directions&lt;/em&gt; or push to another template to display additional information for that location.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now interestingly neither the video nor the programming guide state &lt;em&gt;how&lt;/em&gt; to switch to a navigation app!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CPPointOfInterest&lt;/code&gt; has 2x optional properties relating to buttons that show up when you have a secondary card displayed - &lt;code&gt;primaryButton&lt;/code&gt; and &lt;code&gt;secondaryButton&lt;/code&gt;.  These are both of type &lt;code&gt;CPTextButton&lt;/code&gt;.  In &lt;code&gt;CPTextButton&lt;/code&gt;'s initialiser, there's a &lt;code&gt;handler&lt;/code&gt; parameter that takes a closure.  But what should go there if you want to open the point up on your maps app so you can route to that location?&lt;/p&gt;

&lt;p&gt;Now chances are you already have an &lt;code&gt;MKMapItem&lt;/code&gt; since &lt;code&gt;CPPointOfInterest&lt;/code&gt; requires one in its initialiser.  This class has a method of interest, specifically &lt;code&gt;openInMaps&lt;/code&gt; - this sounds very promising.&lt;/p&gt;

&lt;p&gt;So let's try it out:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

let mapItem = MKMapItem(placemark: ...)
let poi = CPPointOfInterest(
    location: mapItem,
    title: "Sample Location",
    subtitle: "Subtitle",
    summary: "Summary",
    detailTitle: "Detail Title",
    detailSubtitle: "Detail subtitle",
    detailSummary: "Detail Summary",
    pinImage: UIImage()
)

poi.primaryButton = CPTextButton(
    title: "GO",
    textStyle: .normal,
    handler: { _ in item.openInMaps() }
)

let mapTemplate = CPPointOfInterestTemplate(
    title: "Locations", 
    pointsOfInterest: [poi], 
    selectedIndex: NSNotFound
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The template will now show one location...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhcd3fy65ukhpw08wh3nn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhcd3fy65ukhpw08wh3nn.png" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2020-10-18 at 15.06.16"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...and you can drill down to the location in question...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4m8icgke0btzpb0awag1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4m8icgke0btzpb0awag1.png" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2020-10-18 at 15.06.19"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...tapping "GO" will open up the maps app - unfortunately this happens on your phone - and crucially Apple will reject your app because Apple rightly states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All CarPlay user flows must be possible without interacting with iPhone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thankfully this can be fixed - &lt;code&gt;MKMapItem.openInMaps(...)&lt;/code&gt; can optionally take a few parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;launchOptions&lt;/code&gt; - there are a few optional launch parameters you can pass to the maps app to help with directions.   More on this a bit later.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scene&lt;/code&gt; - the scene that you're launching the maps app from.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;completion&lt;/code&gt; - an optional completion handler that is called upon the maps app being loaded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the &lt;code&gt;scene&lt;/code&gt; parameter looks promising.  Chances are you'll be calling all of this from &lt;code&gt;CPTemplateApplicationSceneDelegate.templateApplicationScene(:didConnect:)&lt;/code&gt;, which has a &lt;code&gt;CPTemplateApplicationScene&lt;/code&gt; parameter.  Conveniently this is a &lt;code&gt;UIScene&lt;/code&gt; subclass, so you  can either pass this directly in or retain it from your &lt;code&gt;didConnect&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So let's now populate that &lt;code&gt;scene&lt;/code&gt; parameter - again assuming this is called from &lt;code&gt;didConnect&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

poi.primaryButton = CPTextButton(
    title: "GO",
    textStyle: .normal,
    handler: { _ in 
        item.openInMaps(
            from: templateApplicationScene
        ) 
    }
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This indeed opens up the maps app with the suggested location prepopulated.  However, as of iOS 14.0.1, your own app will almost certainly crash shortly afterwards with a system stack trace that looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6069qcty7k0n5u13fnt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6069qcty7k0n5u13fnt1.png" alt="Screenshot 2020-10-18 at 2.59.53 pm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The best way to stop this happening is to provide an empty &lt;code&gt;completionHandler&lt;/code&gt; parameter:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

poi.primaryButton = CPTextButton(
    title: "GO",
    textStyle: .normal,
    handler: { _ in 
        item.openInMaps(
            from: templateApplicationScene,
            completionHandler: { _ in return }
        ) 
    }
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And now the external maps app opens on your CarPlay display with your location prepopulated, but this time without any crashes on your app.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note about the CarPlay external display on the iOS simulator:&lt;/strong&gt; annoyingly there is no maps app on the CarPlay display on the simulator.  Opening the link opens a "Now Playing" display, as shown below.  This in turn explains why I have no further screenshots of the maps app experience from here.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxex4occ3zq5ngvjporle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxex4occ3zq5ngvjporle.png" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2020-10-18 at 15.04.28"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Now I did mention &lt;code&gt;MKMapItem.openInMaps(...)&lt;/code&gt; had a &lt;code&gt;launchOptions&lt;/code&gt; parameter.  Given that you already have a destination prepopulated and it's also a car routing, no parameters need passing here - therefore &lt;code&gt;launchOptions&lt;/code&gt; can be left out.&lt;/p&gt;

&lt;p&gt;I would however suggest populating 2x additional properties of your &lt;code&gt;MKMapItem&lt;/code&gt; instance to give the maps app some extra information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; - this shows up as the name of the location.  Chances are you'll know this in some way.  If you leave this out, the maps app will name the location "Unknown Location", which isn't desirable.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pointOfInterestCategory&lt;/code&gt; - this is more for future-proofing than a necessity if you have this information at hand - it might help the maps app hook into any additional functionality for this specific location.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, you may be applying a button like this from a different kind of template, such as &lt;code&gt;CPInformationTemplate&lt;/code&gt; - again, as long as you have the location that you wish to navigate to, creating a map item only requires an &lt;code&gt;MKPlacemark&lt;/code&gt; instance, which only requires the location in question to initialise.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>ios</category>
    </item>
    <item>
      <title>Swift on Netlify</title>
      <dc:creator>Simon Rice</dc:creator>
      <pubDate>Fri, 15 May 2020 20:10:47 +0000</pubDate>
      <link>https://forem.com/simonrice/swift-on-netlify-3440</link>
      <guid>https://forem.com/simonrice/swift-on-netlify-3440</guid>
      <description>&lt;p&gt;Since it was open sourced in December 2015, there have been a number of efforts in bringing Apple's Swift Programming Language to run on a variety of operating systems, servers and even embedded systems.&lt;/p&gt;

&lt;p&gt;In December 2019, prominent Swift &amp;amp; iOS developer John Sundell open sourced &lt;a href="https://github.com/johnsundell/publish"&gt;Publish&lt;/a&gt;, a production-ready static site generator package written in Swift.  Its purpose is given a set of markdown and Swift files, you can generate your HTML and other assets by running &lt;code&gt;swift run&lt;/code&gt; - this will fetch your Swift Package Manager (or SPM) dependencies, build a command line app and run it, putting your generated website in a directory (which, by default, is &lt;code&gt;Output&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Since I’m primarily an iOS developer by trade who previously tended to opt for Ruby / Middleman to publish content on the web, and given I’ve used &lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt; for hosting said websites, I had a lightbulb moment 💡 What if I could get Swift working with full SPM caching on Netlify, and so allow a seamless build pipeline for Publish?  After all, &lt;a href="https://github.com/netlify/build-image"&gt;Netlify’s build image is open source &amp;amp; is welcoming contributions.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, I'm happy to say not only is it possible, but as of build image v3.3.8, Swift is now supported on Netlify as a first party language.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to create a static website written in Swift that’s hosted on Netlify
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt; Build your website using Publish locally, and ensure you’ve checked in your &lt;code&gt;Package.swift&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt; After pushing your website to a remote repository, set it up on Netlify.&lt;/li&gt;
&lt;li&gt; When prompted on Netlify for your Basic Build Settings (or in Your Site’s Settings -&amp;gt; Build &amp;amp; Deploy -&amp;gt; Continuous Deployment -&amp;gt; Build Settings if you're migrating an existing website), use these settings to deploy your website:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build Command: swift run
Publish Directory: Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...and then deploy 🚀 that’s all there is to it 🎉&lt;/p&gt;

&lt;p&gt;Note that your first deploy will be a bit slower as there’s no SPM cache to start off with, but this will be used for subsequent builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional, but recommended&lt;/strong&gt;: Include a &lt;code&gt;.swift-version&lt;/code&gt; file in the root of your repository stating which version of Swift you’re targeting.  By default, Netlify runs on Swift 5.2, which at the time of writing is the current, readily-available stable version - even if you are using Swift 5.2 yourself, including this file is a good habit.  However, Netlify supports any version of Swift from 5.0 and above that &lt;a href="https://github.com/kylef/swiftenv"&gt;swiftenv&lt;/a&gt; supports.  If you’re not using Netlify’s default version of Swift then, in addition to your SPM dependencies, your Swift version will also be cached at the end of your first build, so your build time isn’t sucked up downloading your selected version of Swift.  You can equally configure a &lt;code&gt;SWIFT_VERSION&lt;/code&gt; environment variable on Netlify, but if you have swiftenv installed locally then a &lt;code&gt;.swift-version&lt;/code&gt; file will work for you locally too.&lt;/p&gt;




&lt;p&gt;While Publish is currently the most popular static site generator that’s written in Swift, in practice Netlify can run &lt;em&gt;&lt;strong&gt;any&lt;/strong&gt;&lt;/em&gt; SPM-based Swift command line app that generates content of some form, so long as it’s not dependant on any proprietary framework from Apple (such as UIKit or AppKit).  You just need to ensure your publish directory is pointing to the right place.&lt;/p&gt;

&lt;p&gt;I’ve enjoyed playing a small role in bringing the Swift Programming Language to another new environment, via a small bit of Docker &amp;amp; shell scripting that I might document on here if anyone’s interested.  And if Swift is your thing, I hope you find this little guide useful.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>html</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
