<?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>DEV Community: Artem Novichkov</title>
    <description>The latest articles on DEV Community by Artem Novichkov (@artemnovichkov).</description>
    <link>https://dev.to/artemnovichkov</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%2F26737%2Ff6acbd47-946e-4249-81a1-235d05e0ded4.PNG</url>
      <title>DEV Community: Artem Novichkov</title>
      <link>https://dev.to/artemnovichkov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/artemnovichkov"/>
    <language>en</language>
    <item>
      <title>Custom @Environment value for share actions</title>
      <dc:creator>Artem Novichkov</dc:creator>
      <pubDate>Mon, 15 Feb 2021 18:24:10 +0000</pubDate>
      <link>https://dev.to/artemnovichkov/custom-environment-value-for-share-actions-4g8</link>
      <guid>https://dev.to/artemnovichkov/custom-environment-value-for-share-actions-4g8</guid>
      <description>&lt;p&gt;SwiftUI has a lot of modern and useful features. One of my favourite is @Environment property wrapper. It allows you to get system-wide settings, for instance, current locale or color scheme. Since iOS 14.0 you can use &lt;code&gt;openURL&lt;/code&gt; value to open URLs from apps easily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;@available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mf"&gt;14.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macOS&lt;/span&gt; &lt;span class="mf"&gt;11.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tvOS&lt;/span&gt; &lt;span class="mf"&gt;14.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;watchOS&lt;/span&gt; &lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;EnvironmentValues&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;/// Opens a URL using the appropriate system service.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;openURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;OpenURLAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With just a one line of code you can extend behaviour of you views:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ContentView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Share"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;openURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://blog.artemnovichkov.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was wondering how it works under the hood and tried to implement the same trick for sharing activity items with &lt;code&gt;UIActivityViewController&lt;/code&gt;. Let's check the result!&lt;/p&gt;

&lt;h2&gt;
  
  
  Keys and values
&lt;/h2&gt;

&lt;p&gt;At first we should create a custom key, conform to &lt;code&gt;EnvironmentKey&lt;/code&gt; protocol and set a default value. It will be an empty struct for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ShareAction&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ShareActionEnvironmentKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EnvironmentKey&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ShareAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we should extend &lt;code&gt;EnvironmentValues&lt;/code&gt; to make our &lt;code&gt;ShareAction&lt;/code&gt; be available from the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;EnvironmentValues&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;share&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ShareAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;ShareActionEnvironmentKey&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing is adding &lt;code&gt;callAsFunction&lt;/code&gt; in &lt;code&gt;ShareAction&lt;/code&gt; struct to use the same syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ShareAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;callAsFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;activityItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;vc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIActivityViewController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;activityItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;activityItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;applicationActivities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;UIApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;windows&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rootViewController&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Unfortunately, there is no SwiftUI-way to open this controller. If you use a better way, let me know!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To read more about callable values of user-defined nominal types, check &lt;a href="https://github.com/apple/swift-evolution/blob/master/proposals/0253-callable.md" rel="noopener noreferrer"&gt;SE-0253&lt;/a&gt; proposal on Github.&lt;/p&gt;

&lt;p&gt;That's it, now we can use &lt;code&gt;.share&lt;/code&gt; value and share activities from any view:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ContentView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Share"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;share&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kt"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://blog.artemnovichkov.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Related Resources
&lt;/h2&gt;

&lt;p&gt;The final code is available &lt;a href="https://github.com/artemnovichkov/ShareEnvironmentExample" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and there is a list of related articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/swiftui/environment" rel="noopener noreferrer"&gt;Environment Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sarunw.com/posts/what-is-environment-in-swiftui/" rel="noopener noreferrer"&gt;What is @Environment in SwiftUI&lt;/a&gt; by &lt;a href="https://twitter.com/sarunw" rel="noopener noreferrer"&gt;Sarun W.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://swiftwithmajid.com/2019/08/21/the-power-of-environment-in-swiftui/" rel="noopener noreferrer"&gt;The power of Environment in SwiftUI&lt;/a&gt; by &lt;a href="https://twitter.com/mecid" rel="noopener noreferrer"&gt;Majid Jabrayilov&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views" rel="noopener noreferrer"&gt;How to use @EnvironmentObject to share data between views&lt;/a&gt; by &lt;a href="https://twitter.com/twostraws" rel="noopener noreferrer"&gt;Paul Hudson&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swiftui</category>
      <category>ios</category>
      <category>swift</category>
    </item>
    <item>
      <title>iOS 13 Dark Mode</title>
      <dc:creator>Artem Novichkov</dc:creator>
      <pubDate>Sat, 11 Jan 2020 09:41:17 +0000</pubDate>
      <link>https://dev.to/artemnovichkov/ios-13-dark-mode-1o6j</link>
      <guid>https://dev.to/artemnovichkov/ios-13-dark-mode-1o6j</guid>
      <description>&lt;p&gt;In iOS 13.0 and later, users can choose to adopt a dark appearance called Dark Mode. In Dark Mode, apps and system use a darker colors for all screens, controls and views. Users can select Dark Mode as their default interface style, and can use Settings to make their devices automatically switch to Dark Mode when ambient light is low.&lt;/p&gt;

&lt;p&gt;In this article I'll describe Dark Mode support in third-party apps with(out) storyboards, highlight handy debugging tools and try to implement Dark Mode updating inside the app without overhead.&lt;/p&gt;

&lt;p&gt;All my examples from this article are available in &lt;a href="https://github.com/rosberry/DarkMode" rel="noopener noreferrer"&gt;DarkMode&lt;/a&gt; project. This small framework is a result of my research and a place for experiments with Dark Mode. Please feel free to open it and play with examples.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: in this article I'll tell about UIKit, not SwiftUI. The main goals of my research were practical use and backward compatibility.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Dark mode appearance is based on trait collections. When the user changes the system appearance, the system automatically asks all windows and views to redraw its content. UIKit controls support it out of the box without additional logic. Let's start with colors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Color appearance
&lt;/h3&gt;

&lt;p&gt;To configure app colors with different appearances, you can use Asset Catalogs. Just create a New Color Set and add required colors. If you want to improve app accessibility, you can add high contrast color variant for every color:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fac8nod66tkngpxfed4iz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fac8nod66tkngpxfed4iz.jpeg" alt="Alt Text" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In storyboards these colors are available in Named Colors section during color selection. To use it in code, just initialize it with the given name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backdroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;named&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Color"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: I recommend that we use code generation tools for it to prevent silly crashes after renaming or refactoring.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you don't want to use Asset Catalog for some reason, you can configure colors directly via &lt;code&gt;UIColor.init(dynamicProvider:)&lt;/code&gt; initializer. It returns different colors based on trait collection properties. I've added an extension to reduce SDK version checks:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;UIColor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;/// Creates a color object that generates its color data dynamically using the specified colors. For early SDKs creates light color.&lt;/span&gt;
    &lt;span class="c1"&gt;/// - Parameters:&lt;/span&gt;
    &lt;span class="c1"&gt;///   - light: The color for light mode.&lt;/span&gt;
    &lt;span class="c1"&gt;///   - dark: The color for dark mode.&lt;/span&gt;
    &lt;span class="kd"&gt;convenience&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;#available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tvOS&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;traitCollection&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;traitCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;userInterfaceStyle&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dark&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cgColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cgColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, iOS has some default colors that automatically adapt to the current trait environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backdroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;systemRed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Image appearance
&lt;/h3&gt;

&lt;p&gt;The same logic in Asset Catalog works for images as well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzdwtv6n49che7240ejl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzdwtv6n49che7240ejl.png" alt="Alt Text" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use it as usual in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;imageView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIImageView&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;imageView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;named&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Image"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to create images at runtime, for example, load from file system or from server, you must use image assets. Also I've added an extension to initialize assets with two images for different appearances:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;UIImageAsset&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;/// Creates an image asset with registration of tht eimages with the light and dark trait collections.&lt;/span&gt;
    &lt;span class="c1"&gt;/// - Parameters:&lt;/span&gt;
    &lt;span class="c1"&gt;///   - lightModeImage: The image you want to register with the image asset with light user interface style.&lt;/span&gt;
    &lt;span class="c1"&gt;///   - darkModeImage: The image you want to register with the image asset with dark user interface style.&lt;/span&gt;
    &lt;span class="kd"&gt;convenience&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lightModeImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt; &lt;span class="nv"&gt;darkModeImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lightModeImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lightModeImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;darkModeImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;darkModeImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;/// Register an images with the light and dark trait collections respectively.&lt;/span&gt;
    &lt;span class="c1"&gt;/// - Parameters:&lt;/span&gt;
    &lt;span class="c1"&gt;///   - lightModeImage: The image you want to register with the image asset with light user interface style.&lt;/span&gt;
    &lt;span class="c1"&gt;///   - darkModeImage: The image you want to register with the image asset with dark user interface style.&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lightModeImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt; &lt;span class="nv"&gt;darkModeImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lightModeImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;darkModeImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;/// Register an image with the specified trait collection.&lt;/span&gt;
    &lt;span class="c1"&gt;/// - Parameters:&lt;/span&gt;
    &lt;span class="c1"&gt;///   - image: The image you want to register with the image asset.&lt;/span&gt;
    &lt;span class="c1"&gt;///   - traitCollection: The traits to associate with image.&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;traitCollection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITraitCollection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;traitCollection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;/// Returns the variant of the image that best matches the current trait collection. For early SDKs returns the image for light user interface style.&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;#available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tvOS&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layers
&lt;/h3&gt;

&lt;p&gt;Previous examples work for views perfectly. The colors are updated automatically without additional logic. But what about layers?&lt;br&gt;
To update colors in CALayers, you should implement &lt;code&gt;traitCollectionDidChange(_:)&lt;/code&gt; method in UIView or UIViewController and configure layer's colors manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;traitCollectionDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;previousTraitCollection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITraitCollection&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;traitCollectionDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previousTraitCollection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;traitCollection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasDifferentColorAppearance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;comparedTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;traitCollection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIColor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cgColor&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to line #3. Trait collection may be changed for many reasons, for instance, when an iPhone is rotated from portrait to landscape orientation. This function indicates whether changing between the specified and current trait collections would affect color values. It saves you from extra drawing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;There are many ways to test Dark Mode appearance in your apps. Let's start with storyboards. If you use storyboards for layout, you can update interface style in the bottom next to device configuration pane.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxvc67tczko4671unops.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxvc67tczko4671unops.png" alt="Alt Text" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the useful features of Xcode 11 is Xcode Preview. It's possible to use it for UIKit-based projects with additional configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#if canImport(SwiftUI) &amp;amp;&amp;amp; DEBUG&lt;/span&gt;

&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;SwiftUI&lt;/span&gt;

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ViewControllerRepresentable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIViewRepresentable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;makeUIView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UIView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;storyboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UIStoryboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Main"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;viewController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storyboard&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiateViewController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;withIdentifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ViewController"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;viewController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;updateUIView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;@available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ViewController_Preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PreviewProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;previews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Group&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;ViewControllerRepresentable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previewDisplayName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Light Mode"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kt"&gt;ViewControllerRepresentable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previewDisplayName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dark Mode"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;colorScheme(_:)&lt;/code&gt; you can preview screens with both schemes simultaneously:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwk6bwll9xc348tzacbyl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwk6bwll9xc348tzacbyl.png" alt="Alt Text" width="762" height="927"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are debugging one of the color schemes, it's handy to fix dark appearance in the Simulator in &lt;code&gt;Preferences &amp;gt; Developer &amp;gt; Dark Appearance&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffui9paep0lanx3pbmski.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffui9paep0lanx3pbmski.png" alt="Alt Text" width="472" height="975"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If it's not enough for your case, you can override interface style during app sessions via Environment Overrides:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3ywmvqjvwxd08usha10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3ywmvqjvwxd08usha10.png" alt="Alt Text" width="355" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I told earlier, trait collections may be changed a lot of times during app sessions. You can enable debug logging to easily see when traitCollectionDidChange(_:) is called in your own classes. Turn on the logging by using the following launch argument: &lt;code&gt;-UITraitCollectionChangeLoggingEnabled YES&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sne9fe2ezmyswm1tks6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sne9fe2ezmyswm1tks6.png" alt="Alt Text" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When Dark Mode setting is updated, you'll see a message in the Console like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2019-12-16 09:12:44.819195+0600 DarkModeExample[22611:3698294] [TraitCollectionChange] Sending -traitCollectionDidChange: to &amp;lt;DarkModeExample.ViewController: 0x7fdb81d0b7a0&amp;gt;
► trait changes: { UserInterfaceStyle: Light → Dark }
► previous: &amp;lt;UITraitCollection: 0x600002f98900; UserInterfaceIdiom = Phone, DisplayScale = 3, DisplayGamut = P3, HorizontalSizeClass = Compact, VerticalSizeClass = Regular, UserInterfaceStyle = Light, UserInterfaceLayoutDirection = LTR, ForceTouchCapability = Available, PreferredContentSizeCategory = L, AccessibilityContrast = Normal, UserInterfaceLevel = Base&amp;gt;
► current: &amp;lt;UITraitCollection: 0x600002f98840; UserInterfaceIdiom = Phone, DisplayScale = 3, DisplayGamut = P3, HorizontalSizeClass = Compact, VerticalSizeClass = Regular, UserInterfaceStyle = Dark, UserInterfaceLayoutDirection = LTR, ForceTouchCapability = Available, PreferredContentSizeCategory = L, AccessibilityContrast = Normal, UserInterfaceLevel = Base&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update Dark Mode dynamically
&lt;/h2&gt;

&lt;p&gt;Unfortunately, iOS doesn't support updating color schemes dynamically for a single app. A simple way to implement it is saving selected &lt;code&gt;UIUserInterafaceStyle&lt;/code&gt; and using it in next app sessions. A good option for this is UserDefaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;UserDefaults&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;overridedUserInterfaceStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIUserInterfaceStyle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;UIUserInterfaceStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;forKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;#function&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unspecified&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;forKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;#function&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To apply the style saved we should override it for all app windows. They're available via &lt;code&gt;UIApplication.shared.windows&lt;/code&gt;. Pay attention that since iOS 13 iPad apps may support multiple windows&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;UIApplication&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

     &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;userInterfaceStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIUserInterfaceStyle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;supportsMultipleScenes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;connectedScene&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;connectedScenes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connectedScene&lt;/span&gt; &lt;span class="k"&gt;as?&lt;/span&gt; &lt;span class="kt"&gt;UIWindowScene&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;windows&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                          &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;overrideUserInterfaceStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userInterfaceStyle&lt;/span&gt;
                     &lt;span class="p"&gt;}&lt;/span&gt;
                 &lt;span class="p"&gt;}&lt;/span&gt;
             &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;windows&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                 &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;overrideUserInterfaceStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userInterfaceStyle&lt;/span&gt;
             &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to override the style for windows created afterwards. After overriding it standard views and controls automatically update their appearance to match the current interface style.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You may think about method swizzling to reduce configurations. I tried to avoid it in my example. Method swizzling is risky and may lead to unexpected behaviour. In my opinion for this case it's a good decision.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What do you think? How did you implement this feature in your apps? And should apps have this option or should we rely on the system?&lt;/p&gt;

&lt;h2&gt;
  
  
  Backward compatibility
&lt;/h2&gt;

&lt;p&gt;At Rosberry we usually support two latest major iOS versions. At the time of writing this article it's iOS 12 and 13. The simplest way is to use only a light color scheme for iOS 12 devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I've shared my experience as to the Dark Mode support. I hope this article will help you to update existing apps and to inspire you to develop new ones. I want to believe that in future Dark Mode will be default app feature without the need for additional adjustments for design and code.&lt;/p&gt;

&lt;p&gt;At the end I want to mention useful materials from around the web that helped me writing this article. And don't forget to check &lt;a href="https://github.com/rosberry/DarkMode" rel="noopener noreferrer"&gt;DarkMode&lt;/a&gt; project to see how Dark Mode works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apple
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/videos/play/wwdc2019/214/" rel="noopener noreferrer"&gt;WWDC 2019 - Implementing Dark Mode on iOS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/dark-mode/" rel="noopener noreferrer"&gt;Human Interface Guidelines - Dark Mode&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/#system-colors" rel="noopener noreferrer"&gt;Human Interface Guidelines - System Colors&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.apple.com/documentation/xcode/supporting_dark_mode_in_your_interface" rel="noopener noreferrer"&gt;Supporting Dark Mode in Your Interface&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Articles
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.avanderlee.com/swift/dark-mode-support-ios/" rel="noopener noreferrer"&gt;Dark Mode: Adding support to your app in Swift - SwiftLee&lt;/a&gt;&lt;br&gt;
&lt;a href="https://nshipster.com.ru/dark-mode/" rel="noopener noreferrer"&gt;Dark Mode on iOS 13 - NSHipster&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pspdfkit.com/blog/2019/adopting-dark-mode-on-ios/" rel="noopener noreferrer"&gt;Adopting Dark Mode on iOS and Ensuring Backward Compatibility - Inside PSPDFKit&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Github
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/aaronbrethorst/SemanticUI" rel="noopener noreferrer"&gt;aaronbrethorst/SemanticUI&lt;/a&gt;: iOS 13 Semantic UI: Dark Mode, Dynamic Type, and SF Symbols&lt;br&gt;
&lt;a href="https://github.com/noahsark769/ColorCompatibility" rel="noopener noreferrer"&gt;noahsark769/ColorCompatibility&lt;/a&gt;: Use iOS 13+ system colors while defaulting to light colors on iOS &amp;lt;=12&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.producthunt.com/posts/color-system-plugin-for-sketch" rel="noopener noreferrer"&gt;Color System Plugin for Sketch - Product Hunt&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.figma.com/c/plugin/780821534053786200/Lights---Light-and-Dark-Mode" rel="noopener noreferrer"&gt;Lights - Light and Dark Mode - Figma&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>xcode</category>
      <category>ui</category>
    </item>
    <item>
      <title>Github Actions CI for Swift Projects</title>
      <dc:creator>Artem Novichkov</dc:creator>
      <pubDate>Thu, 29 Aug 2019 09:38:12 +0000</pubDate>
      <link>https://dev.to/artemnovichkov/github-actions-ci-for-swift-projects-36kp</link>
      <guid>https://dev.to/artemnovichkov/github-actions-ci-for-swift-projects-36kp</guid>
      <description>&lt;p&gt;Github &lt;a href="https://github.blog/2019-08-08-github-actions-now-supports-ci-cd" rel="noopener noreferrer"&gt;introduced&lt;/a&gt; CI and CD based on actions. It allows you to automate how you analyse, build, test and deploy your projects on any platform, including Linux, macOS and Windows.&lt;/p&gt;

&lt;p&gt;I was excited over this news and can't wait to try it out. My idea was to automate building and unit testing of Swift projects.&lt;br&gt;
There are two types of actions and we should know the difference before starting.&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker container vs JS
&lt;/h2&gt;

&lt;p&gt;Originally all actions were based on Docker and used HCL syntax for workflows. Actions based on Docker run only in Linux virtual environment. With CI/CD announcement Github released JavaScript based actions and new YAML syntax for workflows.&lt;/p&gt;

&lt;p&gt;For iOS projects you can use only JS actions because they should be run on macOS. Moreover using a JavaScript action simplifies the action code and executes faster than a Docker container action.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lights! Camera! Github Action!
&lt;/h2&gt;

&lt;p&gt;As an example I will use &lt;a href="https://github.com/rosberry/texstyle" rel="noopener noreferrer"&gt;Texstyle&lt;/a&gt;. It's a framework for formatting attributed strings. Let's start with a complete configuration and inspect it step by step:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;At first you should select an event to trigger the workflow. My workflow is triggered on any pull request in the repository. Optionally you can label the workflow with &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Workflows must contain at least one job. My workflow contains only one job for testing. It is possible to run up to 20 jobs concurrently per repository across all workflows.&lt;/p&gt;

&lt;p&gt;Jobs run on virtual host machines that are specified with &lt;code&gt;runs-on&lt;/code&gt;. In my case it's &lt;code&gt;macOS-latest&lt;/code&gt;, because I want to use xcodebuild. It's a standard Apple developer tool and works on macOS only.&lt;/p&gt;

&lt;p&gt;Texstyle supports both iOS and tvOS, so I want to run xcodebuild with two destinations. To specify different variations, I used &lt;code&gt;strategy.matrix&lt;/code&gt;. I added two simulators with actual OS versions.&lt;/p&gt;

&lt;p&gt;And the last step is to adding steps 🙃. I used &lt;code&gt;checkout&lt;/code&gt; action to access the contents of the repository. You can specify the version of actions after @ sign with a release version, branch or specific commit.&lt;br&gt;
Everything is ready for testing. I added &lt;code&gt;run&lt;/code&gt; with bash commands to change current directory, run xcodebuild and send code coverage data to &lt;a href="https://codecov.io" rel="noopener noreferrer"&gt;Codecov&lt;/a&gt;. To use matrix variables, I added &lt;code&gt;env&lt;/code&gt; with the required variable name.&lt;/p&gt;

&lt;p&gt;To read more about workflow syntax, check the &lt;a href="https://help.github.com/en/articles/workflow-syntax-for-github-actions" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Comparing to Travis CI, my configuration looked like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;That's it! Here is an example of live logs:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43fgbonu1pddzj1ezn0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43fgbonu1pddzj1ezn0r.png" alt="https://github.com/rosberry/texstyle/pull/15/checks" width="710" height="288"&gt;&lt;/a&gt;&lt;br&gt;
But that's not the end, it's just the start! Suppose that we want to reject pull requests if there are any linting warnings or errors. The most popular lint tool for Swift is &lt;a href="https://github.com/realm/SwiftLint" rel="noopener noreferrer"&gt;Swiftlint&lt;/a&gt;. For now it's possible to run it and see warnings in logs that is not enough. It would be great to see annotations from SwiftLint Violations via &lt;a href="https://blog.github.com/2018-05-07-introducing-checks-api/" rel="noopener noreferrer"&gt;GitHub Checks API&lt;/a&gt;, or even have suggested changes. And actions allow to use this API easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As for me Github Actions CI is a game changer. It is deeply integrated into the service. And community-driven actions allow to reuse common scenarios.&lt;/p&gt;

&lt;p&gt;Let's summarise my experience with pros and cons.&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Various triggers for workflows. Pull requests, staring repos, project card statuses, scheduled events etc.&lt;/li&gt;
&lt;li&gt;Speed. According to logs for Texstyle, last builds were 2 min 12 sec on Travis CI and 1 min 8 sec on Github CI.&lt;/li&gt;
&lt;li&gt;Preinstalled software. macOS images have fastlane, swiftlint, Cocoapods, Carthage etc.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace?type=actions" rel="noopener noreferrer"&gt;Marketplace&lt;/a&gt;. There are plenty of actions developed by community. You can reuse any of them.&lt;/li&gt;
&lt;li&gt;Pricing. Of course, it's free for open source. The time limits look pretty good - 2000 minutes for free plan and 3000 minutes with a Pro plan including private repositories 😏.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Still in beta. First actions were written in HCL syntax. Support for it will be removed on September 30. And maybe it's not the end, YAML syntax may be updated as well. So be ready to migrate your actions before public release.&lt;/li&gt;
&lt;li&gt;Debugging. It's hard to debug workflows as any CI service. You must trigger related event and wait for all steps. It's not possible to test it locally, even validate workflow syntax.&lt;/li&gt;
&lt;li&gt;Documentation. On of the goals of this article is to clarify Actions benefit for myself and give it a try on real project. I had many unobvious errors, official documentation and StackOverflow won't help. For instance, a multiline run command won't work without a &lt;code&gt;name&lt;/code&gt; label. I believe open source workflows will help to avoid dump errors and handle edge cases in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading! If you have any questions or ideas of workflows, feel free to leave comments or ping me on Twitter &lt;a href="http://twitter.com/iosartem" rel="noopener noreferrer"&gt;@iosartem&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://help.github.com/en/categories/automating-your-workflow-with-github-actions" rel="noopener noreferrer"&gt;Automating your workflow with GitHub Actions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/actions" rel="noopener noreferrer"&gt;Github Actions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/sdras/awesome-actions" rel="noopener noreferrer"&gt;Awesome Actions&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>ci</category>
      <category>swift</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
