<?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: Ben</title>
    <description>The latest articles on DEV Community by Ben (@arkilis).</description>
    <link>https://dev.to/arkilis</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%2F475838%2Fe4479cc0-48b9-4e80-860e-6d282ea30b8c.png</url>
      <title>DEV Community: Ben</title>
      <link>https://dev.to/arkilis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arkilis"/>
    <language>en</language>
    <item>
      <title>2 hours to master RxSwift - Part 1</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Tue, 14 Mar 2023 02:23:28 +0000</pubDate>
      <link>https://dev.to/arkilis/2-hours-to-master-rxswift-part-1-dhf</link>
      <guid>https://dev.to/arkilis/2-hours-to-master-rxswift-part-1-dhf</guid>
      <description>&lt;h2&gt;
  
  
  About this series
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F03%2FRxSwift-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F03%2FRxSwift-1.png" alt="2 hours to master RxSwift - Part 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This series is to help people to get started with RxSwift easily with straight forward examples, plain explanation. And YES, if you would like to spend &lt;strong&gt;2 hours with&lt;/strong&gt; a bit efforts, I am quite confident you will master the RxSwift from zero to hero.&lt;/p&gt;

&lt;p&gt;This is the part 1 of this series which will cover most of the topic on RxSwift, from the basic concept and usage to some advanced techniques. The whole series is using RxSwift 6.5.0 (latest as for now) and Swift 5.0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Roadmaps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Part 1: Introduction and Quick example&lt;/p&gt;

&lt;p&gt;Part 2: Core concepts&lt;/p&gt;

&lt;p&gt;Part 3: Observable in depth&lt;/p&gt;

&lt;p&gt;Part 4: Subscriber in depth&lt;/p&gt;

&lt;p&gt;Part 5: Scheduler&lt;/p&gt;

&lt;p&gt;Part 6: Common Operators&lt;/p&gt;

&lt;p&gt;Part 7: RXSwift with MVVM&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduce RxSwift
&lt;/h2&gt;

&lt;p&gt;RxSwift is a popular &lt;strong&gt;reactive&lt;/strong&gt; programming framework for Swift, which allows us to write code that responds to changes and events.&lt;/p&gt;

&lt;p&gt;Before dive into the RxSwift, let's have a basic under standing on what is the Reactive programming. Reactive programming is a programming paradigm which can efficiently handle asynchronous data streams, by using a set of operators to transform and manipulate these streams, such as user's input, UI change, network responses and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why need RxSwift
&lt;/h2&gt;

&lt;p&gt;Compared with the existing programing paradigm - Functional programming, there are few benefits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RxSwift enhances code reusability and reduces the amount of code.&lt;/li&gt;
&lt;li&gt;RxSwift makes it easier to understand business logic, abstract asynchronous programming, and unify code style, therefore make the code more readable and easier to maintain.&lt;/li&gt;
&lt;li&gt;RxSwift makes it easier to write integrated unit tests, increasing code stability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use a short example on above characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick example of using RxSwift
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1, Integrate RxSwift framework into project
&lt;/h3&gt;

&lt;p&gt;Like many other 3rd party libraries, we need to install the framework. There are a couple of ways of doing so as fully documented on its github page: &lt;a href="https://github.com/ReactiveX/RxSwift" rel="noopener noreferrer"&gt;https://github.com/ReactiveX/RxSwift&lt;/a&gt;. Notice that the current latest version is RxSwift 6.5.0. However, there is an issue with the Swift Package Manager (SPM) installation. So we can either follow their workaround or use other means.&lt;/p&gt;

&lt;h3&gt;
  
  
  2, Functional programming way
&lt;/h3&gt;

&lt;p&gt;Imagine we are doing a view which will verify user's input on their email address. Here is what we used to do:&lt;/p&gt;

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

&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// ViewController.swift&lt;/span&gt;
&lt;span class="c1"&gt;// RXSwiftExercise&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Created by Ben Liu on 6/3/2023.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;

&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;UIKit&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="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;emailTextField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UILabel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&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;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Do any additional setup after loading the view.&lt;/span&gt;
    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTarget&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="nv"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;#selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;textFieldDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:)),&lt;/span&gt; &lt;span class="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;editingChanged&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

  &lt;span class="kd"&gt;@objc&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;textFieldDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;textField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;textField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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="n"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Invalid character"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;This will create a view, and once the user input a invalid character such as &lt;code&gt;!&lt;/code&gt;, the error message will display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F03%2Fimage-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F03%2Fimage-3.png" alt="2 hours to master RxSwift - Part 1"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Functional programming example 1&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, there are few problems with above method:&lt;/p&gt;

&lt;p&gt;1, When user delete the &lt;code&gt;!&lt;/code&gt; in the input text field, the error message is still there, which is quite confusing&lt;/p&gt;

&lt;p&gt;2, If we have multiple text inputs such as we want to add user's username, mobile phone number and more, we need to add check on the textfield. See the code below:&lt;/p&gt;

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

&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// ViewController.swift&lt;/span&gt;
&lt;span class="c1"&gt;// RXSwiftExercise&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Created by Ben Liu on 6/3/2023.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;

&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;UIKit&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="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;emailTextField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UILabel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;mobileTextField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;mobileErrorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UILabel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&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;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Do any additional setup after loading the view.&lt;/span&gt;


    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTarget&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="nv"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;#selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;emailTextFieldDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:)),&lt;/span&gt; &lt;span class="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;editingChanged&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;mobileTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTarget&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="nv"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;#selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mobileTextFieldDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:)),&lt;/span&gt; &lt;span class="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;editingChanged&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

  &lt;span class="kd"&gt;@objc&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;emailTextFieldDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;textField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;textField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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="n"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Invalid character"&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="n"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&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="kd"&gt;@objc&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;mobileTextFieldDidChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;textField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;textField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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="n"&gt;mobileErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Invalid character"&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="n"&gt;mobileErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&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="p"&gt;}&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F03%2Fimage-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F03%2Fimage-4.png" alt="2 hours to master RxSwift - Part 1"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Functional programming 2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are still some problems that not resolved yet:&lt;/p&gt;

&lt;p&gt;1, How to unit test the textfields rules&lt;/p&gt;

&lt;p&gt;2,  How to handle multiple textfields, i.e. 10 inputs, we have to create 10 &lt;code&gt;TextFieldDidChange&lt;/code&gt; methods to deal with that in the worst case.&lt;/p&gt;

&lt;p&gt;This stage of Source code can be found on &lt;a href="https://github.com/arkilis/RxSwiftExercise/tree/03b5e30027a895251ccca8d127296bb405b6bb84" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3, Refactor with RxSwift
&lt;/h3&gt;

&lt;p&gt;Time to show the power of RxSwift:&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;import&lt;/span&gt; &lt;span class="kt"&gt;RxSwift&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;RxCocoa&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="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;emailTextField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UILabel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;mobileTextField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UITextField&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="kd"&gt;@IBOutlet&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;mobileErrorInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UILabel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;disposeBag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DisposeBag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&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;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Do any additional setup after loading the view.&lt;/span&gt;

    &lt;span class="nf"&gt;setupBinding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;setupBinding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;onNext&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$0&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="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emailErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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="s"&gt;"Invalid character"&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="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disposed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;disposeBag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;mobileTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;onNext&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$0&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="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mobileErrorInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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="s"&gt;"Invalid character"&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="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disposed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;disposeBag&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;With just 8 lines, we make the code much simpler and concise. More importantly we can handle as many new textfields as we want, such as user names, address and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  4, Test with the textfields
&lt;/h3&gt;

&lt;p&gt;Here since we are using the text change as the source input, it is better to test with the UI test.&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;XCTest&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;RXSwiftExerciseUITests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;XCTestCase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;setUpWithError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;tearDownWithError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Put teardown code here. This method is called after the invocation of each test method in the class.&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;testTextFields&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;XCUIApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// test email&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;emailTextField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;textFields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;typeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123"&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;emailErrorLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;staticTexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"emailError"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;emailTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;typeText&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="kt"&gt;XCTAssertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;emailErrorLabel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid character"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// test mobile&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;mobileTextField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;textFields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"mobile"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;mobileTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mobileTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;typeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"456"&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;mobileErrorLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;staticTexts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"mobileError"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


    &lt;span class="n"&gt;mobileTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mobileTextField&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;typeText&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="kt"&gt;XCTAssertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mobileErrorLabel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid character"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This stage of Source code can be found on &lt;a href="https://github.com/arkilis/RxSwiftExercise/tree/cab0edeb5728180a047f6e35e0a741d9b8f2aa03" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compared with Combine
&lt;/h2&gt;

&lt;p&gt;Combine was introduced by Apple in 2019, which is another reactive programming framework comes with iOS 13+. Here are few comparisions:&lt;/p&gt;

&lt;h3&gt;
  
  
  1, Compatibility
&lt;/h3&gt;

&lt;p&gt;RxSwift has been available since 2015 and supports iOS 8 and later, while Combine only supports iOS 13 and later.&lt;/p&gt;

&lt;h3&gt;
  
  
  2, API Design
&lt;/h3&gt;

&lt;p&gt;RxSwift is designed to be more flexible and configurable, with a larger number of operators and customization options. On the other hand, Combine has a more concise and streamlined API, with a focus on Swift's built-in functional programming features.&lt;/p&gt;

&lt;h3&gt;
  
  
  3, Support
&lt;/h3&gt;

&lt;p&gt;There are a large amount of projects already using RxSwift, so getting to know and master RxSwift is a necessary skill to get a job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;In the next few articles, we will dig more depth into the RxSwift, first start with some core concepts such as what is &lt;code&gt;Observable&lt;/code&gt;, &lt;code&gt;Subscriber&lt;/code&gt; , &lt;code&gt;Subject&lt;/code&gt; and &lt;code&gt;Operator&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://needone.app/rxswift-tutorial-part-1/" rel="noopener noreferrer"&gt;https://needone.app/rxswift-tutorial-part-1/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>rxswift</category>
      <category>programming</category>
    </item>
    <item>
      <title>RunBlocking in Kotlin Coroutine</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Tue, 28 Feb 2023 02:30:38 +0000</pubDate>
      <link>https://dev.to/arkilis/runblocking-in-kotlin-coroutine-2jkk</link>
      <guid>https://dev.to/arkilis/runblocking-in-kotlin-coroutine-2jkk</guid>
      <description>&lt;p&gt;In previous post, we have gone through most of the key concepts and methods in Coroutine:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kotlin Coroutines Table Content  &lt;/p&gt;

&lt;p&gt;1, &lt;a href="https://needone.app/introduction-to-coroutine-in-kotlin/"&gt;Introduction to Coroutine in Kotlin&lt;/a&gt;&lt;br&gt;&lt;br&gt;
2, &lt;a href="https://needone.app/non-blocking-in-kotlin-coroutines/"&gt;Non-blocking in Kotlin Coroutines&lt;/a&gt;&lt;br&gt;&lt;br&gt;
3, &lt;a href="https://needone.app/start-and-suspend-a-coroutine-in-kotlin/needone.app/start-and-suspend-a-coroutine-in-kotlin/"&gt;Start and Suspend a Coroutine in Kotlin&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, we haven't talked about &lt;code&gt;runBlocking&lt;/code&gt; yet, which is a function provided by the &lt;code&gt;kotlinx.coroutines&lt;/code&gt; library in Kotlin. It is used to start a new coroutine that runs &lt;strong&gt;synchronously&lt;/strong&gt; on the current thread and blocks the thread until the coroutine completes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;runBlocking&lt;/code&gt; is typically used to start a coroutine from a non-coroutine context, such as a main function, a unit test, or a Java method. It allows you to start a coroutine and wait for it to complete without having to manually manage the lifecycle of the coroutine.&lt;/p&gt;

&lt;p&gt;Here's an example of how you might use &lt;code&gt;runBlocking&lt;/code&gt; to start a coroutine and wait for it to complete:&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;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.*&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;runBlocking&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;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&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;println&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;await&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;runBlocking&lt;/code&gt; function starts a new coroutine that runs on the current thread (the main thread in this case). Inside the coroutine, we use the &lt;code&gt;async&lt;/code&gt; function to start another coroutine that sleeps for one second and then returns a string. The &lt;code&gt;await()&lt;/code&gt; function is used to wait for the result of the async coroutine and the result is printed out after 1 sec.&lt;/p&gt;

&lt;p&gt;It's important to note that &lt;code&gt;runBlocking&lt;/code&gt; is a blocking function, so it should be used with caution. It can be useful for small test cases, but for longer-running coroutines it is recommended to use the &lt;code&gt;launch&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; functions and manage the lifecycle of the coroutines manually, in order to not block the main thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  RunBlocking for Unit testing
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;runBlocking&lt;/code&gt; often is used in unit tests to start a coroutine and wait for it to complete. This allows you to test coroutines in a synchronous manner, making it easier to write tests and assert on the results.&lt;/p&gt;

&lt;p&gt;Here's an example of how you might use &lt;code&gt;runBlocking&lt;/code&gt; in a JUnit test:&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;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.Test&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyTests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;testCoroutine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&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;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&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;assertEquals&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="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we use the &lt;code&gt;runBlocking&lt;/code&gt; function to start a new coroutine in the context of the test method. The coroutine sleeps for 1 sec and returns a string, which is then asserted in the test.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;runBlocking&lt;/code&gt; in unit tests can make it easier to write tests and assert on the results of coroutines, but it's important to be aware that it makes the test synchronous, so it will block the current thread until the coroutine completes. Also, it's important to make sure that your coroutines are properly isolated from other parts of the system, by using Dispatchers.Unconfined or test dispatchers, to avoid unexpected results in your test.&lt;/p&gt;

&lt;p&gt;Ref: &lt;a href="https://needone.app/runblocking-in-kotlin/"&gt;https://needone.app/runblocking-in-kotlin/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>coroutine</category>
      <category>android</category>
    </item>
    <item>
      <title>Certificate pinning and Public key pinning</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Tue, 28 Feb 2023 02:21:03 +0000</pubDate>
      <link>https://dev.to/arkilis/certificate-pinning-and-public-key-pinning-59d6</link>
      <guid>https://dev.to/arkilis/certificate-pinning-and-public-key-pinning-59d6</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F02%2Fcertificate-pinning.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fneedone.app%2Fcontent%2Fimages%2F2023%2F02%2Fcertificate-pinning.png" alt="Certificate pinning and Public key pinning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Certificate pinning and public key pinning are both techniques that are used to enhance the security of a network connection by ensuring that the client trusts only a specific certificate or public key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Certificate pinning
&lt;/h2&gt;

&lt;p&gt;Certificate pinning is a security technique that is used to ensure that an app is communicating with the correct server. Certificate pinning works by associating a specific certificate or public key with a server, and checking that the certificate or key is being used when the app communicates with the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Public key pinning
&lt;/h2&gt;

&lt;p&gt;Public key pinning, on the other hand, is a technique in which the client stores the public key of a trusted server and verifies that the public key presented by the server during the SSL/TLS handshake is the same as the stored public key. If the public key presented by the server does not match the stored public key, the connection is terminated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difference between Certificate pinning and Public key pinning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Both used to prevent man-in-the-middle (MITM) attacks, in which an attacker intercepts the communication between the client and the server and presents a fake certificate or public key in an attempt to impersonate the server.&lt;/li&gt;
&lt;li&gt;Certificate pinning may be more effective in some cases, as it verifies the entire certificate chain and all of its associated trust relationships. Public key pinning, on the other hand, only verifies the public key of the server and does not take into account the trust relationships between the server and other certificate authorities.&lt;/li&gt;
&lt;li&gt;Public key pinning might be more flexible which only required to check the public key which can be static. With certificate pinning, we need to replace certificates in the app every time when renew them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implement certificate pinning
&lt;/h2&gt;

&lt;p&gt;To implement certificate pinning in Swift, you can use the &lt;code&gt;URLSession&lt;/code&gt; class and the &lt;code&gt;serverTrustPolicy&lt;/code&gt; property of the &lt;code&gt;ServerTrustPolicy&lt;/code&gt; enum to configure the trust policy of the session, and the &lt;code&gt;URLSessionDelegate&lt;/code&gt; protocol and the &lt;code&gt;urlSession(_:didReceive:completionHandler:)&lt;/code&gt; method to evaluate the server trust. Here is an example of how to do this:&lt;/p&gt;

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

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;PinningDelegate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;URLSessionDelegate&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;urlSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;didReceive&lt;/span&gt; &lt;span class="nv"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;URLAuthenticationChallenge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;completionHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;@escaping&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;URLSession&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;AuthChallengeDisposition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;URLCredential&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;Void&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;challenge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;protectionSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authenticationMethod&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;NSURLAuthenticationMethodServerTrust&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;serverTrust&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;challenge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;protectionSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serverTrust&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;certificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SecTrustGetCertificateAtIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serverTrust&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&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;serverCertificateData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SecCertificateCopyData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Compare the server certificate data with the trusted certificate data&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;serverCertificateData&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;trustedCertificateData&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;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;URLCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;trust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serverTrust&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nf"&gt;completionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;useCredential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credential&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="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Cancel the connection if the server certificate is not trusted&lt;/span&gt;
        &lt;span class="nf"&gt;completionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cancelAuthenticationChallenge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;delegate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;PinningDelegate&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;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;URLSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;delegateQueue&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;url&lt;/span&gt; &lt;span class="o"&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://www.example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataTask&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;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle the response here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;In this example, the &lt;code&gt;PinningDelegate&lt;/code&gt; class is a delegate of the &lt;code&gt;URLSession&lt;/code&gt; class that implements the &lt;code&gt;urlSession(_:didReceive:completionHandler:)&lt;/code&gt; method. The method is called when the session receives an authentication challenge from the server, and it is used to evaluate the server trust. The method retrieves the server trust and the server certificate from the challenge, and it compares the server certificate data with the trusted certificate data. If the server certificate is trusted, the method creates a &lt;code&gt;URLCredential&lt;/code&gt; object with the server trust and returns it to the session, and the session continues the connection. If the server certificate is not trusted, the method cancels the connection and returns &lt;code&gt;nil&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement public key pinning
&lt;/h2&gt;

&lt;p&gt;To implement certificate pinning in a Swift app, you can use the &lt;code&gt;ServerTrustPolicyManager&lt;/code&gt; and &lt;code&gt;ServerTrustPolicy&lt;/code&gt; classes from the Alamofire library. The &lt;code&gt;ServerTrustPolicyManager&lt;/code&gt; class allows you to specify a set of trusted certificates or public keys, and the &lt;code&gt;ServerTrustPolicy&lt;/code&gt; class allows you to specify the certificate pinning policy for a particular server.&lt;/p&gt;

&lt;p&gt;Here is an example of how to use the &lt;code&gt;ServerTrustPolicyManager&lt;/code&gt; and &lt;code&gt;ServerTrustPolicy&lt;/code&gt; classes to pin a certificate in a Swift app:&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;Alamofire&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;certificateData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;base64Encoded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;certificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;SecCertificateCreateWithData&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="n"&gt;certificateData&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;CFData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;trustedCertificates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;certificate&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;serverTrustPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ServerTrustPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pinCertificates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;certificates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;trustedCertificates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;validateCertificateChain&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;validateHost&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="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;serverTrustPolicyManager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ServerTrustPolicyManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"example.com"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serverTrustPolicy&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="kt"&gt;AF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;serverTrustPolicyManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;serverTrustPolicyManager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle the response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;In this example, we use the &lt;code&gt;SecCertificateCreateWithData&lt;/code&gt; function to create a &lt;code&gt;SecCertificate&lt;/code&gt; object from the certificate data, and add it to an array of trusted certificates. We then use the &lt;code&gt;ServerTrustPolicy.pinCertificates&lt;/code&gt; method to create a &lt;code&gt;ServerTrustPolicy&lt;/code&gt; object that trusts the specified certificates, and validate the certificate chain and host. We then create a &lt;code&gt;ServerTrustPolicyManager&lt;/code&gt; with the &lt;code&gt;ServerTrustPolicy&lt;/code&gt; just created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further read
&lt;/h2&gt;

&lt;p&gt;Certificate pinning and Public key pinning in Kotlin.&lt;/p&gt;

&lt;p&gt;Ref: &lt;a href="https://needone.app/certifate-pinning-public-key-pinning/" rel="noopener noreferrer"&gt;https://needone.app/certifate-pinning-public-key-pinning/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swift</category>
      <category>apple</category>
    </item>
    <item>
      <title>Encode URL in Kotlin</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Mon, 27 Feb 2023 22:49:35 +0000</pubDate>
      <link>https://dev.to/arkilis/encode-url-in-kotlin-59en</link>
      <guid>https://dev.to/arkilis/encode-url-in-kotlin-59en</guid>
      <description>&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%2F4sfaj06ud2l2oentesyd.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%2F4sfaj06ud2l2oentesyd.png" alt="Encode URL in Kotlin" width="700" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Kotlin, you can use the &lt;code&gt;URLEncoder&lt;/code&gt; class to encode a URL string so that it can be safely transmitted over the internet. The &lt;code&gt;URLEncoder&lt;/code&gt; class is part of the Java standard library, and it provides a method called &lt;code&gt;encode&lt;/code&gt; that can be used to encode a URL string.&lt;/p&gt;

&lt;p&gt;Here's an example of how to use the &lt;code&gt;URLEncoder.encode&lt;/code&gt; method to encode a URL string 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="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.net.URLEncoder&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&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;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://www.example.com?q=hello world"&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;encodedUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;URLEncoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encodedUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints "https%3A%2F%2Fwww.example.com%3Fq%3Dhello%20world"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we define a URL string that includes a query parameter with a space character. We then use the &lt;code&gt;URLEncoder.encode&lt;/code&gt; method to encode the URL string using the UTF-8 character encoding. The encoded URL is then printed to the console.&lt;/p&gt;

&lt;p&gt;Overall, the &lt;code&gt;URLEncoder&lt;/code&gt; class can be used to encode a URL string in Kotlin, ensuring that it can be safely transmitted over the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Read
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://needone.app/http-encoding/" rel="noopener noreferrer"&gt;HTTP Encoding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://needone.app/encode-url-in-swift/" rel="noopener noreferrer"&gt;Encode URL in Swift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Certificate pinning and Public key pinning in Kotlin</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Mon, 27 Feb 2023 21:16:16 +0000</pubDate>
      <link>https://dev.to/arkilis/certificate-pinning-and-public-key-pinning-in-kotlin-5he2</link>
      <guid>https://dev.to/arkilis/certificate-pinning-and-public-key-pinning-in-kotlin-5he2</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZWS7yPa---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://needone.app/content/images/2023/02/Cerificate-pinning.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZWS7yPa---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://needone.app/content/images/2023/02/Cerificate-pinning.png" alt="Certificate pinning and Public key pinning in Kotlin" width="700" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the last article (&lt;a href="https://needone.app/certifate-pinning-public-key-pinning/"&gt;Certificate pinning and Public key pinning&lt;/a&gt;), we know the concept of Certificate pinning and Public key pinning, and how to implement them in iOS. This article will demonstrate how to implement them in Kotlin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement certificate pinning
&lt;/h2&gt;

&lt;p&gt;Certificate pinning is a security technique that involves associating a specific certificate or public key with a particular server. This helps to prevent man-in-the-middle attacks by ensuring that the client only trusts the specific certificate or public key associated with the server, and not any other certificate that may be presented by an attacker.&lt;/p&gt;

&lt;p&gt;Here is an example of how to implement certificate pinning in Kotlin using the OkHttp library:&lt;/p&gt;

&lt;h2&gt;
  
  
  Implement public key pinning
&lt;/h2&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;certificatePinner&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CertificatePinner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sha256/1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&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;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;certificatePinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;certificatePinner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&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;request&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we create a &lt;code&gt;CertificatePinner&lt;/code&gt; object using the &lt;code&gt;CertificatePinner.Builder&lt;/code&gt; class. We add a pin for the &lt;code&gt;example.com&lt;/code&gt; domain using the &lt;code&gt;add&lt;/code&gt; method, specifying the domain name and the SHA-256 hash of the public key.&lt;/p&gt;

&lt;p&gt;Next, we create an &lt;code&gt;OkHttpClient&lt;/code&gt; object using the &lt;code&gt;OkHttpClient.Builder&lt;/code&gt; class and set the &lt;code&gt;CertificatePinner&lt;/code&gt; object using the &lt;code&gt;certificatePinner&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Finally, we create a &lt;code&gt;Request&lt;/code&gt; object using the &lt;code&gt;Request.Builder&lt;/code&gt; class and specify the URL of the server. We use the &lt;code&gt;OkHttpClient&lt;/code&gt; object to send the request and execute it.&lt;/p&gt;

&lt;p&gt;Ref: &lt;a href="https://needone.app/certificate-pinning-and-public-key-pinning-in-kotlin/"&gt;https://needone.app/certificate-pinning-and-public-key-pinning-in-kotlin/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Download image from URL in Kotlin</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Mon, 20 Feb 2023 23:50:40 +0000</pubDate>
      <link>https://dev.to/arkilis/download-image-from-url-in-kotlin-4fc6</link>
      <guid>https://dev.to/arkilis/download-image-from-url-in-kotlin-4fc6</guid>
      <description>&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%2F0pcx6gcja551330eooqb.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%2F0pcx6gcja551330eooqb.png" alt="Download image from URL in Kotlin" width="700" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Android, we can get the image from synchronously and asynchronously, but it is more common to see in the later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Download image synchronously
&lt;/h2&gt;

&lt;p&gt;To download an image from a URL in Kotlin, you can use the &lt;code&gt;URL&lt;/code&gt; class and the &lt;code&gt;readBytes&lt;/code&gt; function from the &lt;code&gt;kotlin.io&lt;/code&gt; library. The &lt;code&gt;URL&lt;/code&gt; class represents a uniform resource locator and provides methods for creating and parsing URLs. The &lt;code&gt;readBytes&lt;/code&gt; function can be used to read the contents of a file or a stream as a byte array.&lt;/p&gt;

&lt;p&gt;Here's an example of how to use the &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;readBytes&lt;/code&gt; to download an image from a URL 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="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.net.URL&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.io.readBytes&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&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;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com/image.png"&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;imageData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readBytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: Save the image data to a file or display it in an ImageView&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we create a &lt;code&gt;URL&lt;/code&gt; object using the URL of the image as a string. We then use the &lt;code&gt;readBytes&lt;/code&gt; function to read the contents of the URL as a byte array. The byte array contains the data for the image, which can then be saved to a file or displayed in an &lt;code&gt;ImageView&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Download image asynchronously
&lt;/h2&gt;

&lt;p&gt;To download an image from a URL in Kotlin asynchronously, you can use a coroutine combined with above method. For more&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;import&lt;/span&gt; &lt;span class="nn"&gt;kotlinx.coroutines.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.net.URL&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kotlin.io.readBytes&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a new coroutine scope&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CoroutineScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Dispatchers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Launch a new coroutine in the scope&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&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;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com/image.png"&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;imageData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readBytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;// TODO: Save the image data to a file or display it in an ImageView&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we create a new coroutine scope using the &lt;code&gt;Dispatchers.Default&lt;/code&gt; dispatcher, which runs the coroutine on a shared background thread pool. We then launch a new coroutine in the scope using the &lt;code&gt;launch&lt;/code&gt; function. Inside the coroutine, we create a &lt;code&gt;URL&lt;/code&gt; object using the URL of the image as a string and use the &lt;code&gt;readBytes&lt;/code&gt; function to read the contents of the URL as a byte array. The byte array contains the data for the image, which can then be saved to a file or displayed in an &lt;code&gt;ImageView&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>openai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>[System.Serializable] in Unity</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Fri, 17 Feb 2023 19:59:23 +0000</pubDate>
      <link>https://dev.to/arkilis/systemserializable-in-unity-25hm</link>
      <guid>https://dev.to/arkilis/systemserializable-in-unity-25hm</guid>
      <description>&lt;p&gt;&lt;code&gt;[System.Serializable]&lt;/code&gt; is a C# attribute that can be applied to a class, struct, or field to indicate that it can be serialized by Unity's serialization system. By doing which will allow developer to save data locally (or remotely via API) , and reload later. Here's a simple example of how to use the &lt;code&gt;[System.Serializable]&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serializable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlayerData&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;health&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 reason of using the &lt;code&gt;[System.Serializable]&lt;/code&gt; is it can make a custom class Serializable, meaning store and reload from local device in text format, such as Json or xml.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of data can be serialized
&lt;/h2&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic data types such as int, float, and string&lt;/li&gt;
&lt;li&gt;Arrays of basic data types or other serializable objects&lt;/li&gt;
&lt;li&gt;Classes that implement the &lt;code&gt;ISerializable&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;Lists, dictionaries, and other collection types that contain serializable objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, some other types such as &lt;code&gt;Transform&lt;/code&gt; can't be serialized, or custom data type that user define themselves. So how to serialize those kinds of data types?&lt;/p&gt;

&lt;h2&gt;
  
  
  Serialize advanced data types
&lt;/h2&gt;

&lt;p&gt;To serialize advanced data types such as &lt;code&gt;Transform&lt;/code&gt;, we can create a wrapper class to hold the values of a transform that we want to serialize. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TransformSerialize&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Start is called before the first frame update&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transform: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;gameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;SerializableTransform&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SerializableTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonUtility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transform json: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Transform&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonUtility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromJson&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SerializableTransform&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;DeserializableTransform&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transform json to object: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update is called once per frame&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

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


&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serializable&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SerializableTransform&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Quaternion&lt;/span&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;SerializableTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Transform&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;rotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;localScale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Transform&lt;/span&gt; &lt;span class="nf"&gt;DeserializableTransform&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;GameObject&lt;/span&gt; &lt;span class="n"&gt;tempGamObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Transform&lt;/span&gt; &lt;span class="n"&gt;newTransform&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tempGamObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;newTransform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;newTransform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;newTransform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;localScale&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale&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;newTransform&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 above script, we have a SerializableTransform which can convert a Transform data Serializable. Also we can have a method which can revert it back DeserializableTransform.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;👉 If you want received more stories like this, please subscribe my channel to get the latest update in time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;**Ref: **&lt;a href="https://hackingwithunity.com/system-serializable-in-unity/" rel="noopener noreferrer"&gt;https://hackingwithunity.com/system-serializable-in-unity/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sideprojects</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introduction to Coroutine in Kotlin</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Wed, 15 Feb 2023 23:29:18 +0000</pubDate>
      <link>https://dev.to/arkilis/introduction-to-coroutine-in-kotlin-1i64</link>
      <guid>https://dev.to/arkilis/introduction-to-coroutine-in-kotlin-1i64</guid>
      <description>&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%2Fk1wo7tkx7knwtjw1q6hd.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%2Fk1wo7tkx7knwtjw1q6hd.png" alt="Introduction to Coroutine in Kotlin" width="700" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Coroutine is a lightweight thread of execution that can be suspended and resumed later. There are already many articles or topics covering this but this post is different, it is simple and can let you get start more easily. It will cover the following parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://needone.app/introduction-to-coroutine-in-kotlin/" rel="noopener noreferrer"&gt;Introduction to Coroutine in Kotlin&lt;/a&gt; (This article)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://needone.app/non-blocking-in-kotlin-coroutines/" rel="noopener noreferrer"&gt;Non-blocking in Kotlin Coroutines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Start and Suspend a Coroutine in Kotlin (Incoming this week)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Like many other programming languages such as JS, Python, Coroutine is a feature provided by Kotlin that enable us to perform long and time consuming task. In short:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Kotlin, Coroutines are a way to write asynchronous, non-blocking code in a more sequential, easy-to-read way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In fact, nothing new techiques here. We can treat Kotlin Coroutine as a framework/library that encapsulates the some common usages while dealing with asynchronization.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Simple examples of using coroutines in Kotlin
&lt;/h2&gt;

&lt;p&gt;To use coroutines in Kotlin, you need to include the &lt;code&gt;kotlinx-coroutines-core&lt;/code&gt; library in your project. In your app gradle file (there is only one gradle file under IntelliJ project, or choose the gradle file for app if it is Android project), add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    testImplementation(kotlin("test-junit"))
    implementation(kotlin("stdlib-jdk8"))
    // add coroutine dependency
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can use the &lt;code&gt;suspend&lt;/code&gt; keyword to mark a function as a coroutine and use the &lt;code&gt;launch&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; functions to start a coroutine.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use &lt;code&gt;launch&lt;/code&gt; to create coroutines
&lt;/h3&gt;

&lt;p&gt;Here is an example of using a coroutine to perform a long-running task in the background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import kotlinx.coroutines.*

fun main() {
    // Start a coroutine using the launch function
    val job = GlobalScope.launch {
        // Perform a long-running task in the background
        delay(1000L)
        println("Hello, world!")
    }

    // Wait for the coroutine to finish
    runBlocking {
        job.join()
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://gist.github.com/arkilis/6cdd2d4ad1d30e5852cd1a46210833e0" rel="noopener noreferrer"&gt;https://gist.github.com/arkilis/6cdd2d4ad1d30e5852cd1a46210833e0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, the &lt;code&gt;launch&lt;/code&gt; function starts a coroutine in the background and returns a &lt;code&gt;Job&lt;/code&gt; object that you can use to wait for the coroutine to finish. The &lt;code&gt;delay&lt;/code&gt; function is a suspending function that suspends the coroutine for a given amount of time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use &lt;code&gt;async&lt;/code&gt; to create coroutines
&lt;/h3&gt;

&lt;p&gt;Here is an example of using coroutines in Kotlin to perform multiple tasks in parallel and then wait for all of them to finish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import kotlinx.coroutines.*

fun main() {
    // Start two coroutines using the async function
    val job1 = GlobalScope.async {
        // Perform a long-running task in the background
        delay(1000L)
        println("Task 1")
    }

    val job2 = GlobalScope.async {
        // Perform a different long-running task in the background
        delay(2000L)
        println("Task 2")
    }

    // Wait for both coroutines to finish
    runBlocking {
        job1.await()
        job2.await()
    }
}

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

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;async&lt;/code&gt; function is used to start two coroutines in the background. The &lt;code&gt;await&lt;/code&gt; function is used to wait for the coroutines to finish. Because the coroutines are running concurrently, the tasks are performed in parallel and the output is printed in the order that the tasks complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  The difference between launch and async to start a coroutine
&lt;/h2&gt;

&lt;p&gt;Both of them are commonly used to start a coroutine. The main difference between the two is that &lt;code&gt;launch&lt;/code&gt; returns a Job (a non-blocking cancellable future) and does not return a result, while &lt;code&gt;async&lt;/code&gt; returns a Deferred (a non-blocking cancellable future with a result) that can be used to obtain the result of the coroutine. Considering the difference, when should use the launch and async to create coroutines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you use &lt;code&gt;launch&lt;/code&gt; function, the coroutine will run in the background and the function call will return immediately. It is used when the result of the coroutine is not needed.&lt;/li&gt;
&lt;li&gt;When you use &lt;code&gt;async&lt;/code&gt; function, the coroutine will also run in the background and the function call will return immediately, but it will return a &lt;code&gt;Deferred&lt;/code&gt; object on which you can call .await() function to get the result of the coroutine. It is used when the result of the coroutine is needed. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val result = GlobalScope.async {
        return@async URL("https://api.example.com/data").readText()
    }
val data = result.await()
println(data)
// output: {"fact":"A group of cats is called a \u201cclowder.\u201d","length":38}

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

&lt;/div&gt;



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

&lt;p&gt;Coroutines can make it easier to write concurrent and asynchronous code in Kotlin, it is not some cutting-edge technology but a wrapper of threads provided by Kotlin.&lt;/p&gt;

&lt;p&gt;What is more from here? As we know Coroutine is a big topic and few wores can explain all of it. This is the first article of the Coroutine series. If you interested, please subscribe for more coming posts on this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://needone.app/non-blocking-in-kotlin-coroutines/" rel="noopener noreferrer"&gt;Non-blocking in Kotlin Coroutines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Start and Suspend a Coroutine in Kotlin (Incoming this week)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To learn more about coroutines and how to use them, you can read the official documentation at &lt;a href="https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html" rel="noopener noreferrer"&gt;https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>git</category>
      <category>writing</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Lazy in Kotlin</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Wed, 15 Feb 2023 23:26:53 +0000</pubDate>
      <link>https://dev.to/arkilis/lazy-in-kotlin-2jb2</link>
      <guid>https://dev.to/arkilis/lazy-in-kotlin-2jb2</guid>
      <description>&lt;p&gt;In the Kotlin programming language, the term "lazy" typically refers to a type of property or variable that is only initialized when it is first accessed, rather than when the containing object is created. This can be useful for optimizing the performance of an application, by delaying the creation of costly objects until they are actually needed.&lt;/p&gt;

&lt;p&gt;For example, consider the following code that defines a &lt;code&gt;LazyProperty&lt;/code&gt; class with a &lt;code&gt;lazy&lt;/code&gt; property called &lt;code&gt;val&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LazyProperty&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;lazy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"Hello"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this case, the &lt;code&gt;lazy&lt;/code&gt; property will only be initialized when it is first accessed, at which point the &lt;code&gt;lazy&lt;/code&gt; block will be executed to compute its value. This means that if the &lt;code&gt;lazy&lt;/code&gt; property is never accessed, the expensive computation will never be performed, which can save resources and improve performance.&lt;/p&gt;

&lt;p&gt;You can also specify additional parameters for the &lt;code&gt;by lazy&lt;/code&gt; delegate, such as the &lt;code&gt;mode&lt;/code&gt; which determines whether the property should be initialized eagerly (i.e., when the containing object is created) or lazily (i.e., when the property is first accessed). For example:&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;LazyProperty&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;lazy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LazyThreadSafetyMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SYNCHRONIZED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// some expensive computation&lt;/span&gt;
    &lt;span class="s"&gt;"Hello"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this case, the &lt;code&gt;lazy&lt;/code&gt; property will be initialized using the &lt;code&gt;SYNCHRONIZED&lt;/code&gt; thread safety mode, which means that multiple threads can safely access the property without the need for explicit synchronization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of using Lazy in Kotlin
&lt;/h2&gt;

&lt;p&gt;There are several benefits to using lazy properties in Kotlin, including improved performance and reduced memory usage.&lt;/p&gt;

&lt;p&gt;One of the main benefits of lazy properties is that they can improve the performance of an application by delaying the initialization of costly objects until they are actually needed. For example, if you have an object that takes a long time to create or requires a lot of memory, you can use a lazy property to defer its creation until it is first accessed. This can save resources and improve the overall performance of the application.&lt;/p&gt;

&lt;p&gt;Another benefit of lazy properties is that they can help to reduce memory usage by only creating objects when they are actually needed. This is because lazy properties are only initialized when they are first accessed, and are then cached for future use. This means that if a lazy property is never accessed, the object it references will never be created, which can save memory.&lt;/p&gt;

&lt;p&gt;Additionally, lazy properties can make your code easier to read and understand, by explicitly separating the initialization of an object from its usage. This can make it clear when and how an object is being created, which can help to prevent mistakes and improve the maintainability of your code.&lt;/p&gt;

&lt;p&gt;Overall, lazy properties can be a useful tool for optimizing the performance and memory usage of your Kotlin application, and can make your code easier to read and understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawbacks of using Lazy in Kotlin
&lt;/h2&gt;

&lt;p&gt;While lazy properties can offer many benefits, there are also some potential drawbacks to consider.&lt;/p&gt;

&lt;p&gt;One potential drawback of lazy properties is that they can make your code more complex, by requiring you to use the &lt;code&gt;by lazy&lt;/code&gt; delegate and specify a lambda expression for initializing the property. This can add additional overhead to your code, and can make it more difficult to understand for other developers who are not familiar with the concept of lazy properties.&lt;/p&gt;

&lt;p&gt;Another potential drawback is that lazy properties can make it more difficult to test your code, since the initialization of a lazy property is deferred until it is first accessed. This can make it challenging to ensure that the property has been properly initialized in your test cases, and can require you to use additional tools or techniques to verify its behavior.&lt;/p&gt;

&lt;p&gt;Additionally, lazy properties can introduce potential race conditions in your code if they are not used carefully. For example, if multiple threads try to access a lazy property concurrently, it is possible that the property will be initialized multiple times, which can lead to unexpected behavior and potential errors.&lt;/p&gt;

&lt;p&gt;Overall, while lazy properties can offer many benefits, it is important to consider these potential drawbacks and use them carefully in order to avoid potential problems.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
    </item>
    <item>
      <title>What is the difference between GameObject.FindObjectOfType and GetComponent</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Tue, 14 Feb 2023 20:19:21 +0000</pubDate>
      <link>https://dev.to/arkilis/what-is-the-difference-between-gameobjectfindobjectoftype-and-getcomponent-3cg8</link>
      <guid>https://dev.to/arkilis/what-is-the-difference-between-gameobjectfindobjectoftype-and-getcomponent-3cg8</guid>
      <description>&lt;p&gt;In Unity, it is quite often to get a GameObject's component, such RigidBody or collision2D. There are a couple of ways of doing so, and GameObject.FindObjectOfType&amp;lt;&amp;gt;() ,GetComponent&amp;lt;&amp;gt;() are both frequently used.&lt;/p&gt;

&lt;h2&gt;
  
  
  GameObject.FindObjectOfType&amp;lt;&amp;gt;()
&lt;/h2&gt;

&lt;p&gt;GameObject.FindObjectOfType&amp;lt;&amp;gt;() will search the entire scene for a component of the specified type. Therefore, which is way slower if we have a large amount of game objects in current scene, but it can be useful in some occasions, such as if you need to access a component that is not attached to the same GameObject as the script. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;GameManager&lt;/span&gt; &lt;span class="n"&gt;gm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindObjectOfType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameManager&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the current GameManager in current scene.&lt;/p&gt;

&lt;h2&gt;
  
  
  GetComponent&amp;lt;&amp;gt;()
&lt;/h2&gt;

&lt;p&gt;On the other hand, GetComponent&amp;lt;&amp;gt;() is used to obtain component(s) which attached to the same GameObject that the script is attached to. Therefore it is a much faster method to access a component as it only searches the current GameObject and its children. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Rigidbody2D&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Rigidbody2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the Rigidbody2D of current game object.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;**👉 If you want received more stories like this, please subscribe my channel to get the latest update in time.&lt;/p&gt;

&lt;p&gt;Ref: &lt;a href="https://hackingwithunity.com/what-is-the-difference-between-gameobject-findobjectoftype-and-getcomponent/" rel="noopener noreferrer"&gt;https://hackingwithunity.com/what-is-the-difference-between-gameobject-findobjectoftype-and-getcomponent/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>architecture</category>
      <category>help</category>
      <category>discuss</category>
    </item>
    <item>
      <title>SceneDelegate</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Tue, 14 Feb 2023 20:03:19 +0000</pubDate>
      <link>https://dev.to/arkilis/scenedelegate-6h4</link>
      <guid>https://dev.to/arkilis/scenedelegate-6h4</guid>
      <description>&lt;p&gt;In iOS, the SceneDelegate is a class that is responsible for managing the scenes in your app. A scene is a discrete unit of your app's user interface, such as a window or tab. The SceneDelegate class provides methods that are called at various points in the lifecycle of a scene, such as when a scene is about to be displayed, or when a scene is about to be destroyed.&lt;/p&gt;

&lt;p&gt;The SceneDelegate class is typically used to manage the state of a scene and to respond to events that affect the scene. For example, the SceneDelegate class might be used to manage the size and position of a window, or to respond to changes in the device's orientation.&lt;/p&gt;

&lt;p&gt;In general, the SceneDelegate class is an optional part of the iOS app architecture, and you do not need to use it in your app unless you need to manage multiple scenes. If you only have one scene in your app, you can use the AppDelegate class to manage the lifecycle of your app instead.&lt;/p&gt;

&lt;p&gt;Remove the SceneDelegate&lt;/p&gt;

&lt;p&gt;There might be some reason we probably don't want the SceneDelegate class. To remove the SceneDelegate class from your iOS app, you can follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your project in Xcode and in the Project Navigator, navigate to the SceneDelegate.swift file and delete it.&lt;/li&gt;
&lt;li&gt;In the Project Navigator, navigate to the AppDelegate.swift file.&lt;/li&gt;
&lt;li&gt;In the AppDelegate class, remove the UISceneDelegate protocol from the class declaration.&lt;/li&gt;
&lt;li&gt;In the AppDelegate class, remove the var window: UIWindow? property.&lt;/li&gt;
&lt;li&gt;In the AppDelegate class, remove the following methods:
&lt;/li&gt;
&lt;/ol&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;scene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;willConnectTo&lt;/span&gt; &lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UISceneSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="nv"&gt;connectionOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;ConnectionOptions&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;sceneDidDisconnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&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;sceneDidBecomeActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&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;sceneWillResignActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&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;sceneWillEnterForeground&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&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;sceneDidEnterBackground&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UIScene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6, In the Info.plist file, remove the UISceneManifest key and its associated dictionary.&lt;/p&gt;

&lt;p&gt;After completing these steps, the SceneDelegate class will be removed from your app, and the AppDelegate class will be the only class responsible for managing the lifecycle of your app. However, note that removing the SceneDelegate class will also remove the ability to manage multiple scenes in your app, so you should only do this if you do not need this functionality.&lt;/p&gt;

&lt;p&gt;For more detalis: &lt;a href="https://needone.app/scenedelegate-in-swift/" rel="noopener noreferrer"&gt;https://needone.app/scenedelegate-in-swift/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tooling</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Format currency in Swift</title>
      <dc:creator>Ben</dc:creator>
      <pubDate>Tue, 14 Feb 2023 19:47:17 +0000</pubDate>
      <link>https://dev.to/arkilis/format-currency-in-swift-9ng</link>
      <guid>https://dev.to/arkilis/format-currency-in-swift-9ng</guid>
      <description>&lt;p&gt;Recently I have done quite an amount of work on formatting currency in Swift project, here are some tricks on how to format number in Swift:&lt;/p&gt;

&lt;h2&gt;
  
  
  Format currency with auto  currency symbol
&lt;/h2&gt;

&lt;p&gt;By using the &lt;code&gt;NumberFormatter&lt;/code&gt; class, we can convert numbers into string(s), and vice versa. More conveniently, we can also configure a &lt;code&gt;NumberFormatter&lt;/code&gt; object to display currency values in a specific locale with a specific currency symbol automatically. For example, € in European countries, $ in Australia and son on.&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;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;currencyFormatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NumberFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;currencyFormatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;
&lt;span class="n"&gt;currencyFormatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"en_US"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formattedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;currencyFormatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&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;formattedValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "$100.00"&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Format currency with max 2 decimals
&lt;/h2&gt;

&lt;p&gt;Moreover, we can also format the currency values in specific format, such as converting 100.78 to $100.78:&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;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NumberFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimumFractionDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maximumFractionDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;amount1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;100.78&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formattedAmount1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&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;formattedAmount1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Output: "$100.78"&lt;/span&gt;

&lt;span class="c1"&gt;// input is whole amount&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;amount2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formattedAmount2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&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;formattedAmount2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Output: "$100"&lt;/span&gt;

&lt;span class="c1"&gt;// input is whole amount&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;amount3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;100.1&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formattedAmount3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&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;formattedAmount3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Output: "$100.1"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;minimumFractionDigits&lt;/code&gt; meaning if the original value is whole amount or just 1 decimal part, it will only show 0 or 1 decimals, see above examples on &lt;code&gt;amount2&lt;/code&gt; and &lt;code&gt;amount3&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Format currency with always 2 decimals
&lt;/h2&gt;

&lt;p&gt;Bear the above example in mind, we can also set up the formatter which always displaying 2 decimals (or any number of decimals you want) for currency values:&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;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NumberFormatter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimumFractionDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maximumFractionDigits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;123456.789&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;formattedAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&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;formattedAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Output: "$123,456.79"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;For more details: &lt;a href="https://needone.app/format-currency-in-swift/" rel="noopener noreferrer"&gt;https://needone.app/format-currency-in-swift/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nginx</category>
      <category>backenddevelopment</category>
      <category>debugging</category>
    </item>
  </channel>
</rss>
