<?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: Dandan Meng</title>
    <description>The latest articles on DEV Community by Dandan Meng (@mengdd).</description>
    <link>https://dev.to/mengdd</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%2F877166%2F2a775e5e-2232-4d5b-b0d4-04c991eae152.jpeg</url>
      <title>DEV Community: Dandan Meng</title>
      <link>https://dev.to/mengdd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mengdd"/>
    <language>en</language>
    <item>
      <title>Swift vs Kotlin</title>
      <dc:creator>Dandan Meng</dc:creator>
      <pubDate>Mon, 18 Jul 2022 01:23:20 +0000</pubDate>
      <link>https://dev.to/mengdd/swift-vs-kotlin-3lkd</link>
      <guid>https://dev.to/mengdd/swift-vs-kotlin-3lkd</guid>
      <description>&lt;p&gt;This article is aiming to help an Android developer get a quick knowledge of the Swift programming language. (Writing from this perspective.)&lt;/p&gt;

&lt;p&gt;I didn’t mean to write a very long and detailed article to cover everything, just a quick one to get you onboarded.&lt;/p&gt;

&lt;p&gt;This article is also suitable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experienced programmer (who knows other programming languages) wants to learn Swift.&lt;/li&gt;
&lt;li&gt;iOS developer (who knows Swift) wants to learn Kotlin.&lt;/li&gt;
&lt;li&gt;iOS beginner developers.&lt;/li&gt;
&lt;li&gt;Developer hasn’t used Swift for a while and wants to get a quick refresher memo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic types
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Swift&lt;/th&gt;
&lt;th&gt;Kotlin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bool&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array&lt;/td&gt;
&lt;td&gt;Array, List, MutableList&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Set&lt;/td&gt;
&lt;td&gt;Set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dictionary&lt;/td&gt;
&lt;td&gt;Map&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Other types are basically the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Swift&lt;/th&gt;
&lt;th&gt;Kotlin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;variables (not totally equals, see elaboration below)&lt;/td&gt;
&lt;td&gt;let/var&lt;/td&gt;
&lt;td&gt;val/var&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;named arguments&lt;/td&gt;
&lt;td&gt;at: 0&lt;/td&gt;
&lt;td&gt;at = 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;func name() → returnType&lt;/td&gt;
&lt;td&gt;fun name(): returnType&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;absence of a value&lt;/td&gt;
&lt;td&gt;nil&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;unwrapped type&lt;/td&gt;
&lt;td&gt;String!&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;if&lt;/td&gt;
&lt;td&gt;if number != nil&lt;/td&gt;
&lt;td&gt;if(number != null)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;provide default value if nil or null&lt;/td&gt;
&lt;td&gt;xxx ?? “default string”&lt;/td&gt;
&lt;td&gt;? : ”default string”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;if it has value, do {}&lt;/td&gt;
&lt;td&gt;if let number = Int(”333”) {}&lt;/td&gt;
&lt;td&gt;?.let {}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;for loop&lt;/td&gt;
&lt;td&gt;for i in 1...5 {}&lt;/td&gt;
&lt;td&gt;for (i in 1..5) {}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;for loop&lt;/td&gt;
&lt;td&gt;for i in 1..&amp;lt;5 {}&lt;/td&gt;
&lt;td&gt;for (i in 1 until 5) {}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;do while loop&lt;/td&gt;
&lt;td&gt;repeat {} while&lt;/td&gt;
&lt;td&gt;do {} while ()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;this instance&lt;/td&gt;
&lt;td&gt;self&lt;/td&gt;
&lt;td&gt;this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;value object&lt;/td&gt;
&lt;td&gt;struct&lt;/td&gt;
&lt;td&gt;data class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;as?&lt;/td&gt;
&lt;td&gt;as?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;as!&lt;/td&gt;
&lt;td&gt;as&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;try?&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;try!&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;class initializer&lt;/td&gt;
&lt;td&gt;initializer&lt;/td&gt;
&lt;td&gt;constructor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;init a mutable list&lt;/td&gt;
&lt;td&gt;var someInts: [Int] = []&lt;/td&gt;
&lt;td&gt;val someInts = mutableListOf()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;init a empty dictionary/map&lt;/td&gt;
&lt;td&gt;var namesOfIntegers: [Int: String] = [:]&lt;/td&gt;
&lt;td&gt;val namesOfIntegers = mutableMapOf()&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Constants and Variables
&lt;/h3&gt;

&lt;p&gt;Swift:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;let&lt;/code&gt; you can not assign value again. If the type is struct, you can not update any var properties of the instance. (If it's a class, then you can update var properties).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;var&lt;/code&gt; can both assign values or update properties of the instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;var&lt;/code&gt; also makes an array mutable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kotlin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;val&lt;/code&gt; means final in java, you can not assign values again, but you can update the public vars of the instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;var&lt;/code&gt; means you can assign values again.&lt;/li&gt;
&lt;li&gt;collections types’ immutable or mutable are controlled by the data type.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Switch case
&lt;/h3&gt;

&lt;p&gt;Swift:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x == 1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x == 2 or x == 4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x is something else"&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;Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x == 1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x == 2 or x == 4"&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;-&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x is something else"&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;
  
  
  String interpolation
&lt;/h3&gt;

&lt;p&gt;Swift:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Mike"&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The string can also be output in a format:&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;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"%d , %f, %ld, %@"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Mike"&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello $name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;str&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d, %f, %d, %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Function and Closure
&lt;/h2&gt;

&lt;p&gt;The Swift function has an argument label:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;someFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argumentLabel&lt;/span&gt; &lt;span class="nv"&gt;parameterName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// In the function body, parameterName refers to the argument value&lt;/span&gt;
    &lt;span class="c1"&gt;// for that parameter.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while &lt;code&gt;parameterName&lt;/code&gt; is used inside the function, &lt;code&gt;argumentLabel&lt;/code&gt; is used by the caller.&lt;/p&gt;

&lt;p&gt;When an argument label is not provided, parameterName also plays the role of argumentLabel.&lt;/p&gt;

&lt;p&gt;If you don't want to specify an argument label at all, the argument label can be omitted by using underscored &lt;code&gt;_&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closure
&lt;/h3&gt;

&lt;p&gt;Closure is similar to lambda in Kotlin.&lt;/p&gt;

&lt;p&gt;A simple Swift example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sayHello&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="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&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;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mike"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do the same thing in Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;sayHello&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello $name"&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mike"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The type can be inferred from the context.&lt;/li&gt;
&lt;li&gt;Can be passed as arguments as another function’s parameter to achieve nested functions (high-order functions).&lt;/li&gt;
&lt;li&gt;if the closure/lambda is the last parameter, we can put it outside the function’s parentheses. if it’s the only parameter, we don’t need to write parentheses().&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Swift, only single expression closure can omitting the &lt;code&gt;return&lt;/code&gt;
keyword; In Kotlin, the last expression will be treated as the return value, no return keyword in lambda.&lt;/li&gt;
&lt;li&gt;Swift has shorthand argument names such as &lt;code&gt;$0&lt;/code&gt;, &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Custom types
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Swift&lt;/th&gt;
&lt;th&gt;Kotlin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;class&lt;/td&gt;
&lt;td&gt;class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;protocol&lt;/td&gt;
&lt;td&gt;interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;extension&lt;/td&gt;
&lt;td&gt;extension methods&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  class
&lt;/h3&gt;

&lt;p&gt;The class of Swift and Kotlin looks quite the same.&lt;/p&gt;

&lt;p&gt;The inheritance is using &lt;code&gt;:&lt;/code&gt; and the subclass function could &lt;code&gt;override&lt;/code&gt; the super class's function.&lt;/p&gt;

&lt;p&gt;There is an order requirement: the class need to be put before any protocols.&lt;/p&gt;

&lt;p&gt;The only thing different is the constructor, in swift it’s initializer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Person&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&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;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// default name: ""&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&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;"haha"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kotlin, we could achieve the same result by writing like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;p1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${p1.name}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// default name: ""&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;p2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"haha"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${p2.name}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  struct
&lt;/h3&gt;

&lt;p&gt;Struct is value type.&lt;/p&gt;

&lt;p&gt;struct vs class:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;class can inherit.&lt;/li&gt;
&lt;li&gt;struct is value type, copies never share data; class is reference type, all copies will share the same instance.&lt;/li&gt;
&lt;li&gt;class has &lt;code&gt;deinit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;class instance can be &lt;code&gt;let&lt;/code&gt; , and you can change the &lt;code&gt;var&lt;/code&gt; property of the class.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Person&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Lily"&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;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Justin"&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is ok.&lt;/p&gt;

&lt;p&gt;But if Person is a struct:&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;Person&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Lily"&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;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Justin"&lt;/span&gt;
&lt;span class="c1"&gt;// Compiler error: Cannot assign to property: `p1` is a `let` constant&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using struct, we have to use &lt;code&gt;**var** p1 = Person()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  protocol
&lt;/h3&gt;

&lt;p&gt;protocol is just like &lt;code&gt;interface&lt;/code&gt; in Kotlin.&lt;/p&gt;

&lt;p&gt;We could define function and properties as contracts.&lt;/p&gt;

&lt;p&gt;The properties could be:&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;protocol&lt;/span&gt; &lt;span class="kt"&gt;SomeProtocol&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;mustBeSettable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;doesNotNeedToBeSettable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="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;There are slight differences in protocol and interface, like the class implementing the protocol doesn’t need to use the &lt;code&gt;override&lt;/code&gt; keyword on functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  extension
&lt;/h3&gt;

&lt;p&gt;extension is also different. In Swift, extension is more like a place to hold the functions and properties.&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;String&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;trimmed&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;String&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;trimmingCharacters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;whitespacesAndNewlines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;mutating&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;trim&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="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimmed&lt;/span&gt;&lt;span class="p"&gt;()&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;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;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;components&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;separatedBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;newlines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kotlin the extension method could be the top level method, just add the type before &lt;code&gt;.&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;someMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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;
  
  
  enum
&lt;/h3&gt;

&lt;p&gt;Swift enum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="kt"&gt;CompassPoint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;north&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;south&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;east&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;west&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiple cases can be put in one line, separated by comma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="kt"&gt;Planet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;mercury&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;venus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;earth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mars&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jupiter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;saturn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uranus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;neptune&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the enum, we can drop the type using a shorter dot 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="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;directionToHead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;CompassPoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;west&lt;/span&gt;
&lt;span class="n"&gt;directionToHead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;east&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swift enum has an &lt;code&gt;allCases&lt;/code&gt; property, which exposes a collection of all the cases.&lt;/p&gt;

&lt;p&gt;Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;NORTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SOUTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;WEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EAST&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In enum we can also define properties and functions, which is the same for Swift and Kotlin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optionals
&lt;/h2&gt;

&lt;p&gt;While the syntax of Swift’s optional type and Kotlin’s nullable type looks similar (a question mark following the type), they are different.&lt;/p&gt;

&lt;p&gt;Swift’s optional type is more like Java’s &lt;code&gt;Optional&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You will always need to unwrap it before using the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;someString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print nil&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Fatal error: Unexpectedly found nil while unwrapping an Optional value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the variable has value, we want to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;someString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; with length &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// print: Optional("Hello") with length Optional(5)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; with length &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// print: Hello with length 5&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that when used directly, the variable will always be an Optional.&lt;/p&gt;

&lt;p&gt;Actually in Swift there is a simpler way to do this, using &lt;code&gt;if let&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;someStringValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;someString&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someStringValue&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; with length &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someStringValue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;someStringValue&lt;/code&gt; is the unwrapped value from &lt;code&gt;someString&lt;/code&gt;, and the block is only entered when it's not &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Kotlin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;someString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print null&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// NullPointerException&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is mainly when the variable has value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;someString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someString&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$someString with length: ${someString.length}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// print: Hello with length: 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kotlin, after we check the variable is not null, we could use the value directly, in the following code inside &lt;code&gt;{}&lt;/code&gt; , the compiler knows the variable is not null.&lt;/p&gt;

&lt;h3&gt;
  
  
  If let and guard let
&lt;/h3&gt;

&lt;p&gt;As we see in the above sample in the Optional section, the &lt;code&gt;if let&lt;/code&gt; can unwrap the Optional value, and only execute the block when it has value.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;guard let&lt;/code&gt; does the opposite: the &lt;code&gt;else&lt;/code&gt; block will be entered only when the value is &lt;code&gt;nil&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;printSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?){&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Oops we got nil"&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; * &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt; is &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;guard let can be used to do the argument checking and early return.&lt;/p&gt;

&lt;p&gt;After the guard, the number is no longer optional, it has value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last note
&lt;/h2&gt;

&lt;p&gt;I won’t suggest spending much time to learn a language syntax in every detail.&lt;/p&gt;

&lt;p&gt;Just grab some basics and you are ready to go, you will explore more on your daily work.&lt;/p&gt;

&lt;p&gt;Anyway, I hope this article is handy and useful to you.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Swift book: &lt;a href="https://docs.swift.org/swift-book/"&gt;https://docs.swift.org/swift-book/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
    </item>
    <item>
      <title>Android navigation with multiple back stacks</title>
      <dc:creator>Dandan Meng</dc:creator>
      <pubDate>Mon, 20 Jun 2022 17:26:47 +0000</pubDate>
      <link>https://dev.to/mengdd/android-navigation-with-multiple-back-stacks-471o</link>
      <guid>https://dev.to/mengdd/android-navigation-with-multiple-back-stacks-471o</guid>
      <description>&lt;h2&gt;
  
  
  What is multiple stacks
&lt;/h2&gt;

&lt;p&gt;When users navigate in the app, they may choose to go back to the previous destination.&lt;/p&gt;

&lt;p&gt;The history is kept as a “back stack” by Android.&lt;/p&gt;

&lt;p&gt;Sometimes we might need to maintain multiple back stacks in the app and switch between them.&lt;/p&gt;

&lt;p&gt;A typical example is for the bottom navigation bar: each tab could have its own back stack, and when switching tabs, the history will be kept.&lt;/p&gt;

&lt;p&gt;You may have a different design such as a side drawer, the idea is the same, but for this article, let’s take bottom navigation as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  The multi-stack requirements
&lt;/h2&gt;

&lt;p&gt;First thing first, let’s get clear about what we need to achieve.&lt;/p&gt;

&lt;p&gt;When the bottom navigation does not support multi-stacks, the behavior is: after switching to another tab and back, all the destinations opened on that tab are gone, only the root destination shown.&lt;/p&gt;

&lt;p&gt;That’s also acceptable, and even mentioned as the default behavior for Android platform in &lt;a href="https://material.io/components/bottom-navigation#behavior"&gt;material design&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But it also claims that it can be overridden when needed.&lt;/p&gt;

&lt;p&gt;If we want to keep whatever user viewed on the previous tab, that’s a multi-stack requirement.&lt;/p&gt;

&lt;p&gt;Often, it may not be the only requirement.&lt;/p&gt;

&lt;p&gt;Do we want to reset the stack when people double-click the tab?&lt;/p&gt;

&lt;p&gt;Do we want to customize the animations?&lt;/p&gt;

&lt;p&gt;Do we want to support history between tabs? Like if tab A → B → C, when we are on C’s root screen, do we want to go back to B?&lt;/p&gt;

&lt;p&gt;For the bottom navigation’s default behavior (if you create a new bottom nav example using Android Studio), when on the root level of a tab, when clicking the back button, it will first go back to the home tab (the first tab), and when clicking back again, the app will exit.&lt;/p&gt;

&lt;p&gt;It applies to the fixed start destination principle.&lt;/p&gt;

&lt;p&gt;But if you have special needs, you might also consider how to customize that.&lt;/p&gt;

&lt;p&gt;When you go deep dive to the implementations, you will also find details on how to push to the specific stack and how to pop destination out.&lt;/p&gt;

&lt;p&gt;Let’s list our requirements here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintain multiple stacks.&lt;/li&gt;
&lt;li&gt;Switching tabs: by manually clicking tab or some interactions on the other tab. i.e. Dashboard to a specific content tab.&lt;/li&gt;
&lt;li&gt;Push/pop destinations.&lt;/li&gt;
&lt;li&gt;Reselect tab will reset the stack to root level. (clear history.)&lt;/li&gt;
&lt;li&gt;Transition animations.&lt;/li&gt;
&lt;li&gt;Tab history.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Background
&lt;/h2&gt;

&lt;p&gt;It’s important to know what your “destination” is.&lt;br&gt;
For composable or fragments, the solutions could be very different.&lt;/p&gt;

&lt;p&gt;For this article’s scope, let’s focus on a traditional android app built using Activity and Fragments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fragment lifecycle
&lt;/h3&gt;

&lt;p&gt;The fragment’s lifecycle is quite important to check about, as the Fragment’s lifecycle is related to whether we will need to care about state loss or refreshing action, for example, the re-creation of the ViewModel.&lt;/p&gt;

&lt;p&gt;Let’s recap on Fragment’s lifecycle callbacks.&lt;/p&gt;

&lt;p&gt;When would Fragment onDestroy called?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the &lt;code&gt;replace&lt;/code&gt; transaction is without &lt;code&gt;addToBackStack()&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;when the fragment is removed or popped out by &lt;code&gt;popBackStack()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a &lt;code&gt;replace&lt;/code&gt; transaction is called with &lt;code&gt;addToBackStack()&lt;/code&gt;, the old fragment will be pushed into the stack, and the lifecycle is only reached &lt;code&gt;onDestroyView().&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When the top one popped out from the back stack, the old fragment’s instance is still the same. The come-to-show fragment’s lifecycle starts with &lt;code&gt;onCreateView()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is what we expected for a single back stack.&lt;/p&gt;

&lt;p&gt;If the project is using ViewModel, the Fragment’s ViewModel’s lifecycle is also aligned with the Fragment.&lt;/p&gt;

&lt;p&gt;Whenever the Fragment’s &lt;code&gt;onDestroy()&lt;/code&gt; is called, the ViewModel’s &lt;code&gt;onCleared()&lt;/code&gt; is called.&lt;/p&gt;

&lt;p&gt;We can keep variables we cared about in the saved instance bundle, or by using &lt;code&gt;SavedStateHandle&lt;/code&gt;. But if the fragment is not destroyed, we get everything for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigation Libraries/ Possible Solutions
&lt;/h2&gt;

&lt;p&gt;To compare different solutions, I put some samples together.&lt;br&gt;
See my demo: &lt;a href="https://github.com/mengdd/bottom-navigation-samples"&gt;https://github.com/mengdd/bottom-navigation-samples&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Jetpack navigation component
&lt;/h3&gt;

&lt;p&gt;official site: &lt;a href="https://developer.android.com/guide/navigation"&gt;https://developer.android.com/guide/navigation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even in the FragmentManager’s &lt;a href="https://developer.android.com/guide/fragments/fragmentmanager"&gt;doc&lt;/a&gt; it’s recommended to use the navigation library to manage app’s navigation.&lt;/p&gt;

&lt;p&gt;The multiple back stack support added in &lt;a href="https://developer.android.com/jetpack/androidx/releases/navigation#2.4.0-alpha01"&gt;Navigation 2.4.0-alpha01&lt;/a&gt; and &lt;a href="https://developer.android.com/jetpack/androidx/releases/fragment#1.4.0-alpha01"&gt;Fragment 1.4.0-alpha01&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tried the &lt;a href="https://github.com/mengdd/bottom-navigation-samples/tree/main/navigation-components-multi-stack-sample"&gt;demo&lt;/a&gt;, it’s quite simple and clean, and the app does not need extra code to get this.&lt;/p&gt;

&lt;p&gt;We can check the ideas in this article: &lt;a href="https://medium.com/androiddevelopers/multiple-back-stacks-b714d974f134"&gt;https://medium.com/androiddevelopers/multiple-back-stacks-b714d974f134&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Most well-known. It’s the official library built by Google.&lt;/li&gt;
&lt;li&gt;Safe args supported.&lt;/li&gt;
&lt;li&gt;NavigationController supports popping to a specific destination.&lt;/li&gt;
&lt;li&gt;Can work together with the Compose navigation library.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Multi-stack support: When switching bottom tabs, the fragments on the previous tab will be destroyed, when navigate back, they will all be re-created. The page may be refreshed again.&lt;/li&gt;
&lt;li&gt;Because each tab should be a nested navigation graph, the xml navigation graph files feels like boilerplate code to maintain, especially for common destinations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  FragmentManager
&lt;/h3&gt;

&lt;p&gt;If we are doing more customization we could also try to build the multi stack solution by using FragmentManager’s new APIs.&lt;/p&gt;

&lt;p&gt;As in this &lt;a href="https://developer.android.com/guide/fragments/fragmentmanager#multiple-back-stacks"&gt;doc&lt;/a&gt; suggested:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;FragmentManager&lt;/code&gt; allows you to support multiple back stacks with the &lt;code&gt;saveBackStack()&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;restoreBackStack(&lt;/code&gt; methods. These methods allow you to swap between back stacks by saving one back stack and restoring a different one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here we can find that it’s what navigation component is using under the hood.&lt;/p&gt;

&lt;p&gt;And the why the fragments are all destroyed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;saveBackStack()&lt;/code&gt; works similarly to calling &lt;code&gt;popBackStack()&lt;/code&gt; with the optional &lt;code&gt;name&lt;/code&gt;&lt;br&gt;
parameter: the specified transaction and all transactions after it on the stack are popped. The difference is that &lt;code&gt;saveBackStack()&lt;/code&gt; &lt;a href="https://developer.android.com/guide/fragments/saving-state"&gt;saves the state&lt;/a&gt; of all fragments in the popped transactions.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul&gt;
&lt;li&gt;Fine control. Developers get more control and are aware of what is going on.&lt;/li&gt;
&lt;li&gt;Proper if we are working on a project without any navigation library. We don’t need to migrate a lot of code to a new navigation library.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Lots of fragment transaction boilerplate code.&lt;/li&gt;
&lt;li&gt;Same as navigation components: Fragments on the old tab will be destroyed and re-created.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enro
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/isaac-udy/Enro"&gt;https://github.com/isaac-udy/Enro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For large projects with multiple modules, I really recommend this navigation library.&lt;/p&gt;

&lt;p&gt;It helps to decouple the modules dependencies.&lt;/p&gt;

&lt;p&gt;For multi-stack demo: &lt;a href="https://github.com/mengdd/bottom-navigation-samples/tree/main/enro-fragment-multi-stack-sample"&gt;https://github.com/mengdd/bottom-navigation-samples/tree/main/enro-fragment-multi-stack-sample&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Based on annotation, you only need minimal code to do the navigation, making navigation easy like a breeze.&lt;/li&gt;
&lt;li&gt;Designed for multi-module projects, decoupling modules.&lt;/li&gt;
&lt;li&gt;Can get navigation handle in ViewModel.&lt;/li&gt;
&lt;li&gt;Easy to pass type safe arguments and get results.&lt;/li&gt;
&lt;li&gt;Compose Support.&lt;/li&gt;
&lt;li&gt;Having a companion test tool for Unit Test.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Not that well-known. Need to convince others to learn and apply this.&lt;/li&gt;
&lt;li&gt;For Fragments’ multi-stack support: can not reset the stack when reselecting the tab. And it is hard to customize this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Simple-stack
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Zhuinden/simple-stack"&gt;https://github.com/Zhuinden/simple-stack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would suggest this article for the multi-stack solution using simple-stack: &lt;a href="https://zhuinden.medium.com/creating-a-bottomnavigation-multi-stack-using-child-fragments-with-simple-stack-c73c1ca3bbd4"&gt;https://zhuinden.medium.com/creating-a-bottomnavigation-multi-stack-using-child-fragments-with-simple-stack-c73c1ca3bbd4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the beginning the author showed a demo using child fragments.&lt;/p&gt;

&lt;p&gt;This is another idea if we want to implement the multi-stack by ourselves.&lt;/p&gt;

&lt;p&gt;After I tried the multi-stack &lt;a href="https://github.com/mengdd/bottom-navigation-samples/tree/main/simple-stack-multi-stack-sample"&gt;demo&lt;/a&gt; provided by simple-stack, I found that actually more code is required to let any fragment gain the instance of each tab’s local stack.&lt;/p&gt;

&lt;p&gt;In that way we could push/pop the detail fragment.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The author is quite active in the community, so there are a bunch of speeches and articles for the simple-stack library. Good community support and learning resources.&lt;/li&gt;
&lt;li&gt;Multi-stack support: keep fragments alive.&lt;/li&gt;
&lt;li&gt;Can control or clear the history.&lt;/li&gt;
&lt;li&gt;Compose Support with extensions.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;If your bottom tab is in an Activity layout, when using simple-stack’s multi-stack solution, you have to move things into a RootFragment.&lt;/li&gt;
&lt;li&gt;The multi-stack sample provided by the author is quite simple. Need to write some code to retrieve the correct stack instance to push/pop a fragment to/from the current stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other libraries
&lt;/h3&gt;

&lt;p&gt;There are other libraries designed only for multi-stack navigation.&lt;/p&gt;

&lt;p&gt;Such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/DimaKron/Android-MultiStacks"&gt;https://github.com/DimaKron/Android-MultiStacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/JetradarMobile/android-multibackstack"&gt;https://github.com/JetradarMobile/android-multibackstack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The samples are just along the repos.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Simple solutions with only a few classes. We could even copy them to our codebase to customize.&lt;/li&gt;
&lt;li&gt;The change scope could be limited only to the bottom navigation part.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;The libraries are not so well-known, and have the risk of not being maintained anymore.&lt;/li&gt;
&lt;li&gt;Might not be able to work together with other navigation solutions, like Navigation Components. If the project is aiming to apply some nice navigation library in the future, we have to touch this bottom navigation part again.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusions
&lt;/h3&gt;

&lt;p&gt;Possible solutions for android multi-stack navigation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Popular&lt;/th&gt;
&lt;th&gt;A completed suite of navigation solution&lt;/th&gt;
&lt;th&gt;Actively Maintained&lt;/th&gt;
&lt;th&gt;Supporting clear stack history&lt;/th&gt;
&lt;th&gt;Fragment kept, not destroyed&lt;/th&gt;
&lt;th&gt;Multi-modules supported&lt;/th&gt;
&lt;th&gt;Compose Extensions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Jetpack Navigation Components&lt;/td&gt;
&lt;td&gt;Official, Most Well-known navigation library&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fragment Manager&lt;/td&gt;
&lt;td&gt;Android SDK&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enro&lt;/td&gt;
&lt;td&gt;Star: 188&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simple Stack&lt;/td&gt;
&lt;td&gt;Star: 1.2k&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Child Fragments&lt;/td&gt;
&lt;td&gt;Android SDK&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JetradarMobile/android-multibackstack&lt;/td&gt;
&lt;td&gt;Star: 224&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DimaKron/Android-MultiStacks&lt;/td&gt;
&lt;td&gt;Star: 32&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Not sure&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A Completed suite of navigation solution&lt;/strong&gt; means the solution can be applied to the whole app as a way to navigate, not just to solve the multi-stack navigation. Here I skipped the ways using Android SDK’s fragment manager or child fragments. Of course in your whole app you can depend on them to do all the navigations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fragment kept&lt;/strong&gt;: means the fragments in stack will not be destroyed when pushing back to the back stack, or switching the bottom tabs. Even though the fragments will be recreated after switching back, we need extra work to cache what state we had before.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Sample: &lt;a href="https://github.com/mengdd/bottom-navigation-samples"&gt;https://github.com/mengdd/bottom-navigation-samples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/guide/navigation"&gt;Jetpack Navigation Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/isaac-udy/Enro"&gt;Enro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Zhuinden/simple-stack"&gt;Simple-stack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
    </item>
    <item>
      <title>The anti-patterns in Android codebase and why I hate them</title>
      <dc:creator>Dandan Meng</dc:creator>
      <pubDate>Tue, 14 Jun 2022 17:27:16 +0000</pubDate>
      <link>https://dev.to/mengdd/the-anti-patterns-in-android-codebase-and-why-i-hate-them-5g25</link>
      <guid>https://dev.to/mengdd/the-anti-patterns-in-android-codebase-and-why-i-hate-them-5g25</guid>
      <description>&lt;p&gt;As developers, we work with the code everyday. &lt;br&gt;
Mostly we will be working on some existing code created by others, or as we always like to refer to it as “legacy code”.&lt;/p&gt;

&lt;p&gt;Actually, no matter if the codebase is very old or pretty new, there are always some anti-patterns to complain about. Perfect codebase is quite rare.&lt;/p&gt;

&lt;p&gt;In this article I want to list something I hate most in any android codebase, only biased opinions from a normal developer. So feel free to disagree. &lt;/p&gt;
&lt;h2&gt;
  
  
  No. 1 No Kotlin
&lt;/h2&gt;

&lt;p&gt;If a project is purely java and still in an active development state, I don't believe it has the ambition to embrace all the new technologies.&lt;/p&gt;

&lt;p&gt;I don't think working on this project is a good choice for younger developers who are just entering the Android world.&lt;/p&gt;

&lt;p&gt;I would suggest we migrate to Kotlin at least for new features or new code we are touching, bit by bit.&lt;/p&gt;

&lt;p&gt;If we can't do even this, run from this project.&lt;/p&gt;
&lt;h2&gt;
  
  
  No. 2 No DI framework
&lt;/h2&gt;

&lt;p&gt;Well, it is 2022 already.&lt;/p&gt;

&lt;p&gt;For the Android world, Dependency Injection is not a new topic. &lt;br&gt;
In the old days we had dagger, and now Hilt makes things even more easier and simpler.&lt;/p&gt;

&lt;p&gt;If you don't like to follow Google's recommendations you could also choose from many third party solutions such as Koin.&lt;/p&gt;

&lt;p&gt;There are so many options to choose from and you like neither of them.&lt;/p&gt;

&lt;p&gt;The consequences may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are many boilerplate codes just to assemble dependency instances.&lt;/li&gt;
&lt;li&gt;Your singleton instances might be a disaster to look at and maintain.&lt;/li&gt;
&lt;li&gt;If you are using ViewModel, you are writing a lot of Factories to create ViewModels.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  No. 3 object with global variables
&lt;/h2&gt;

&lt;p&gt;This can be another broader topic whether singleton is a pattern/anti-pattern. &lt;/p&gt;

&lt;p&gt;Yes, singleton is useful.&lt;/p&gt;

&lt;p&gt;Only when you are clear about the boundaries. &lt;br&gt;
When you are sure if it's necessary.&lt;br&gt;
Don’t over use it for everything.&lt;/p&gt;

&lt;p&gt;It's even worse when the object has public &lt;code&gt;var&lt;/code&gt;s in it. &lt;br&gt;
Everyone at every place can read and write it.&lt;br&gt;
Yes, it's global variables.&lt;/p&gt;

&lt;p&gt;It feels like a key to the devil's gate.&lt;/p&gt;

&lt;p&gt;You can't image the tricky usages, and it's hard to debug and maintain.&lt;/p&gt;

&lt;p&gt;The object is bad for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's hard to be unit tested.&lt;/li&gt;
&lt;li&gt;Sometimes you have to write ugly code to assign value to it and then set it to null.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's only nice when there are only some utilities functions inside it.&lt;br&gt;
But in the Kotlin world we also have other choices such as the top-level functions and extensions functions.&lt;/p&gt;
&lt;h2&gt;
  
  
  No. 4 More than 10 Feature Toggles and A/B Tests
&lt;/h2&gt;

&lt;p&gt;If you are a product manager you might have strong reasons for all the feature toggles and A/B Tests. And I'm not challenging the values of them.&lt;/p&gt;

&lt;p&gt;As mentioned from the beginning, I'm just a normal developer who deals with this if-else nightmare.&lt;/p&gt;

&lt;p&gt;Even if I totally understand and agree with the business values, it can not stop me from hating them.&lt;/p&gt;

&lt;p&gt;Implementing new features with the feature toggle could be trivial work as you need to keep everything as before when the toggle is off.&lt;/p&gt;

&lt;p&gt;If developers do this on a large scale, like copying the whole file and giving a different name, there could be some duplications. And other changes (for other features) might need to apply to both versions.&lt;/p&gt;

&lt;p&gt;If developers choose to do this on a small scale, like the if-else on several lines. They have to be precise on every change.&lt;br&gt;
There will be multiple if-else.&lt;/p&gt;

&lt;p&gt;Implementing compatibility is not fun.&lt;br&gt;
And it generates code smells.&lt;br&gt;
If the developer is very patient, he will add unit test cases for both toggle on and off scenarios. But he may also have missed some conditions, if the old code is not test covered.&lt;br&gt;
And often, there will be no refactoring.&lt;br&gt;
What's the point of refactoring the code we might not need soon?&lt;/p&gt;

&lt;p&gt;It is also annoying for QA's work as every feature needs to test more flows, which not only means feature A's on and off, but also feature B on feature A's on and off.&lt;/p&gt;

&lt;p&gt;Yup, things would definitely get worse when our feature toggles nested. &lt;br&gt;
They just have the complex relationship you need to explain to QA and yourself. If more than 2 feature toggles are nested, I think it's time to talk to your PO to remove one.&lt;/p&gt;
&lt;h2&gt;
  
  
  No. 5 Legacy dependencies
&lt;/h2&gt;

&lt;p&gt;Some libraries were really popular and now are deprecated.&lt;/p&gt;

&lt;p&gt;I'm looking at you, ButterKnife.&lt;/p&gt;

&lt;p&gt;This is a famous one and I believe it’s quite rare to see it from any android project.&lt;/p&gt;

&lt;p&gt;But in reality we may encounter others.&lt;/p&gt;

&lt;p&gt;Also, there may be some 3rd-party libraries that are not maintained anymore.&lt;/p&gt;

&lt;p&gt;if you have this flag in your &lt;code&gt;gradle.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;android.enableJetifier=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run this task to check if any of your dependencies are still using the legacy support library rather than AndroidX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./gradlew checkJetifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you find some libraries, I bet they have not been updated for years.&lt;/p&gt;

&lt;p&gt;Please evaluate whether you can find a better replacement.&lt;/p&gt;

&lt;h2&gt;
  
  
  No. 6 Misused Inheritance
&lt;/h2&gt;

&lt;p&gt;It's really painful to see a codebase that has a bunch of base classes for its Activities, Fragments, and ViewModels.&lt;/p&gt;

&lt;p&gt;A bunch means several, or, a lot. &lt;/p&gt;

&lt;p&gt;For example, between the feature's Fragment and AndroidX's Fragment, there may be 2 or 3 parent fragments that play their mysterious roles.&lt;/p&gt;

&lt;p&gt;When a developer wants to add a new Fragment, he might get confused whether to inherit from a base Fragment, and which “base” to use.&lt;/p&gt;

&lt;p&gt;And the same for ViewModel. Do you really need a ViewModel to hold the Loading state and another ViewModel to hold the navigation variable?&lt;br&gt;
So a new ViewMoel has to decide if it needs to reuse them all or do things by itself.&lt;/p&gt;

&lt;p&gt;Normally, the BaseFragments and BaseViewModels will have some base type defined as generic types. Or even worse, you have BaseUseCase.&lt;/p&gt;

&lt;p&gt;Please try to get rid of this inheritance net, it makes navigating in IDE harder than before.&lt;/p&gt;

&lt;p&gt;We should minimize the complexity, isn't it?&lt;/p&gt;

&lt;p&gt;I hope you always remember composition over inheritance.&lt;/p&gt;

&lt;h2&gt;
  
  
  No. 7 Interface for everything
&lt;/h2&gt;

&lt;p&gt;You don't need interfaces for everything.&lt;/p&gt;

&lt;p&gt;If the interface has only 1 implementation, there is no reason to keep it.&lt;/p&gt;

&lt;p&gt;Maybe some developer designed this for good intention, but we only ended up with a lot of boilerplate code.&lt;/p&gt;

&lt;p&gt;If the other implementation is for the test, let's review whether it's a real case or just not using any mock framework yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  No. 8 EventBus Style
&lt;/h2&gt;

&lt;p&gt;EventBus is a famous library.&lt;br&gt;
It is also well-known as an anti-pattern, because it's so free, you can publish one thing and receive it anywhere. Making things unorganized.&lt;/p&gt;

&lt;p&gt;The overuse of EventBus in a codebase could be a disaster. &lt;br&gt;
It will decrease the intention to write better structured code.&lt;/p&gt;

&lt;p&gt;Sometimes we are writing “EventBus code” even without actually using the Library. &lt;br&gt;
I hope it’s applied only for a few cases, not a common pattern in your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summing up
&lt;/h2&gt;

&lt;p&gt;That’s it for now.&lt;/p&gt;

&lt;p&gt;Hope this article is helpful to you. You may find we are suffering with the same issues.&lt;br&gt;
Or you get to know why developers in your team are not that happy or struggling with their hair in hand everyday.&lt;/p&gt;

&lt;p&gt;Let’s make our life easier.&lt;/p&gt;

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