Jekyll2023-01-10T19:34:21+00:00https://albinek.com/feed.xmlalbinek.comMostly thoughts about IT stuff. Short answers for sophisticated questions.Albin "albinek" Sadowskialbinek@albinek.comStart learning SwiftUI 🦆2019-07-01T16:00:00+00:002019-07-01T16:00:00+00:00https://albinek.com/start-learning-swiftui<p><img src="/assets/img/post/start-learning-swiftui-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="swiftui">SwiftUI</h2>
<p>Apple presented <code class="language-plaintext highlighter-rouge">SwiftUI</code> at WWDC 2019.</p>
<blockquote>
<p>SwiftUI is an innovative, exceptionally simple way to build user interfaces across all Apple platforms with the power of Swift. Build user interfaces for any Apple device using just one set of tools and APIs.</p>
</blockquote>
<p>Source: <a href="https://developer.apple.com/xcode/swiftui/">Xcode - SwiftUI - Apple Developer</a></p>
<p>It is a new approach for coding user interface elements in applications. So… how we can start using it?</p>
<h2 id="needed-tools">Needed tools</h2>
<p>The most important thing is to download the latest beta version of <code class="language-plaintext highlighter-rouge">Xcode 11</code> which can be found on <a href="https://developer.apple.com/support/beta-software/">Using Apple Beta Software</a> website.</p>
<p>If you would like to code your project with live preview, you need to have installed <code class="language-plaintext highlighter-rouge">macOS Catalina</code> (which is in beta right now) on your computer… but there is a workaround described below to have a “look-and-feel” of live preview of coded view using still stable <code class="language-plaintext highlighter-rouge">macOS Mojave</code>.</p>
<p>In my opinion the biggest disadvantage of <code class="language-plaintext highlighter-rouge">SwiftUI</code> is to have an awareness that it works only on new version of operating systems (like <code class="language-plaintext highlighter-rouge">iOS 13, macOS Catalina, watchOS 6</code> etc.) so if you have a big production app with massive number of users, probably you will start using this framework in 2 years… 😱</p>
<h2 id="playground-as-a-sandbox">Playground as a sandbox</h2>
<p>Open installed <code class="language-plaintext highlighter-rouge">Xcode-beta 11</code>, choose <code class="language-plaintext highlighter-rouge">File -> New -> Playground</code> and replace the code with these lines:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">import</span> <span class="kt">PlaygroundSupport</span>
<span class="kd">import</span> <span class="kt">SwiftUI</span>
<span class="kd">struct</span> <span class="kt">ContentView</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
<span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
<span class="kt">Text</span><span class="p">(</span><span class="s">"Hello, SwiftUI!"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">PlaygroundPage</span><span class="o">.</span><span class="n">current</span><span class="o">.</span><span class="n">liveView</span> <span class="o">=</span> <span class="kt">UIHostingController</span><span class="p">(</span><span class="nv">rootView</span><span class="p">:</span> <span class="kt">ContentView</span><span class="p">())</span>
</code></pre></div></div>
<p>Make any change in computed property <code class="language-plaintext highlighter-rouge">body</code> and admire “quickly refreshed” the results on the screen.</p>
<p><img src="/assets/img/post/start-learning-swiftui-1.png" alt="SwiftUI in Xcode Playground" /></p>
<h2 id="learning-resources">Learning resources</h2>
<p>Despite the fact it is still in the beta phase, there are some places where you can gain more knowledge and try examples:</p>
<ul>
<li><a href="https://developer.apple.com/videos/wwdc2019/?q=swiftui">SwiftUI videos at WWDC 2019</a></li>
<li><a href="https://developer.apple.com/tutorials/swiftui/">SwiftUI Tutorials - Apple Developer Documentation</a></li>
<li>Tutorials from other bloggers like <a href="https://www.hackingwithswift.com/quick-start/swiftui">SwiftUI by example</a></li>
</ul>
<p>And many many more, just use your favorite search engine to find.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Remember that <code class="language-plaintext highlighter-rouge">SwiftUI</code> is a new approach which is still in beta phase</li>
<li>Install <code class="language-plaintext highlighter-rouge">Xcode-beta 11</code> next to your stable version and play with it</li>
<li>Use a playground for fast prototyping until you have <code class="language-plaintext highlighter-rouge">macOS Catalina</code> installed on your computer</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comPaper wallet 💵2019-05-20T18:00:00+00:002019-05-20T18:00:00+00:00https://albinek.com/paper-wallet<p><img src="/assets/img/post/paper-wallet-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="give-me-my-money">Give me my money</h2>
<p>Today’s topic is something different. I heard that many people are investing in some stocks, jewelry collections or cryptocurrencies. When I looked closer at the last mentioned approach I noticed that people are buying some small amount of crypto and store them on crypto exchange. Exchange services work properly so there is no problem. But what happened when this crypto exchange will be closed one day? Or what will you do when there is a maintenance break at the moment when you need some of your coins?</p>
<h2 id="if-you-dont-own-your-private-keys-you-dont-own-the-coins">“If you don’t own your private keys, you don’t own the coins”</h2>
<p>If you have something on a crypto exchange, it means that in the exchange’s internal database particular value is assigned to your account (mostly your e-mail address). When you want to withdraw something you make a disposition to the crypto exchange and after a while they send proper value from their “real crypto account” and change the balance on your account. This is the reason why it is not so fast and a transaction fee of this operation is more expensive than typical transferring between crypto accounts (an exchange also takes some extra fee).</p>
<p>If something wrong happens like some “improvements” in the database, changes in the policy of the exchange or other stuff - it will be your problem. Anyone remembers <a href="https://en.wikipedia.org/wiki/Mt._Gox">Mt.Gox</a>?</p>
<h2 id="public-key-and-private-key">Public key and private key</h2>
<p>Most cryptocurrencies wallets contains two values: public key and private key. You can think about them using this analogy:</p>
<ul>
<li>public key - your account number</li>
<li>private key - your password</li>
</ul>
<p>The “key” is to share your public key among your friends and gather as many coins as you can on your account and do not share a private key with anyone. 😉</p>
<h2 id="paper-wallet">Paper wallet</h2>
<p>To generate these pairs you can use a lot of stuff like a special application on your computer, an application on your mobile device, web wallets, hardware wallets etc. but I think that the fastest and easier way is to use paper wallet.</p>
<p><code class="language-plaintext highlighter-rouge">Paper wallet</code> is just your public and private key written on the paper. There are many websites to generate them. You can print generated values, save them in your hidden and encrypted directory or even try to know by heart. 😉 It is a free of charge solution and everyone can do it right now.</p>
<h2 id="generating-a-paper-wallet">Generating a paper wallet</h2>
<h3 id="the-fastest-way">The fastest way:</h3>
<ol>
<li>Search for the phrase <code class="language-plaintext highlighter-rouge">paper wallet generator [cryptocurrency]</code> (change <code class="language-plaintext highlighter-rouge">[cryptocurrency]</code> with your desired cryptocurrency like <code class="language-plaintext highlighter-rouge">Bitcoin</code>) on the web</li>
<li>Open the website</li>
<li>Check the opinions about this website</li>
<li>Generate a pair using this website and store it</li>
</ol>
<h3 id="the-quite-secure-steps-are-particular">The “quite secure” steps are particular:</h3>
<ol>
<li>Search for the phrase <code class="language-plaintext highlighter-rouge">paper wallet generator [cryptocurrency]</code> (change <code class="language-plaintext highlighter-rouge">[cryptocurrency]</code> with your desired cryptocurrency like <code class="language-plaintext highlighter-rouge">Bitcoin</code>) on the web</li>
<li>Check the opinions about this website</li>
<li>Check if it contains github repository</li>
<li>Open this repository, read the whole code, understand it and download the codebase</li>
<li>Copy the codebase to the brand new computer which is off-line all the time</li>
<li>Open the downloaded codebase, generate a pair and store it</li>
</ol>
<p>If you are not a “security freak”, the “best effort approach” is in the middle (running the website locally on your computer).</p>
<p>The example of paper wallet for <code class="language-plaintext highlighter-rouge">Bitcoin</code> could be <a href="https://www.bitaddress.org/">bitaddress.org</a>. Open the website, move your mouse around to add some extra randomness or type some random characters into this textbox and see the results.</p>
<p><img src="/assets/img/post/paper-wallet-1.png" alt="Using bitaddress.org to generate paper wallet" /></p>
<h2 id="better-solutions">Better solutions</h2>
<p>It could be easy to forget about the proper sequence of characters in your private key. Moreover you have only this one particular address for every transactions (although for many people it could be an advantage, “one to rule them all”). More flaws are listed on <a href="https://en.bitcoin.it/wiki/Paper_wallet">en.bitcoin.it/wiki/Paper_wallet</a>.</p>
<p><code class="language-plaintext highlighter-rouge">Seed phrase</code> approach is recommended right now and in the future I will try to write something about it.</p>
<p>If you would like you to trade coins stored on your paper wallet - yes, you need to transfer your coins to the crypto exchange back again. The solution is using decentralized crypto exchanges where you have your keys stored locally on your device, but they are not popular nowadays.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Try not to store a large amount of your coins on crypto exchanges.</li>
<li>Securely storing a private key by you makes sure that you are the owner of your coins.</li>
<li>Start with generating paper wallets. Look for other solutions if this option is not suitable for you.</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comGoing dark (Web Edition) 🌙2019-04-08T17:00:00+00:002019-04-08T17:00:00+00:00https://albinek.com/going-dark-web-edition<p><img src="/assets/img/post/going-dark-web-edition-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="the-darkness-is-coming">The darkness is coming</h2>
<p>There is a new trend - making stuff dark. In the past you have to decide the style of your website (light or dark) or you have to add custom settings for the user and store that preference somehow.</p>
<p><code class="language-plaintext highlighter-rouge">Safari 12.1</code> (which is part of <code class="language-plaintext highlighter-rouge">macOS 10.14.4</code>) adds support for detecting a color theme. It can pass this information and specific version of the website can be rendered. When your system uses <code class="language-plaintext highlighter-rouge">Dark Mode</code> (<code class="language-plaintext highlighter-rouge">System Preferences -> General -> Appearance -> Dark</code>), Safari automatically has dark UI and tries to render a website using <code class="language-plaintext highlighter-rouge">dark theme</code> if it possible. Your website’s CSS file needs some tweaks to be dark-ready.</p>
<h2 id="simple-website">Simple website</h2>
<p>Let’s create a very basic website by using two files: <code class="language-plaintext highlighter-rouge">index.html</code> and <code class="language-plaintext highlighter-rouge">main.css</code>. The first file contains standard <code class="language-plaintext highlighter-rouge">HTML5</code> template with a one header and a one paragraph, the second file contains values for styling.</p>
<p>The content of <code class="language-plaintext highlighter-rouge">index.html</code> file:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1.0"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"main.css"</span><span class="nt">></span>
<span class="nt"><title></span>Dark Website Example<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Website Title<span class="nt"></h1></span>
<span class="nt"><p></span>Some random words.<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>The content of <code class="language-plaintext highlighter-rouge">main.css</code> file:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The result of these code:</p>
<p><img src="/assets/img/post/going-dark-web-edition-1.png" alt="Simple website with default style" /></p>
<p>Plain white website despite the fact that <code class="language-plaintext highlighter-rouge">Dark Mode</code> is enabled in the system (look at the dark toolbar at the top of the browser).</p>
<h2 id="adding-support-for-dark-mode">Adding support for Dark Mode</h2>
<p>To enable using dark content on the website, <code class="language-plaintext highlighter-rouge">prefers-color-scheme</code> media query needs to be used. Just add it and override the proper values.</p>
<p>The improved content of <code class="language-plaintext highlighter-rouge">main.css</code> file:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="p">(</span><span class="n">prefers-color-scheme</span><span class="p">:</span> <span class="n">dark</span><span class="p">)</span> <span class="p">{</span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>It checks if the dark mode (color scheme) is enabled and renders proper colors according to it. The result of these changes:</p>
<p><img src="/assets/img/post/going-dark-web-edition-2.png" alt="Simple website with enabled dark mode" /></p>
<p>You can take a look at this website here: <a href="https://albinek.com/DarkWebsiteExample/">Dark Website Example</a>.</p>
<p>The example code used in this post can be found here: <a href="https://github.com/albinekcom/DarkWebsiteExample">Dark Website Example on GitHub</a>.</p>
<h2 id="is-it-the-future">Is it the future?</h2>
<p>Dark style is trendy right now and I think it could be the future (better browsing at night, more content-focused and lower battery consumption by the device). You don’t need some custom things like remember the user preferecnes etc., just use this media query and that’s all! Looking forward to supporting this funciton in the other browsers (Firefox 67 already did it), better adoptation on the websites and more users with enabled <code class="language-plaintext highlighter-rouge">Dark Mode</code> by default.</p>
<p>Maybe changing the colors will not be enough (the icons could need some tweaks too) so ask your local UI/UX expert about it. 😉</p>
<p>Read <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme">prefers-color-scheme - CSS: Cascading Style Sheets</a> about the browser compatibility and more parameters.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Use <code class="language-plaintext highlighter-rouge">prefers-color-scheme</code> media query in CSS file and override values for another theme.</li>
<li>Try to design your website to be not hardcoded (or even hardcolored?) with only one style. Be polite to dark lovers. 🌙</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comMeasuring compile time 📐2019-03-25T15:00:00+00:002019-03-25T15:00:00+00:00https://albinek.com/measuring-compile-time<p><img src="/assets/img/post/measuring-compile-time-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="building">Building…</h2>
<p>More features, more code, longer compile time. Probably you heard about some tips and tricks how to improve it. Do you think that this code improvement makes your compilation faster? It is a good idea to have a specific determinant before doing it. The best approach will be measuring the compile time before particular improvement and measure it after that.</p>
<h2 id="using-report-navigator">Using Report navigator</h2>
<p>The simplest way is to open <code class="language-plaintext highlighter-rouge">Report navigator</code> in Xcode (<code class="language-plaintext highlighter-rouge">⌘+9</code> shortcut key), select a particular build and look at the time next to <code class="language-plaintext highlighter-rouge">Compile Swift source files</code> phase.</p>
<p><img src="/assets/img/post/measuring-compile-time-1.png" alt="Compile time in Report navigator" /></p>
<h2 id="using-a-script">Using a script</h2>
<p>Another idea is using a script. Gather the time before building and after it, calculate the difference and voilà! Now you know what is your compile time.</p>
<p>Add this <code class="language-plaintext highlighter-rouge">Script Phase</code> before <code class="language-plaintext highlighter-rouge">Compile Sources</code> phase:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">date_now_in_miliseconds</span><span class="o">=</span><span class="si">$(</span>python <span class="nt">-c</span> <span class="s1">'from time import time; print int(round(time() * 1000))'</span><span class="si">)</span>
<span class="nb">echo</span> <span class="nv">$date_now_in_miliseconds</span> <span class="o">></span> <span class="s2">"measured_compile_time.log"</span>
</code></pre></div></div>
<p>Add this <code class="language-plaintext highlighter-rouge">Script Phase</code> after <code class="language-plaintext highlighter-rouge">Compile Sources</code> phase:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">start_time_in_miliseconds</span><span class="o">=</span><span class="si">$(</span><measured_compile_time.log<span class="si">)</span>
<span class="nv">finish_time_in_miliseconds</span><span class="o">=</span><span class="si">$(</span>python <span class="nt">-c</span> <span class="s1">'from time import time; print int(round(time() * 1000))'</span><span class="si">)</span>
<span class="nv">difference</span><span class="o">=</span><span class="k">$((</span><span class="nv">$finish_time_in_miliseconds</span><span class="o">-</span><span class="nv">$start_time_in_miliseconds</span><span class="k">))</span>
<span class="nb">echo</span> <span class="s2">"[Difference] </span><span class="nv">$difference</span><span class="s2"> [ms]"</span> <span class="o">></span> <span class="s2">"measured_compile_time.log"</span>
</code></pre></div></div>
<p><img src="/assets/img/post/measuring-compile-time-2.png" alt="Adding script phases in Build Phases" /></p>
<p><code class="language-plaintext highlighter-rouge">python -c 'from time import time; print int(round(time() * 1000))'</code> is used to get a value in miliseconds (you can use also simple <code class="language-plaintext highlighter-rouge">date +%s</code> to receive that value in seconds).</p>
<p>From that moment you can check your compile time just by looking at the value in <code class="language-plaintext highlighter-rouge">compile_time.log</code> file. Remember about adding this <code class="language-plaintext highlighter-rouge">measured_compile_time.log</code> to <code class="language-plaintext highlighter-rouge">.gitignore</code> in your project. Thanks to it you can easily measure different places (or more phases at once) or even store these values and use it in other places (for example: in charts).</p>
<h2 id="using-a-tool">Using a tool</h2>
<p>More robust approach is using <a href="https://github.com/RobertGummesson/BuildTimeAnalyzer-for-Xcode">Build Time Analyzer for Xcode</a>. You can look at the compile time of a specific class (or even the particular method) using GUI.</p>
<p>Follow the steps included in the <code class="language-plaintext highlighter-rouge">README.md</code> to use this tool (mostly it is about adding <code class="language-plaintext highlighter-rouge">OTHER_SWIFT_FLAGS = "-Xfrontend -debug-time-function-bodies"</code> in <code class="language-plaintext highlighter-rouge">.pbxproj</code> file). After that you can visually notice which particular method has the longest compile time. Now you know which places need more love from your side.</p>
<p><img src="/assets/img/post/measuring-compile-time-3.png" alt="Example of usage "Build Time Analyzer for Xcode" tool" /></p>
<p>The example used in this post can be found here: <a href="https://github.com/albinekcom/MeasuringCompileTimeExample">Measuring Compile Time Example</a>.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Before doing any improvement - measure the impact!</li>
<li>Use a <code class="language-plaintext highlighter-rouge">Report navigator</code> / simple script / Build Time Analyzer to measure compile time.</li>
<li>After measuring the compile time, improve the code / enviroment and measure it once again. Now you can be sure what kind of impact has the implemented change.</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comCI in the cloud ☁️2018-12-22T13:00:00+00:002018-12-22T13:00:00+00:00https://albinek.com/ci-in-the-cloud<p><img src="/assets/img/post/ci-in-the-cloud-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="build-test-push-sleep-repeat">Build, test, push, sleep, repeat</h2>
<p>Do you remember a situation when you want to check an example on GitHub and it doesn’t want to compile? Do you recall a situation when you change something in your codebase and push the code without checking it? Or maybe little renaming after implementing the feature, pushing the code and forgot about improving names in unit tests? These situations can be avoided by building the code, checking tests etc. every time by yourself.</p>
<p>So if there is something which is repeatable and can be automated - why not to improve it?</p>
<h2 id="continuous-integration">Continuous integration</h2>
<p>There is a solution for that which is called <a href="https://en.wikipedia.org/wiki/Continuous_integration">continuous integration (CI)</a>. Basically it makes sure that your codebase integrates properly without checking it all the time by yourself. Obviously you can do it manually but this is a common challenge - so using a ready solution will be a good option.</p>
<h2 id="some-solutions">Some solutions</h2>
<p>After typing the phrase <code class="language-plaintext highlighter-rouge">continuous integration tools</code> in Google search this list appears:</p>
<ul>
<li>Jenkins</li>
<li>TeamCity</li>
<li>Travis CI</li>
<li>Go CD</li>
<li>Bamboo</li>
<li>GitLab CI</li>
<li>CircleCI</li>
<li>Codeship</li>
<li>Bitrise</li>
</ul>
<p>These are just a couple of them. Some are working locally, some of them only in the cloud, some have specific features like level of parallelization, mobile-only etc. Which one use at the beginning? Of course the easiest and the most popular one.</p>
<h2 id="travis-ci">Travis CI</h2>
<p><a href="https://travis-ci.org">Travis CI</a> is free for open source projects so it is a perfect solution for making yourself familiar with CI paradigm. (BTW. They don’t pay me for that phrase. 😉)</p>
<p>Steps to use it:</p>
<ol>
<li>Sing in with your <code class="language-plaintext highlighter-rouge">GitHub</code> account</li>
<li>Create an empty <code class="language-plaintext highlighter-rouge">.travis.yml</code> file in your project and fill it with some rules (some examples are written below)</li>
<li>Connect your project with <code class="language-plaintext highlighter-rouge">Travis CI</code></li>
</ol>
<p>That’s it! Every change in a repository should execute commands located in <code class="language-plaintext highlighter-rouge">.travis.yml</code> by default on Travis CI (you can change it in the settings).</p>
<h2 id="connecting-travis-ci-to-your-ios-project">Connecting Travis CI to your iOS project</h2>
<p>A repository with this example can be found on GitHub: <a href="https://github.com/albinekcom/Travis-CI-With-iOS-Project">Travis CI With iOS Project</a>.</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">os</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">osx</span>
<span class="na">osx_image</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">xcode10.1</span>
<span class="na">script</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">xcodebuild test -project Travis-CI-With-iOS-Project.xcodeproj -scheme Travis-CI-With-iOS-Project -destination "platform=iOS Simulator,name=iPhone XS"</span>
</code></pre></div></div>
<p>Yes, this file contains only 3 keys and 3 values.</p>
<ol>
<li>A value for key <code class="language-plaintext highlighter-rouge">os</code> is <code class="language-plaintext highlighter-rouge">osx</code>. Nowadays it should be <code class="language-plaintext highlighter-rouge">macos</code>, probably it will be changed in the near future.</li>
<li>A value for key <code class="language-plaintext highlighter-rouge">osx_image</code> is <code class="language-plaintext highlighter-rouge">xcode10.1</code>. This is the version of used Xcode in this process.</li>
<li>A value for key <code class="language-plaintext highlighter-rouge">script</code> is the command which is used for the building. It is used <code class="language-plaintext highlighter-rouge">xcodebuild test</code> with proper values for this project and a simulator variant. Building is done implicitly before testing (<code class="language-plaintext highlighter-rouge">xcodebuild test</code> does it automatically).</li>
</ol>
<p>And that’s it. Enable your project in <code class="language-plaintext highlighter-rouge">Travis CI</code> and from this moment you have working CI.</p>
<p><img src="/assets/img/post/ci-in-the-cloud-1.png" alt="Adding a project to Travis CI" /></p>
<h2 id="connecting-travis-ci-to-your-swift-project">Connecting Travis CI to your Swift project</h2>
<p>A repository with this example can be found on GitHub: <a href="https://github.com/albinekcom/Travis-CI-With-Swift-Project">Travis CI With Swift Project</a>.</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">os</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">osx</span>
<span class="na">osx_image</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">xcode10.1</span>
<span class="na">script</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">swift test --parallel</span>
</code></pre></div></div>
<p>The first 2 parameters are the same like in the previous example. The only difference is a script command. It can be done with simple <code class="language-plaintext highlighter-rouge">swift test</code> but when you add a parameter <code class="language-plaintext highlighter-rouge">--parallel</code>, unit tests are executed faster (in a parallel manner). You can but you do not need to add <code class="language-plaintext highlighter-rouge">swift build</code> before, because a command <code class="language-plaintext highlighter-rouge">swift test</code> does it under the hood before testing.</p>
<h2 id="next-steps">Next steps</h2>
<p>I think the idea of adding a badge in a <code class="language-plaintext highlighter-rouge">README.md</code> file is quite welcome because you and other people can easily check a state of your project / library. You can do it by pressing the badge image, choose <code class="language-plaintext highlighter-rouge">Markdown</code> style, copy the content and paste in your <code class="language-plaintext highlighter-rouge">README.md</code> file.</p>
<p><img src="/assets/img/post/ci-in-the-cloud-2.png" alt="Adding a badge to README file" /></p>
<p>Furthermore, you can also test your project on other operating systems (if it possible). You need to change things only in one file - <code class="language-plaintext highlighter-rouge">.travis.yml</code>. Try to add CI to your other projects even with different languages (solutions can be found mostly by using phrase “travis ci [your_project_language]”).</p>
<p>Can’t find a specific feature in Travis CI? Check other tools! 😉</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Adding CI to your project makes easier for you to notice earlier if something is wrong with building or testing.</li>
<li>When you use cloud solutions you do not need to take care about the hardware.</li>
<li>Using free continuous integration in the cloud helps your embedding simple CI in your project.</li>
<li>Informing a user about a build status of your project / library is a cute practice. 👍</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comMaking tools up-to-date ⚒2018-11-12T15:00:00+00:002018-11-12T15:00:00+00:00https://albinek.com/making-tools-up-to-date<p><img src="/assets/img/post/making-tools-up-to-date-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="there-is-a-new-update">“There is a new update”</h2>
<p>Mostly new features and bug fixes are delivered with the new version of the installed applications. Checking every 5-minutes the application’s website is not the most efficient approach. How to do it in a better way?</p>
<h2 id="checking-update-automatically">Checking “Update automatically”</h2>
<p>First of all check if your application contains something like “automatic updates” in the settings. Nowadays it is an industry standard for the modern apps. If your application is downloaded via <code class="language-plaintext highlighter-rouge">App Store</code>, make sure that in the preferences the <code class="language-plaintext highlighter-rouge">Automatic Updates</code> option is marked.</p>
<h2 id="updating-tools---a-classic-way">Updating tools - a classic way</h2>
<p>Not all the apps and tools you are using contains GUI. Moreover, sometimes you would like to update something without opening every app. How can this be achieved? Using special commands in terminal! For example: when you install app via <code class="language-plaintext highlighter-rouge">brew</code> there is a command like:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>brew update
<span class="nv">$ </span>brew upgrade
</code></pre></div></div>
<p>For the <code class="language-plaintext highlighter-rouge">Ruby</code> scripts installed via <code class="language-plaintext highlighter-rouge">gem</code>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gem update <span class="nt">--system</span>
<span class="nv">$ </span>gem update
</code></pre></div></div>
<p>Command <code class="language-plaintext highlighter-rouge">gem update --system</code> updates the <code class="language-plaintext highlighter-rouge">gem</code> itself. (if there is a new version)</p>
<p>You can update even <code class="language-plaintext highlighter-rouge">macOS</code> using:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>softwareupdate <span class="nt">--install</span> <span class="nt">--all</span>
</code></pre></div></div>
<p>Probably you notice that these commands are different for each manager / tool. Some commands are changed in the future. There are also things like <code class="language-plaintext highlighter-rouge">npm</code>, <code class="language-plaintext highlighter-rouge">apm</code>, <code class="language-plaintext highlighter-rouge">mas</code> etc. How to handle all of them?</p>
<h2 id="updating-all-tools---a-better-way">Updating all tools - a better way</h2>
<p>The best way is to gather all of the commands, write them into one file and run it. You can use my small tool which aggregates most of them. I called its <a href="https://github.com/albinekcom/updater-for-macos">Updater for macOS</a>. Every updater is in a separate file, the main script <code class="language-plaintext highlighter-rouge">updater_for_macos.sh</code> takes a tool name as an argument and execute all the code included in a particular file. So when you use it in that way:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./updater_for_macos.sh <span class="nt">--macos</span> <span class="nt">--brew</span>
</code></pre></div></div>
<p>It looks for these two files (<code class="language-plaintext highlighter-rouge">macos.sh</code> and <code class="language-plaintext highlighter-rouge">brew.sh</code>) and invoke the code in them. If you want to add something more which is not included here right now, you can fork this repository, add a a new file in the <code class="language-plaintext highlighter-rouge">lib</code> directory and pass that name as an argument. It is just that easy. 😉</p>
<h2 id="updating-all-tools---an-automatic-way">Updating all tools - an automatic way</h2>
<p>“Automate everything what you can”. According to that mantra let’s run this script automatically. There are few ways to do it but for <code class="language-plaintext highlighter-rouge">macOS</code> I can recommend <a href="https://www.launchd.info"><code class="language-plaintext highlighter-rouge">launchd</code></a>.</p>
<p>To make it easy for everyone I have included a file <code class="language-plaintext highlighter-rouge">com.albinek.mac.updater_for_macos.plist</code> as an example. Download it, modify values like <code class="language-plaintext highlighter-rouge">PATH</code> (the path to your user’s directory) and <code class="language-plaintext highlighter-rouge">ProgramArguments</code> (path to your updater script and with the tools’ names you would like to have up-to-date). You can also change the time when this script will be invoked. Now you only need to move this file to <code class="language-plaintext highlighter-rouge">~/Library/LaunchAgents/</code> directory and load it using <code class="language-plaintext highlighter-rouge">launchctl</code> command.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>launchctl load com.albinek.mac.updater_for_macos.plist
</code></pre></div></div>
<p>Since that moment your updater is executed automatically and you do not need to take care about it anymore. 😉</p>
<h2 id="other-platforms">Other platforms?</h2>
<p>On Linux you can always use the manual way but probably you will need a file with updating <code class="language-plaintext highlighter-rouge">apt-get</code> to make most of your tools updated. <a href="https://en.wikipedia.org/wiki/Cron">cron</a> can be helpful in enabling automatic updating.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Make sure that <code class="language-plaintext highlighter-rouge">Automatic Updates</code> is enabled in your applications.</li>
<li>Use already implemented solutions like <a href="https://github.com/albinekcom/updater-for-macos">Updater for macOS</a> for making the tools on your computer up-to-date.</li>
<li>If something is repeatable and it needs to be done - automate it!</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comOptimizing raster images 👁👁2018-10-29T20:00:00+00:002018-10-29T20:00:00+00:00https://albinek.com/optimizing-raster-images<p><img src="/assets/img/post/optimizing-raster-images-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="show-me-your-nice_pictures">Show me your #nice_pictures</h2>
<p>In the previous blog post (<a href="optimizing-vector-graphics">Optimizing vector graphics 👁</a>) I described how in a easy way optimize vector images. Vectors are great but we are still surrounded by typical, classic images. <code class="language-plaintext highlighter-rouge">JPEG</code>, <code class="language-plaintext highlighter-rouge">PNG</code>, <code class="language-plaintext highlighter-rouge">GIF</code>… These files could be also improved (with smaller file size as an output). How you can do it? By using a proper tool!</p>
<h2 id="perfect-tool">Perfect tool?</h2>
<p>Simple optmizing raster images looks very similar to vector graphics. Use sophisticated tool and you are done. So it is time to find this Swiss Army knife. During browsing the Internet you can encounter stuff named like:</p>
<ul>
<li>pngquant</li>
<li>PNGGauntlet</li>
<li>jpegoptim</li>
<li>Gifsicle</li>
<li>OptiPNG</li>
<li>DeflOpt</li>
<li>PNGOut</li>
<li>PNGOptimizer</li>
<li>AdvPNG</li>
<li>(…)</li>
</ul>
<p>A lot of stuff. So what is the good solution? You can always use each one, try it with some special flags, compare the results and find an image with the fewest bytes at the end. Maybe there is a tool with already integrated other optimizers? 🤔</p>
<h2 id="optimizing-using-imageoptim">Optimizing using ImageOptim</h2>
<p><a href="https://imageoptim.com/mac">ImageOptim</a> is a macOS application. It contains some of the previously listed tools. The usage is quite simple: drag & drop the files and wait for the results.</p>
<p><img src="/assets/img/post/optimizing-raster-images-1.png" alt="ImageOptim" /></p>
<h2 id="optimizing-using-pinga-and-pingo">Optimizing using pinga and pingo</h2>
<p>I know, I know, not everyone uses macOS. So what about other platforms? On Windows I remember <code class="language-plaintext highlighter-rouge">PNGSlim</code> for <code class="language-plaintext highlighter-rouge">PNG</code> files. The development of that solution has been stopped but the author published 2 other tools: <a href="https://css-ig.net/pinga">pinga</a> and <a href="https://css-ig.net/pingo">pingo</a> (both are also for <code class="language-plaintext highlighter-rouge">JPG</code> files).</p>
<p><img src="/assets/img/post/optimizing-raster-images-2.png" alt="pinga" /></p>
<h2 id="examples">Examples</h2>
<h3 id="example-no-1">Example No. 1</h3>
<p>The first example will be the image which was used in the previous post but right now it is exported as a raster image. (after zooming in the edges of the image are not so sharp like in a vector one…)</p>
<p><img src="/assets/img/post/optimizing-raster-images-3.png" alt="Example No. 1" /></p>
<table>
<thead>
<tr>
<th>Original file size</th>
<th>ImageOptim</th>
<th>pinga</th>
<th>pingo</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">11081 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">5210 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">4973 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">3390 bytes</code></td>
</tr>
</tbody>
</table>
<p>Quite significant improvement, more than <code class="language-plaintext highlighter-rouge">50%</code>!</p>
<h3 id="example-no-2">Example No. 2</h3>
<p>The next example will be something from the web. Let’s open some specific website like the wrong address, for example: <a href="https://google.com/wrong_address">https://google.com/wrong_address</a>. Google logo appears. Let’s check what can we do with it.</p>
<p><img src="/assets/img/post/optimizing-raster-images-4.png" alt="Example No. 2" /></p>
<table>
<thead>
<tr>
<th>Original file size</th>
<th>ImageOptim</th>
<th>pinga</th>
<th>pingo</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">3170 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">3170 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">3137 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">2281 bytes</code></td>
</tr>
</tbody>
</table>
<p>So when you have already optimized image (using an old tool in the past), it can be still improved when you use different approach or newer version of the optimizer.</p>
<h2 id="other-tools">Other tools?</h2>
<p>Yes, there are a lot of other tools. You can use some other specific optimizing tool which are listed above (and find more and more), use cloud solution <a href="https://tinypng.com">TinyPNG</a> or even a ready API service like <a href="https://imageoptim.com/api/start">ImageOptim API</a>.</p>
<p>Choose the right one which fits your needs.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Optimized images in a lossless way are better than default, non-optimized version: the same quality and smaller size.</li>
<li>Tools with aggregated optimizers are doing good job for the common tasks.</li>
<li>Users and their Internet providers will thank you for faster downloading the content.</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comOptimizing vector graphics 👁2018-08-20T10:00:00+00:002018-08-20T10:00:00+00:00https://albinek.com/optimizing-vector-graphics<p><img src="/assets/img/post/optimizing-vector-graphics-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="vectors-vectors-everywhere">Vectors, vectors everywhere</h2>
<p>Modern websites contain a lot of cute images. Now it is popular to use vector graphics (they use lines, points, and polygons to represent an image) which are scalable without losing the quality, usually simple and designed in a flat manner. Steps are well-known: design a masterpiece, save as a vector image, upload and admire.</p>
<p>This is an example of the vector image. When you change the size of the image or zoom in/out - the image does not lose the quality. Pretty nice, huh?</p>
<p><img src="/assets/img/post/optimizing-vector-graphics-1.svg" alt="NASA Logo" /></p>
<p>Do you know that when can add one more operation between save and upload, you will decrease uploading time, you could upload more images on your hosting and improve user experience without the lose of the quality at all?</p>
<h2 id="what-is-optimising">What is optimising?</h2>
<p>A definition form the dictionary:</p>
<blockquote>
<p>optimization /ɒptɪmʌɪˈzeɪʃ(ə)n/ - the action of making the best or most effective use of a situation or resource</p>
</blockquote>
<p>In computer graphics it is mostly about reducing the size of the image by eliminating unnecessary image resources. The smaller image size is, the quicker is downloaded by the user’s device, your hosting is used less and the whole user experience is improved.</p>
<h2 id="svg---a-vector-image">SVG - a vector image</h2>
<p>Let’s create an image. For that purpose I will use <a href="https://www.designer.io">Gravit Designer</a> which is free and you can even use it in the browser.</p>
<p><img src="/assets/img/post/optimizing-vector-graphics-2.png" alt="Gravit Designer" /></p>
<p>One of the most popular vector images format is <a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics"><code class="language-plaintext highlighter-rouge">SVG</code></a> so export the image and save as a <code class="language-plaintext highlighter-rouge">SVG</code> file. The output file size is <code class="language-plaintext highlighter-rouge">729 bytes</code>.</p>
<p><img src="/assets/img/post/optimizing-vector-graphics-3.svg" alt="Default image" /></p>
<p><code class="language-plaintext highlighter-rouge">SVG</code> file is a <a href="https://en.wikipedia.org/wiki/XML"><code class="language-plaintext highlighter-rouge">XML</code></a> file, so you can easily edit it using normal text editor and change same values etc. “Beautified” code (with nice indents) of this image file looks like that:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" standalone="no"?></span>
<span class="c"><!-- Generator: Gravit.io --></span>
<span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">xmlns:xlink=</span><span class="s">"http://www.w3.org/1999/xlink"</span> <span class="na">style=</span><span class="s">"isolation:isolate"</span> <span class="na">viewBox=</span><span class="s">"0 0 560 315"</span> <span class="na">width=</span><span class="s">"560"</span> <span class="na">height=</span><span class="s">"315"</span><span class="nt">></span>
<span class="nt"><defs></span>
<span class="nt"><clipPath</span> <span class="na">id=</span><span class="s">"_clipPath_YegyOi5h4pIbcFU6rpeBjkWrMAei2if2"</span><span class="nt">><rect</span> <span class="na">width=</span><span class="s">"560"</span> <span class="na">height=</span><span class="s">"315"</span><span class="nt">/></clipPath></span>
<span class="nt"></defs></span>
<span class="nt"><g</span> <span class="na">clip-path=</span><span class="s">"url(#_clipPath_YegyOi5h4pIbcFU6rpeBjkWrMAei2if2)"</span><span class="nt">><rect</span> <span class="na">x=</span><span class="s">"172.395"</span> <span class="na">y=</span><span class="s">"92.546"</span> <span class="na">width=</span><span class="s">"149"</span> <span class="na">height=</span><span class="s">"151"</span> <span class="na">transform=</span><span class="s">"matrix(1,0,0,1,0,0)"</span> <span class="na">fill=</span><span class="s">"rgb(49,151,109)"</span><span class="nt">/><polygon</span> <span class="na">points=</span><span class="s">"368.395,96.546,387.605,261.454,235.185,195.637"</span> <span class="na">fill=</span><span class="s">"rgb(18,116,221)"</span><span class="nt">/><circle</span> <span class="na">vector-effect=</span><span class="s">"non-scaling-stroke"</span> <span class="na">cx=</span><span class="s">"311.3948822334847"</span> <span class="na">cy=</span><span class="s">"103.54551732809568"</span> <span class="na">r=</span><span class="s">"50"</span> <span class="na">fill=</span><span class="s">"rgb(217,28,28)"</span><span class="nt">/></g></span>
<span class="nt"></svg></span>
</code></pre></div></div>
<p>It is nice, file is small but can it be improved?</p>
<h2 id="optimising-svg-using-svgo-tool">Optimising SVG using SVGO tool</h2>
<p>One of the tool is <a href="https://github.com/svg/svgo">SVGO</a>. It needs <code class="language-plaintext highlighter-rouge">npm</code> which is included in <code class="language-plaintext highlighter-rouge">Node.js</code> so you need to install it before (<code class="language-plaintext highlighter-rouge">$ brew install node</code> for <code class="language-plaintext highlighter-rouge">macOS</code>). After that you can install SVGO using command <code class="language-plaintext highlighter-rouge">$ npm install -g svgo</code>. Now you can use it, let’s do it in a lazy way - with a default option:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>svgo image.svg
</code></pre></div></div>
<p><img src="/assets/img/post/optimizing-vector-graphics-4.svg" alt="Optimized image" /></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><svg</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/2000/svg"</span> <span class="na">style=</span><span class="s">"isolation:isolate"</span> <span class="na">width=</span><span class="s">"560"</span> <span class="na">height=</span><span class="s">"315"</span><span class="nt">><defs><clipPath</span> <span class="na">id=</span><span class="s">"a"</span><span class="nt">><path</span> <span class="na">d=</span><span class="s">"M0 0h560v315H0z"</span><span class="nt">/></clipPath></defs><g</span> <span class="na">clip-path=</span><span class="s">"url(#a)"</span><span class="nt">><path</span> <span class="na">fill=</span><span class="s">"#31976D"</span> <span class="na">d=</span><span class="s">"M172.395 92.546h149v151h-149z"</span><span class="nt">/><path</span> <span class="na">fill=</span><span class="s">"#1274DD"</span> <span class="na">d=</span><span class="s">"M368.395 96.546l19.21 164.908-152.42-65.817z"</span><span class="nt">/><circle</span> <span class="na">vector-effect=</span><span class="s">"non-scaling-stroke"</span> <span class="na">cx=</span><span class="s">"311.395"</span> <span class="na">cy=</span><span class="s">"103.546"</span> <span class="na">r=</span><span class="s">"50"</span> <span class="na">fill=</span><span class="s">"#D91C1C"</span><span class="nt">/></g></svg></span>
</code></pre></div></div>
<table>
<thead>
<tr>
<th>Size of the file</th>
<th>Size of the file after the optimization</th>
<th>Difference</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">729 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">411 bytes</code></td>
<td><code class="language-plaintext highlighter-rouge">-318 bytes</code></td>
</tr>
</tbody>
</table>
<p>The output of that command is the image with the size of <code class="language-plaintext highlighter-rouge">411 bytes</code> so we save <code class="language-plaintext highlighter-rouge">318 bytes</code>. Maybe it is not so much but when you think about the percentage it is about <code class="language-plaintext highlighter-rouge">44%</code>! Imagine that your whole asset of the images on the website is <code class="language-plaintext highlighter-rouge">10 megabytes</code>. It will be <code class="language-plaintext highlighter-rouge">5.6 megabytes</code>, the website can be downloaded by the user’s browser about <code class="language-plaintext highlighter-rouge">x2</code> faster! Or you can store <code class="language-plaintext highlighter-rouge">x2</code> more content on your website’s hosting without paying more for the extra storage. 😉</p>
<h2 id="optimizing-svg-using-other-tools">Optimizing SVG using other tools</h2>
<p>This is not the only solution. If you like something with the User Interface, there is the on-line tool called <a href="https://jakearchibald.github.io/svgomg/">SVGOMG</a>.</p>
<p><img src="/assets/img/post/optimizing-vector-graphics-5.png" alt="SVGOMG Website" /></p>
<p>You can adjust the parameters and see the live results. Feel free to find more tools but I recommend starting with something simple, verified and used by the community (which are described here).</p>
<h2 id="can-it-be-even-better">Can it be even better?</h2>
<p>Yes! First of all you need to think about simplifying your designed graphics, removing not needed elements, choosing the right file type for that image, reducing number of colors, using appropriate dimensions and more… And after that: optimize image. Moreover I described only one format: <code class="language-plaintext highlighter-rouge">SVG</code>. There are other tools for the different formats.</p>
<p>Writing about it is a perfect idea for the new blog post in the future. 🙂</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>Optimized graphics in lossless way are better than default, non-optimized version: the same quality and smaller size.</li>
<li>Start with something simple like just run one command <code class="language-plaintext highlighter-rouge">$ svgo image.svg</code>. This solution is good enough at the beginning.</li>
<li>Save your hosting space and quickly improve user experience in a easy way!</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comFrom debug to release 🚜2018-08-06T19:00:00+00:002018-08-06T19:00:00+00:00https://albinek.com/from-debug-to-release<p><img src="/assets/img/post/from-debug-to-release-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="debug-anyone">Debug anyone?</h2>
<p>In the previous blog post (<a href="map-method-vs-for-loop">Map vs for in vs forEach challenge in Swift ⚔️</a> and <a href="to-if-let-or-to-if-not-nil">To if let or to not nil? 💀</a>) I have tested some methods using unit tests and function <code class="language-plaintext highlighter-rouge">measure()</code> from <code class="language-plaintext highlighter-rouge">XCTest</code> framework. But are these results also legit for the production? Let’s take a look that <code class="language-plaintext highlighter-rouge">loop</code> challenge and test it using different building configurations.</p>
<h2 id="from-tests-to-the-code-in-debug-mode">From tests to the code in debug mode</h2>
<p>We can implement <code class="language-plaintext highlighter-rouge">measure()</code> method by ourself using code like that:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">measure</span><span class="p">(</span><span class="nv">attempts</span><span class="p">:</span> <span class="kt">Int</span><span class="p">,</span> <span class="nv">measuredClosure</span><span class="p">:</span> <span class="p">(()</span> <span class="o">-></span> <span class="p">()))</span> <span class="o">-></span> <span class="p">([</span><span class="kt">TimeInterval</span><span class="p">],</span> <span class="kt">TimeInterval</span><span class="p">)</span> <span class="p">{</span>
<span class="k">var</span> <span class="nv">durationsInSeconds</span> <span class="o">=</span> <span class="p">[</span><span class="kt">TimeInterval</span><span class="p">]()</span>
<span class="k">for</span> <span class="n">_</span> <span class="k">in</span> <span class="mi">1</span><span class="o">...</span><span class="n">attempts</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">startDate</span> <span class="o">=</span> <span class="kt">Date</span><span class="p">()</span>
<span class="nf">measuredClosure</span><span class="p">()</span>
<span class="n">durationsInSeconds</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="kt">Date</span><span class="p">()</span><span class="o">.</span><span class="nf">timeIntervalSince</span><span class="p">(</span><span class="n">startDate</span><span class="p">))</span>
<span class="p">}</span>
<span class="k">let</span> <span class="nv">averageInSeconds</span> <span class="o">=</span> <span class="n">durationsInSeconds</span><span class="o">.</span><span class="nf">reduce</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">+</span><span class="p">)</span> <span class="o">/</span> <span class="kt">Double</span><span class="p">(</span><span class="n">durationsInSeconds</span><span class="o">.</span><span class="n">count</span><span class="p">)</span>
<span class="nf">return</span> <span class="p">(</span><span class="n">durationsInSeconds</span><span class="p">,</span> <span class="n">averageInSeconds</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>It takes the number of attempts and code to measure, it returns the tuple which contains all the results and the average.</p>
<p>Let’s test <code class="language-plaintext highlighter-rouge">for in</code> approach:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">numbers</span> <span class="o">=</span> <span class="kt">Array</span><span class="p">(</span><span class="mi">1</span><span class="o">...</span><span class="n">arrayLength</span><span class="p">)</span>
<span class="k">let</span> <span class="p">(</span><span class="nv">_</span><span class="p">,</span> <span class="nv">averageEmptyForIn</span><span class="p">)</span> <span class="o">=</span> <span class="nf">measure</span><span class="p">(</span><span class="nv">attempts</span><span class="p">:</span> <span class="n">measureAttempts</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="n">_</span> <span class="k">in</span> <span class="n">numbers</span> <span class="p">{}</span>
<span class="p">}</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"averageEmptyForIn: </span><span class="se">\(</span><span class="n">averageEmptyForIn</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>
<p>Now it is time to compile it and run.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>swift build
<span class="nv">$ </span>.build/debug/Comparer
averageEmptyForIn: 1.48660808801651
</code></pre></div></div>
<p>OK. It works, we have the results now it is time to rest… but suddenly someone asks:</p>
<blockquote>
<p>“Have you checked it on production?”</p>
</blockquote>
<h2 id="from-the-code-in-debug-mode-to-release">From the code in debug mode to release</h2>
<p>Going from <code class="language-plaintext highlighter-rouge">debug</code> mode to <code class="language-plaintext highlighter-rouge">release</code> mode is simple by adding one more flag to the <code class="language-plaintext highlighter-rouge">swift build</code> command. It is time to build it and execute.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>swift build <span class="nt">--configuration</span> release
<span class="nv">$ </span>.build/release/Comparer
averageEmptyForIn: 0
</code></pre></div></div>
<p>What? <code class="language-plaintext highlighter-rouge">0</code>? What is going on?</p>
<h2 id="magic-in-the-release-mode">Magic in the release mode</h2>
<p>In the <code class="language-plaintext highlighter-rouge">release</code> mode, the compiler uses optimization mechanism and the final performance of the application should increased. The compilation time can be longer but the final results should be better than in the <code class="language-plaintext highlighter-rouge">debug</code> mode. The compiler noticed that this <code class="language-plaintext highlighter-rouge">for in loop</code> is empty, it is pointless to execute it at all so it skips it completely during building and the results is <code class="language-plaintext highlighter-rouge">0</code>.</p>
<p>To measure this kind of stuff we need to put something more robust between braces. I will use a new random mechanism <code class="language-plaintext highlighter-rouge">Int.random(in: 1...2)</code> included in <code class="language-plaintext highlighter-rouge">Swift 4.2</code>. It generates a random number from inserted range so the output should be the number <code class="language-plaintext highlighter-rouge">1</code> or <code class="language-plaintext highlighter-rouge">2</code>.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="p">(</span><span class="nv">_</span><span class="p">,</span> <span class="nv">averageForInSeconds</span><span class="p">)</span> <span class="o">=</span> <span class="nf">measure</span><span class="p">(</span><span class="nv">attempts</span><span class="p">:</span> <span class="n">measureAttempts</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="n">i</span> <span class="k">in</span> <span class="n">numbers</span> <span class="p">{</span>
<span class="n">_</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="kt">Int</span><span class="o">.</span><span class="nf">random</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="mi">1</span><span class="o">...</span><span class="mi">2</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Now this sentence can be added for every previous <code class="language-plaintext highlighter-rouge">loop</code> approaches, compiled using specific configuration and launched. The repository with the improved code can be found <a href="https://github.com/albinekcom/FromDebugToReleaseComparer">here</a>.</p>
<h2 id="test-environment">Test environment</h2>
<ul>
<li>Device: MacBook Pro (15-inch, 2015, 2.2GHz Intel Core i7, 16GB RAM)</li>
<li>OS: macOS High Sierra 10.13.6</li>
<li>Swift: 4.2 (Xcode 10 Beta 5)</li>
<li>Array length: 10,000,000</li>
</ul>
<h2 id="test-results">Test results</h2>
<h3 id="tests">Tests</h3>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Average duration</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">map()</code></td>
<td>5.215 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">for in</code></td>
<td>5.921 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">forEach()</code></td>
<td>6.083 sec</td>
</tr>
</tbody>
</table>
<h3 id="debug-mode">Debug mode</h3>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Average duration</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">map()</code></td>
<td>5.164 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">for in</code></td>
<td>5.908 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">forEach()</code></td>
<td>5.929 sec</td>
</tr>
</tbody>
</table>
<h3 id="release-mode">Release mode</h3>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Average duration</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">map()</code></td>
<td>2.189 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">for in</code></td>
<td>2.187 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">forEach()</code></td>
<td>2.180 sec</td>
</tr>
</tbody>
</table>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li>The performance of the code compiled in the <code class="language-plaintext highlighter-rouge">debug</code> mode and the results of executed <code class="language-plaintext highlighter-rouge">tests</code> are similar (both complied using the same configuration).</li>
<li>In the <code class="language-plaintext highlighter-rouge">release</code> mode there is no significant impact which <code class="language-plaintext highlighter-rouge">loop</code> approach is used. The results are quite the same.</li>
<li>Code compiled in the <code class="language-plaintext highlighter-rouge">release</code> mode is executed faster than in <code class="language-plaintext highlighter-rouge">debug</code> mode. It should be obvious but who knows, maybe there are some edge cases. 😉</li>
<li>Tests are complied in <code class="language-plaintext highlighter-rouge">debug</code> mode by default. The results of the tests can be used as indicator but the production performance could be different.</li>
</ul>Albin "albinek" Sadowskialbinek@albinek.comTo if let or to not nil? 💀2018-07-08T20:00:00+00:002018-07-08T20:00:00+00:00https://albinek.com/to-if-let-or-to-if-not-nil<p><img src="/assets/img/post/to-if-let-or-to-if-not-nil-0.png" alt="Cover" class="cover-img" /></p>
<h2 id="is-it-nil">Is it <code class="language-plaintext highlighter-rouge">nil</code>?</h2>
<p>You have a variable that can have a value or it can be equal <code class="language-plaintext highlighter-rouge">nil</code> (reference to nothing).</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="nv">someVariable</span><span class="p">:</span> <span class="kt">Int</span><span class="p">?</span> <span class="o">=</span> <span class="kc">nil</span>
<span class="c1">// (...)</span>
<span class="n">someVariable</span> <span class="o">=</span> <span class="mi">42</span>
<span class="c1">//(...)</span>
</code></pre></div></div>
<p>When you want to check if something is not empty you probably think of that instruction:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">someVariable</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
<span class="c1">// do something when someVariable is not nil</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In Swift there is something like optional unwrapping and this unwrapped value can be used:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="k">let</span> <span class="nv">unwrapped</span> <span class="o">=</span> <span class="n">someVariable</span> <span class="p">{</span>
<span class="c1">// do something with unwrapped variable</span>
<span class="p">}</span>
</code></pre></div></div>
<p>If you don’t need that value, you can use that instruction to check if something it not <code class="language-plaintext highlighter-rouge">nil</code>:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="k">let</span> <span class="nv">_</span> <span class="o">=</span> <span class="n">someVariable</span> <span class="p">{</span>
<span class="c1">// do something when someVariable is not nil</span>
<span class="p">}</span>
</code></pre></div></div>
<p>So now we have 2 instructions for the same thing. Which one shall we use? 🤔</p>
<h2 id="show-me-the-numbers">Show me the numbers</h2>
<p>The tests include one, quite large array.</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nv">arrayLength</span> <span class="o">=</span> <span class="mi">10_000_000</span>
<span class="k">var</span> <span class="nv">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="kt">Int</span><span class="p">]()</span>
<span class="k">for</span> <span class="n">index</span> <span class="k">in</span> <span class="mi">1</span><span class="o">...</span><span class="n">arrayLength</span> <span class="p">{</span>
<span class="n">numbers</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Each test method includes just iterating through that array using one of the previously mentioned approach. The winner is the method which will pass the test in the smallest amount of time.</p>
<p>For <code class="language-plaintext highlighter-rouge">if let</code> it is:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">testIfLet</span><span class="p">()</span> <span class="p">{</span>
<span class="n">measure</span> <span class="p">{</span>
<span class="k">for</span> <span class="n">_</span> <span class="k">in</span> <span class="mi">0</span><span class="o">..<</span><span class="k">self</span><span class="o">.</span><span class="n">attempts</span> <span class="p">{</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">_</span> <span class="o">=</span> <span class="k">self</span><span class="o">.</span><span class="n">value</span> <span class="p">{}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>For <code class="language-plaintext highlighter-rouge">if not nil</code> it is:</p>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">func</span> <span class="nf">testIfNotNil</span><span class="p">()</span> <span class="p">{</span>
<span class="n">measure</span> <span class="p">{</span>
<span class="k">for</span> <span class="n">_</span> <span class="k">in</span> <span class="mi">0</span><span class="o">..<</span><span class="k">self</span><span class="o">.</span><span class="n">attempts</span> <span class="p">{</span>
<span class="k">if</span> <span class="k">self</span><span class="o">.</span><span class="n">value</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The complete repository can be found <a href="https://github.com/albinekcom/NotNilChallenge">here</a>.</p>
<h2 id="test-environment">Test environment</h2>
<ul>
<li>Device: MacBook Pro (15-inch, 2017, 2.8GHz Intel Core i7, 16GB RAM)</li>
<li>OS: macOS High Sierra 10.13.3</li>
<li>Swift: 4.1.2</li>
<li>Array length: 10,000,000</li>
</ul>
<h2 id="test-results">Test results</h2>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Average duration</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">if let _ = someVariable</code></td>
<td>0.165 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">if someVariable != nil</code></td>
<td>0.184 sec</td>
</tr>
</tbody>
</table>
<p>For <code class="language-plaintext highlighter-rouge">Swift 4.1</code> <code class="language-plaintext highlighter-rouge">if let _ = someVariable</code> is about <strong>12%</strong> faster than <code class="language-plaintext highlighter-rouge">if someVariable != nil</code>.</p>
<h2 id="some-history">Some history</h2>
<p>Now we know what is the fastest but is it worth to take care about 12% better performance? When we look at the older versions, you can notice that for different version of Swift language there are different results.</p>
<h3 id="swift-31">Swift 3.1</h3>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Average duration</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">if let _ = someVariable</code></td>
<td>0.046 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">if someVariable != nil</code></td>
<td>0.754 sec</td>
</tr>
</tbody>
</table>
<p>For <code class="language-plaintext highlighter-rouge">Swift 3.1</code> <code class="language-plaintext highlighter-rouge">if let _ = someVariable</code> is about <strong>1539%</strong> faster than <code class="language-plaintext highlighter-rouge">if someVariable != nil</code>.</p>
<h3 id="swift-40">Swift 4.0</h3>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Average duration</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">if let _ = someVariable</code></td>
<td>0.193 sec</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">if someVariable != nil</code></td>
<td>0.887 sec</td>
</tr>
</tbody>
</table>
<p>For <code class="language-plaintext highlighter-rouge">Swift 4.0</code> <code class="language-plaintext highlighter-rouge">if let _ = someVariable</code> is about <strong>360%</strong> faster than <code class="language-plaintext highlighter-rouge">if someVariable != nil</code>.</p>
<h2 id="conclusions">Conclusions</h2>
<ul>
<li><code class="language-plaintext highlighter-rouge">if let _ = someVariable</code> has better performance.</li>
<li>The solution from the past could be not the best right now so be prepared for the changes.</li>
<li>The performance of the some of the instructions are different using various version of the language (changes in the compiler). So when you use something because it is faster than another instruction - make sure that you are 100% right and check it when you use the newest version of your programming language. 😉</li>
</ul>
<h2 id="epilog">Epilog</h2>
<p>These results are measured using method <code class="language-plaintext highlighter-rouge">measure()</code> included in <code class="language-plaintext highlighter-rouge">XCTest</code> framework during testing (which is in <code class="language-plaintext highlighter-rouge">Debug</code> mode by default). Is it the same performance on production when the final code is optimized by the compiler? Stay tuned for the next blog post. 😉</p>Albin "albinek" Sadowskialbinek@albinek.com