Jekyll2020-05-31T10:05:36+00:00https://balestrapatrick.github.io/feed.xmlPatrick BalestraiOS Engineer at <a href="http://spotify.com" target="_blank">Spotify</a>.<br>Conference organizer.<br>OSS contributor.Patrick BalestraBuilding a Custom Minimal HomeKit Lamp2020-05-31T00:00:00+00:002020-05-31T00:00:00+00:00https://balestrapatrick.github.io/blog/2020/05/31/building-a-custom-minimal-homekit-lamp<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/result.jpg" alt="" />
Building your own dream custom light may seem daunting and time-consuming at first, but it’s actually pretty easy. In this post I’ll walk you through building your own floor lamp controllable via HomeKit and Alexa using off-the-shelf products.
<!--more--></p>
<h2 id="the-why-and-what">The Why and What</h2>
<p>This cool-looking minimal lamp has been all over my Instagram and Facebook ads for the last couple of weeks, and it seems like I’m not the only one given my <a href="https://twitter.com/_patmurray/status/1265741078369452032">Twitter replies</a>.
<img src="/assets/blog/building-a-custom-minimal-homekit-lamp/ad.jpg" alt="" />
The Facebook ad has a lot of emoji, an all caps title, default Shopify domain and the original price was $199 but is now being sold at $99, how much can you trust it?
There are other similar lights that you can trust a bit more on the market, such as the <a href="https://www2.meethue.com/en-us/p/hue-white-and-color-ambiance-signe-floor-light/4080248U7">Philips Hue Signe floor light</a> which is $249, a bit too expensive for what it offers (single color and requires a Hue Bridge).</p>
<p>So I’ve decided to build my own. The goal was to keep the design very similar: a thin black structure and a multi zone LED strip lights attached to it that would project the beautiful colors on the wall. Of course HomeKit and Alexa controls were mandatory. It’s the perfect corner lamp for a living room.</p>
<p>I’m no expert in electronics, so I decided to go with product easily available to consumers. Therefore, this post should be pretty easy to follow and doesn’t require any particular tools or skills. I’ve used tools which you can easily find at your nearest home improvement shop.</p>
<h2 id="what-you-need">What You Need</h2>
<p>Here are the main parts that I’ve used:</p>
<ol>
<li>One aluminum squared pipe of length around 1 meter and 20mmx20mm thickness (<a href="https://www.bauhaus.se/ror-fyrkantigt-aluminium-20x20x1-5mm-2m-1">Rör Fyrkantigt Aluminium 20X20X1,5mm 1M</a> in Sweden). I ended up cutting this pipe to obtain two pipes of equal length. I wanted to find a pipe of size 15x15mm since that’s the width of the LED strip, but my local shop didn’t have it.</li>
<li>One angle profile aluminum bar of length 1 meter (<a href="https://www.bauhaus.se/vinkelprofil-aluminium-20x20x1-5mm-1m">Vinkelprofil Aluminium 20x20x1,5mm 1M</a>) that will be placed vertically and have the LED strip attached to it.</li>
<li>A 90º profile connector with three couplings (<a href="https://www.bauhaus.se/profilforbindare-90-plast-20x20x1-5mm-svart">Profilförbindare 90° Plast 20X20X1,5mm Svart</a>).</li>
<li>Super glue.</li>
<li>Black color spray (<a href="https://www.bauhaus.se/sprayfarg-halvblank-svart-400ml">Sprayfärg Halvblank Svart 400ML</a>).</li>
<li>LED strip that has multiple zones to allow assignment of different colors to different parts of the light. Most LED strips have a single color, but to give that cool effect in the picture you will probably need a more expensive light. It’s really up to you to decide which one to get. My apartment is completely on HomeKit/Alexa and it’s fully based on Philips Hue, but I choose to go with the <a href="https://eu.lifx.com/collections/light-strips/products/z-tv-led-strip">LIFX Z LED Strip 1m Kit (“Z TV”)</a>. Its primary use is to be attached on the back of the TV to provide ambient light, but its length is also perfect for this kind of project.</li>
</ol>
<p>The total cost of all the parts was around $100 in Stockholm, Sweden.</p>
<h2 id="putting-everything-together">Putting Everything Together</h2>
<p>The first part of the process consisted in cutting the long squared tube of alluminium into multiple pieces. I decided that my base should be 33cm per leg, so I cut the parts using the <a href="https://www.ikea.com/us/en/p/vidga-miter-box-white-50317412/">Vidga cutting box from IKEA</a> I had lying around and a cutting saw.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/cutting.jpg" alt="" /></p>
<p>I then assembled the pieces with the profile connector using a hammer to fit them securely.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/assembling.jpg" alt="" /></p>
<p>The top part was the most challenging. The initial idea was to go with the same square pipe which would fit perfectly in the profile connector, but I realized that I’d need to attach the LED strip on one side of the pipe, causing the light not to diffuse evenly on the wall.</p>
<p>Instead, by going with a angle profile and attaching the light on the border of one side, the light is more evenly distributed as you can see from this picture. It also depends on where you’re placing your light of course, but this should give you an idea of what to keep in mind.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/distribution.jpg" alt="" /></p>
<p>I decided to use super glue to attach the vertical bar to the bottom of the base. It worked well and it seems to be pretty sturdy.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/top-part.jpg" alt="" /></p>
<p>I then spray painted the structure in black and left it to dry for a couple of minutes. Make sure to follow the instructions of the spray paint you buy to avoid leaving visible stains or drops on the structure, for example by spraying too closely to the surface (been there, done that). Also, of course you should do the painting outside; this picture was taken after the fact.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/black.jpg" alt="" /></p>
<p>The structure is now complete!</p>
<p>Time to attach the LED strip. As mentioned before, try to evenly diffuse the light. I positioned the strip on the edge of one side of the angle profile bar. The strip has a pretty powerful sticker ready to be used, so this was easy.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/led.jpg" alt="" /></p>
<h2 id="the-tech-part">The Tech Part</h2>
<p>Downloading the <a href="https://apps.apple.com/us/app/lifx/id657758311">LIFX app</a> and setting it up in my HomeKit app was pretty straightforward. As most HomeKit accessories these days, you can pair them by just scanning the HomeKit QR code that comes with the product. My specific light directly connects to the home WiFi, no need for a hub. I was bit surprised when the app showed an error about “Unsupported router”. I have two WiFi connections, a 2.4 GHz and 5 GHz one. My iPhone was connected to the 5 GHz, which seems to be unsupported by the WiFi module of the light, so I had to switch to the 2.4 GHz to complete the configuration.</p>
<p>I was very surprised by the quality of the iOS LIFX app. It’s very well designed and has a ton of options to dynamically customize the colors and save them as scenes as you can see.</p>
<p><img src="/assets/blog/building-a-custom-minimal-homekit-lamp/demo.gif" alt="" /></p>
<p>The app comes with a few built-in color themes, but it doesn’t have animatable patterns that change color over time for example. I might look into if this is possible by building a <a href="https://homebridge.io">homebridge</a> plugin and scheduling constant updates via HomeKit. Let me know if you’ve tried this already!</p>
<p>I hope this post was useful and it’ll encourage you to try and build more stuff yourself! 🛠</p>
<p>If you end up building your own version, make sure to <a href="https://twitter.com/BalestraPatrick">tweet me</a> a picture of it!</p>
<p>Thanks to <a href="https://twitter.com/a2">Alex</a> for proofreading this post and to Majd for helping me in finding the right components to buy by translating them to Swedish.</p>Patrick BalestraBuilding your own dream custom light may seem daunting and time-consuming at first, but it’s actually pretty easy. In this post I’ll walk you through building your own floor lamp controllable via HomeKit and Alexa using off-the-shelf products.Xcode’s Find Navigator & Search Scopes2020-02-09T00:00:00+00:002020-02-09T00:00:00+00:00https://balestrapatrick.github.io/blog/2020/02/09/xcode-find-navigator<p><img src="/assets/blog/xcode-find-navigator/header.jpg" alt="" />
Xcode’s built-in search and replace function, present in the find navigator is severely underrated and unknown to many developers. It is very powerful and comes with various options that may look complex at first, but the nice and simple UI should help in getting started with it. Let’s take a quick look at what the Xcode’s find navigator has to offer.
<!--more--></p>
<p>This is how the find navigator presents itself in the 4th tab on the left sidebar of Xcode (you can also use the ⌘ + 4 or the more common ⌘ + ⇧ + F shortcuts).
<img src="/assets/blog/xcode-find-navigator/1.png" alt="" />
As you can see, there’s a lot going on in this simple view. At first you may only see a text field and that’s it, but there are actually 6 customizable interactive buttons in this view alone.
By pressing on “Find”, a popover with another option will appear. Instead of the standard search, you can switch to a more powerful “Find and Replace”.
<img src="/assets/blog/xcode-find-navigator/3.png" alt="" />
You can type the text that you’d like to find, and the text that you want to replace your match with. Using the “Replace” and “Replace All” buttons you’ll be able to replace all instances found or proceed more carefully by replacing instances one-by-one.
Surprisingly, also the text “Text” is a button and will show different options based on what type of search you’re currently in (Find or Replace).
<img src="/assets/blog/xcode-find-navigator/4.png" alt="" />
You can search for a simple string, for a symbol reference or definition (where a specific symbol is being used or defined), using a regex or searching the call hierarchy of a method, property or function.
<img src="/assets/blog/xcode-find-navigator/5.png" alt="" />
Depending on the second option selected, a third column may be available allowing you to make your search even more powerful.
<img src="/assets/blog/xcode-find-navigator/6.png" alt="" />
The magnifying glass on the left is kind of a miscellaneous button. Upon pressing, a recent history of your search terms will appear, along an interesting “Insert Pattern” feature which allows you to create a regex-like search term without having to write a regex from scratch.
<img src="/assets/blog/xcode-find-navigator/7.png" alt="" />
The feature I like the most is actually a simple find and replace combined with a regex. You can do complex refactors by using lookup groups like in the following example:
<img src="/assets/blog/xcode-find-navigator/10.png" alt="" />
You can refer to the matched group in the regex with <code class="language-plaintext highlighter-rouge">$1</code>, <code class="language-plaintext highlighter-rouge">$2</code> and apply any modification you would like. You can imagine how useful running regexes over your whole project could be when doing big refactors (pro tip: use <a href="https://regexr.com">regexr</a> to create and validate your regexes).</p>
<p>Pressing on “In Project” will reveal all available scopes that you can perform a search on.
You can create your own scopes pretty easily with the helpful UI that guides you through adding all filters needed. For example, I created multiple scopes to search the project by file type.
<img src="/assets/blog/xcode-find-navigator/8.png" alt="" />
These scopes actually persist across closing and reopening of Xcode, so now you may wonder where are these scopes actually stored?</p>
<p>The search scopes are stored in a file named <code class="language-plaintext highlighter-rouge">IDEFindNavigatorScopes.plist</code> . This file can be found either in <code class="language-plaintext highlighter-rouge">~/Library/Developer/Xcode/UserData/</code> or in the <code class="language-plaintext highlighter-rouge">xcuserdata</code> of your <code class="language-plaintext highlighter-rouge">workspace</code>, such as <code class="language-plaintext highlighter-rouge">FindNavigator.xcodeproj/project.xcworkspace/xcuserdata/patrickbalestra.xcuserdatad/</code>.</p>
<p>Knowing the location of the file, you can reverse engineer the format of this property list after creating a scope in Xcode. I wanted to automatically create a search scope for my repo that would search all files with a specific extension in a directory.
<img src="/assets/blog/xcode-find-navigator/9.png" alt="" />
After modifying the search scope in Xcode to look for “swift” files in my project root directory instead of my project, I opened <code class="language-plaintext highlighter-rouge">~/Library/Developer/Xcode/UserData/IDEFindNavigatorScopes.plist</code>.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="cp"><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"></span>
<span class="nt"><plist</span> <span class="na">version=</span><span class="s">"1.0"</span><span class="nt">></span>
<span class="nt"><array></span>
<span class="nt"><dict></span>
<span class="nt"><key></span>name<span class="nt"></key></span>
<span class="nt"><string></span>Swift<span class="nt"></string></span>
<span class="nt"><key></span>predicate<span class="nt"></key></span>
<span class="nt"><dict></span>
<span class="nt"><key></span>predicates<span class="nt"></key></span>
<span class="nt"><array></span>
<span class="nt"><dict></span>
<span class="nt"><key></span>operand<span class="nt"></key></span>
<span class="nt"><string></span>swift<span class="nt"></string></span>
<span class="nt"><key></span>operator<span class="nt"></key></span>
<span class="nt"><string></span>is-equal-to<span class="nt"></string></span>
<span class="nt"><key></span>rule<span class="nt"></key></span>
<span class="nt"><string></span>file-extension<span class="nt"></string></span>
<span class="nt"></dict></span>
<span class="nt"></array></span>
<span class="nt"><key></span>rule<span class="nt"></key></span>
<span class="nt"><string></span>all<span class="nt"></string></span>
<span class="nt"></dict></span>
<span class="nt"><key></span>source<span class="nt"></key></span>
<span class="nt"><dict></span>
<span class="nt"><key></span>base-path<span class="nt"></key></span>
<span class="nt"><string></span>/Users/patrickbalestra/FindNavigator/<span class="nt"></string></span>
<span class="nt"><key></span>file-source<span class="nt"></key></span>
<span class="nt"><string></span>directory<span class="nt"></string></span>
<span class="nt"></dict></span>
<span class="nt"></dict></span>
<span class="nt"></array></span>
<span class="nt"></plist></span>
</code></pre></div></div>
<p>As you can see, the plist file is just an array of dictionaries that specify what the search scopes look like. Each search scope has a <code class="language-plaintext highlighter-rouge">name</code> , a <code class="language-plaintext highlighter-rouge">predicate</code> dictionary that describes what to search for and a <code class="language-plaintext highlighter-rouge">source</code> dictionary that describes where to search. Now that you now the format, you can programmatically create your own custom search scopes and distribute them as part of the build tooling.</p>
<p>In big codebases for example, it may be useful to start distributing common search scopes to all developers to give a better and consistent experience when searching the project.</p>Patrick BalestraXcode’s built-in search and replace function, present in the find navigator is severely underrated and unknown to many developers. It is very powerful and comes with various options that may look complex at first, but the nice and simple UI should help in getting started with it. Let’s take a quick look at what the Xcode’s find navigator has to offer.WWDC 2019 - The Things You May Have Missed2019-06-07T00:00:00+00:002019-06-07T00:00:00+00:00https://balestrapatrick.github.io/blog/2019/06/07/wwdc-2019-the-things-you-may-have-missed<p><img src="/assets/blog/wwdc-2019-the-things-you-may-have-missed/header.jpg" alt="" />
WWDC 2019 was definitely the biggest event in the last few years. I was in the audience when Swift was announced in 2014, but I can say that this year is probably bigger than WWDC 2014. Given the many changes across frameworks, OSes, developers tools and web services that Apple offers, many interesting minor long-awaited improvements may have gone unnoticed. I tried to collect some of the announcements that may have been shadowed by the bigger announcements in a single and short post. Every item has an associated source or link where you can learn more about it.</p>
<p>I am planning to keep this list up to date over the next few weeks as a personal reference, so feel free to send me anything you discover. I hope you enjoy the list!
<!--more--></p>
<h2 id="new-frameworks">New Frameworks</h2>
<ul>
<li><code class="language-plaintext highlighter-rouge">PencilKit</code> is a new framework that allows capturing touch input as an opaque drawing and display that content from your app. <a href="https://developer.apple.com/documentation/pencilkit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">RealityKit</code> is a new framework that allows simulation and rendering of 3D content for use in your augmented reality apps. <a href="https://developer.apple.com/documentation/realitykit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">BackgroundTasks</code> is a new framework that can be used to request the system to launch your app in the background to run tasks. <a href="https://developer.apple.com/documentation/backgroundtasks">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">QuickLookThumbnailing</code> is a new framework that can be used to provide quick look thumbnails for custom file types provided by your app. <a href="https://developer.apple.com/documentation/quicklookthumbnailing">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">Combine</code> is a new framework for handling of asynchronous events by combining event-processing operators. <a href="https://developer.apple.com/documentation/combine">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">Core Audio Types</code> is a new framework that uses specialized data types to interact with audio streams, complex buffers, and audiovisual timestamps. <a href="https://developer.apple.com/documentation/coreaudiotypes">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">Core Haptics</code> is a new framework that allows composing and playing haptic patterns to customize your iOS app’s haptic feedback. <a href="https://developer.apple.com/documentation/corehaptics">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">SoundAnalysis</code> is a new framework that allows the analysis of streamed and file-based audio to classify it as a particular type. <a href="https://developer.apple.com/documentation/soundanalysis">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">VisionKit</code> is a new framework that allows developers to implement a camera scanning documents feature like the one available in the stock Notes app. <a href="https://developer.apple.com/documentation/visionkit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">Maps Web Snapshots</code> is a new web service that allows the creation of a static image of a map from a URL. <a href="https://developer.apple.com/documentation/snapshots">Apple Documentation</a>, <a href="https://twitter.com/vickimurley/status/1136775033123028992">@vickimurley</a></li>
<li><code class="language-plaintext highlighter-rouge">CryptoKit</code> is a new framework that performs cryptographic operations securely and efficiently. <a href="https://developer.apple.com/documentation/cryptokit">Apple Documentation</a>
<ul>
<li><code class="language-plaintext highlighter-rouge">MD5</code> and <code class="language-plaintext highlighter-rouge">SHA1</code> are classified as insecure and are only provided for backward compatibility services that require them. <a href="https://twitter.com/vixentael/status/1135676180605128704">@vixentael</a></li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">MetricKit</code> is a new framework that allows aggregation and analysis per-device reports on power and performance metrics. <a href="https://developer.apple.com/documentation/metrickit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">DriverKit</code> is a new framework that allows developing device drivers that run in user space. <a href="https://developer.apple.com/documentation/driverkit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">EndpointSecurity</code> is a new framework that allows developing system extensions that enhance user security. <a href="https://developer.apple.com/documentation/endpointsecurity">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">SystemExtensions</code> is a new framework that allows to install and manage user-space code that extends the capabilities of macOS. <a href="https://developer.apple.com/documentation/systemextensions">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">USBDriverKit</code> is a new framework that allows to develop drivers for USB-based devices. <a href="https://developer.apple.com/documentation/usbdriverkit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">USBSerialDriverKit</code> is a new framework that allows to develop drivers for serial IO devices connected to your Mac. <a href="https://developer.apple.com/documentation/usbserialdriverkit">Apple Documentation</a></li>
<li><code class="language-plaintext highlighter-rouge">HIDDriverKit</code> is a new framework that allows to develop drivers for devices that users interact with. <a href="https://developer.apple.com/documentation/hiddriverkit">Apple Documentation</a></li>
<li>There are some more new frameworks without documentation: <a href="https://developer.apple.com/documentation/linkpresentation">LinkPresentation</a>, <a href="https://developer.apple.com/documentation/iousbhost">IOUSBHost</a>, <a href="https://developer.apple.com/documentation/logging">Logging</a>, <a href="https://developer.apple.com/documentation/networkingdriverkit">NetworkingDriverKit</a>, <a href="https://developer.apple.com/documentation/executionpolicy">ExecutionPolicy</a> and <a href="https://developer.apple.com/documentation/wifi">WiFi</a>.</li>
</ul>
<h2 id="ios">iOS</h2>
<ul>
<li>The default presentation modal animation is a card-like design. Modals are dismissable interactively by default (which may break some apps), but you can set <code class="language-plaintext highlighter-rouge">isModalInPresentation</code> to false to disable this behavior. <a href="https://twitter.com/hansemannnn/status/1135667513960816642">@hansemannnn</a></li>
<li><code class="language-plaintext highlighter-rouge">UISegmentedControl</code> and <code class="language-plaintext highlighter-rouge">UIStepper</code> have an updated design. <a href="https://twitter.com/hansemannnn/status/1135667513960816642">@hansemannnn</a></li>
<li>Apps are to request “Always” access to the device location but users will see an alert when an app tries to access the location from the background that prompts them to “Always Allow” or to “Change to Only While Using”. Users are also presented with a map clearly showing that the app was tracking the location. In this way, users are not forced to take a decision upfront when installing the app for example. <a href="https://twitter.com/quicklywilliam/status/1135680571445669889">quicklywilliam</a></li>
<li>Apple sign-in is going to be mandatory for apps that support third-party sign-in when it is commercially available later this year (presumably after both macOS 10.15 Catalina and iOS 13 ship publicly). <a href="https://developer.apple.com/sign-in-with-apple/get-started/">Apple Documentation</a></li>
<li>Safari now has a download manager. Users can specify the destination in the Settings (even USB drives are supported!). <a href="https://twitter.com/stroughtonsmith/status/1135663919689797633">@stroughtonsmith</a></li>
<li>Starting next spring, it will be an App Store requirement for apps to adopt to different screen sizes (such as supporting Multitasking on the iPad). <a href="https://twitter.com/steipete/status/1135660558261186560">@steipete</a></li>
<li>The share sheet has been completely redesigned and seems to be smarted and have more context about what the user wants to do based on the content type it is presented with. <a href="https://twitter.com/Swanros/status/1135702658570842112">@Swanros</a></li>
<li><code class="language-plaintext highlighter-rouge">UIImage</code> has a new initializer, <code class="language-plaintext highlighter-rouge">UIImage(systemName:)</code> that takes a string and returns one of over 1500 different system icons. <a href="https://twitter.com/twostraws/status/1135639902337478656">@twostraws</a></li>
<li>The 3D Touch APIs such as peek & pop have been updated with a new <a href="https://developer.apple.com/documentation/uikit/menus_and_shortcuts"><code class="language-plaintext highlighter-rouge">UIContextMenuInteraction</code></a> API. This is in contrast with previous rumours about 3D Touch not being present on future iOS devices. <a href="https://twitter.com/bhansmeyer/status/1135719208296361991">@bhansmeyer</a></li>
<li>iOS 13 has some major updated APIs to manage and diff datasource. A new block-based APIs has also been added if you don’t like delegates. <a href="https://twitter.com/smileyborg/status/1135691034573168641">@smileyborg</a></li>
<li>A new “Low Data” mode has been added to avoid running out of data when you’re on a roaming plan for example. This feature is also available under Wi-Fi. <a href="https://twitter.com/daytonlowell/status/1135692976968077312">@daytonlowell</a></li>
<li>iOS 13 raises the limit of apps downloadable via cellular to 200 MB, but this limit can be removed by the user in the Settings. <a href="https://twitter.com/steipete/status/1135788297182015489">@steipete</a></li>
<li><code class="language-plaintext highlighter-rouge">UIViewController</code> subclasses can now be initialized from a Storyboard and be passed additional context and arguments (required for dependency injection). <a href="https://twitter.com/kharrison/status/1135641442658017281">@kharrison</a></li>
<li>Similar improvements have been made to <code class="language-plaintext highlighter-rouge">UIStoryboardSegue</code> with the new <code class="language-plaintext highlighter-rouge">@IBSegueAction</code> modifier. You can pass additional context and parameters directly to the next segue view controller that should be initialized. <a href="https://twitter.com/jnadeau/status/1136051762446520321">@jnadeau</a></li>
<li>Sharing photos on iOS 13 has the option to include the original info such as depth map and other sensitive data. <a href="https://twitter.com/_HarshilShah/status/1136111406271541248">@_HarshilShah</a></li>
<li>A new <code class="language-plaintext highlighter-rouge">UICollectionViewDiffableDataSource</code> class has been added to UIKit to make it easier to manage diffable data sources in <code class="language-plaintext highlighter-rouge">UICollectionView</code> (insert, update and remove actions). <a href="https://twitter.com/_ryannystrom/status/1135683786690113536">@_ryannystrom</a></li>
<li>A new <code class="language-plaintext highlighter-rouge">UICollectionViewCompositionalLayout</code> class has been added to UIKit to make it easier to create compositional layouts without requiring a custom <code class="language-plaintext highlighter-rouge">UICollectionViewLayout</code>. <a href="https://twitter.com/MarvinNazari/status/1135684283132239875">@MarvinNazari</a></li>
<li>iOS 13 supports scroll view scrubbing. Simply drag the scrolling indicator to to fly through a long document. <a href="https://twitter.com/bzamayo/status/1135692076505587712">@bzamayo</a></li>
<li>The mute indicator on iOS 13 has been completely redesigned to match the Apple Pencil charging indicator seen previously on the iPad. <a href="https://twitter.com/MikeBeas/status/1135681611415138304">@MikeBeas</a></li>
<li>Users can now change each app’s language independently from the system language in the Settings app, no change is required by developers. <a href="https://twitter.com/frederikRiedel/status/1135896821232852992">@frederikRiedel</a></li>
<li>iOS now supports multiple windows of your app running simultaneously, and there are new APIs such as <code class="language-plaintext highlighter-rouge">UIScene</code> and <code class="language-plaintext highlighter-rouge">UISceneConfiguration</code> in order to coordinate them. <a href="https://twitter.com/stroughtonsmith/status/1136086390997966854">@stroughtonsmith</a></li>
<li>NFC is getting a lot more powerful in iOS 13, allowing developers to read new type of NFC tags and many new features. <a href="https://twitter.com/imlxgr/status/1136275969008951297">@imlxgr</a>, <a href="https://gototags.com/blog/apple-expands-nfc-on-iphone-in-ios-13/">gototags</a></li>
<li>iOS 13 has a new <code class="language-plaintext highlighter-rouge">_visualRecursiveDescription</code> private API that can construct a visual representation of a view hierarchy. Very useful for debugging in LLDB. <a href="https://twitter.com/steipete/status/1136661076043370496">@steipete</a></li>
<li>iOS apps using the File Management APIs can now be granted read/write access to an entire folder, rather than just a file. <a href="https://twitter.com/stroughtonsmith/status/1136612838158536705">@stroughtonsmith</a></li>
<li>iOS 13 now supports strictly silencing unknown callers. <a href="https://twitter.com/JuanArreguin/status/1136645585581121538">@JuanArreguin</a></li>
<li>Apps can now be removed from the App Store Updates page by simply swiping left on an app. <a href="https://twitter.com/chrisvega/status/1135910167894208512">@chrisvega</a></li>
<li>iOS 13 allows apps to take full content screenshots in a PDF format. <a href="https://twitter.com/qdoug/status/1137070624910655488">@qdoug</a></li>
<li>iMessage will have full blown App Store managed through App Store Connect with full TestFlight capabilities. <a href="https://twitter.com/ott_max/status/1137303995893071872">@ott_max</a></li>
<li>iOS 13 now shows a map of where apps have been tracking you when requesting permission. <a href="https://twitter.com/9to5mac/status/1137390952614682625">@9to5mac</a></li>
<li>In iOS 13, a new method on <code class="language-plaintext highlighter-rouge">UIImageAsset</code> named <code class="language-plaintext highlighter-rouge">registerImage:withTraitCollection</code> can be used to create dynamic images (that switch in light/dark mode) programmatically. <a href="https://twitter.com/timonus/status/1137401708261257219">@timonus</a></li>
<li>The <code class="language-plaintext highlighter-rouge">UITableViewStyle</code> enum gained a new public <code class="language-plaintext highlighter-rouge">UITableViewStyleInsetGrouped</code> case that can be used to create grouped style table views as seen in some of Apple’s stock apps. <a href="https://twitter.com/ian_mcdowell/status/1137478715363880960">@ian_mcdowell</a></li>
<li>iOS 13 has new toast-bar-like tips integrated into apps like iMessage to teach users new actions. <a href="https://twitter.com/kylebshr/status/1137417140280135685">@kylebshr</a></li>
<li>Safari can now auto-close tabs based on when you last viewed them (one day, one week or one month). <a href="https://twitter.com/MacRumors/status/1138046036281159687">@MacRumors</a></li>
</ul>
<h2 id="xcode">Xcode</h2>
<ul>
<li><code class="language-plaintext highlighter-rouge">XCFrameworks</code> make it possible to bundle a binary framework or library for multiple platforms —including iOS devices, iOS simulators, and UIKit for Mac — into a single distributable <code class="language-plaintext highlighter-rouge">.xcframework</code> bundle that your developers can use within their own applications. This should remove the need to use <code class="language-plaintext highlighter-rouge">lipo</code> to create a fat binary. <a href="https://twitter.com/KamilPyc/status/1135628413279100929">@KamilPyc</a></li>
<li>Xcode added a new minimap to get an overview of a source code file. Holding command (⌘) reveals more details and allows to navigate source files easily. <a href="https://twitter.com/_eliperkins/status/1135666873591304192">@_eliperkins</a></li>
<li>You can now manage much of the Swift Package Manager workflow directly in Xcode, such as adding Swift packages to an existing iOS project. <a href="https://twitter.com/cocoawithlove/status/1135669190415699968">@cocoawithlove</a></li>
<li>SwiftUI in Xcode 11 and macOS 10.15 uses a new feature of Swift called “dynamic replacement”. This is similar to how swizzling works in Objective-C, and is needed to avoid recompiling the whole app when changing just one color or font size for example. <a href="https://twitter.com/jckarter/status/1135730593537249282">@jckarter</a></li>
<li>SwiftUI is currently missing an implementation for <code class="language-plaintext highlighter-rouge">UISplitViewController</code> which is coming in a later seed. An API to build forms is also rumored to be released in a later beta. <a href="https://twitter.com/OhItsShaun/status/1136394789299949568">@OhItsShaun</a></li>
<li>With Xcode 11, you can share and open result bundles (.xcresult files) which contain things like tests, code coverage and logs. You can also fully parse them with the new <code class="language-plaintext highlighter-rouge">xcresulttool</code> from custom tooling. <a href="https://twitter.com/czechboy0/status/1135702721812525056">@czechboy0</a></li>
<li>watchOS 6 and Xcode 11 still don’t have <code class="language-plaintext highlighter-rouge">XCTest</code> support. <a href="https://twitter.com/simjp/status/1135718463803052032">@simjp</a></li>
<li>Clang has a new mode -Oz that optimizes your code for size. It reduces code size by identifying identical code sequences across functions. <a href="https://twitter.com/steipete/status/1135792538026033157">@steipete</a></li>
<li><code class="language-plaintext highlighter-rouge">XCTUnwrap</code> is a new API in <code class="language-plaintext highlighter-rouge">XCTest</code> that is equivalent to asserting that an object is not nil and doesn’t throw an error. <a href="https://twitter.com/zntfdr/status/1135860381841104897">@zntfdr</a></li>
<li>In Xcode 11, Interface Builder has some great new icons, especially for NSView and NSControl objects. <a href="https://twitter.com/thequinntaylor/status/1136415276575027201">@thequinntaylor</a></li>
<li>You can command-click on Swift operators to use Quick Help and Jump to Definition. <a href="https://twitter.com/olebegemann/status/1136588444262653954">@olebegemann</a></li>
<li>Xcode 11 has a new “Environment Override” in Storyboard files that allow much faster live accessibility testing. <a href="https://twitter.com/alexiscreuzot/status/1136609041252270080">@alexiscreuzot</a></li>
<li>Application Loader is no longer bundled with Xcode 11. A new native app called Transporter for submission of .itmsp, .ipa and .pkg files is going to be available. <a href="https://twitter.com/ott_max/status/1137303995893071872">@ott_max</a></li>
<li>Xcode now shows an inline diff for all your changes. A new redesigned panel workflow is also present, alogn with some new major features like XCTestPlans, live previews for Stooryboards and UIKit components, the Simulator running on GPU with Metal and condition inducers to test your apps in extreme temperature conditions. <a href="https://twitter.com/edwardsanchez/status/1137961890703765504">@edwardsanchez</a></li>
</ul>
<h2 id="macos">macOS</h2>
<ul>
<li>Holding down option when mousing over the full-screen button reveals some interesting options. <a href="https://twitter.com/BalestraPatrick/status/1135977371255877632">@BalestraPatrick</a></li>
<li>AppKit got some love this year by adding a new <code class="language-plaintext highlighter-rouge">NSSwitch</code> UI element. <a href="https://twitter.com/jnadeau/status/1135694067608592384">@jnadeau</a></li>
<li>In the 10.15 SDK, all of AppKit’s ivars were removed from headers. The ivars that were previously @public have linker symbols exported for compatibility, but you’ll hit build errors with the new SDK if you reference them. <a href="https://twitter.com/jnadeau/status/1136421688256581632">@jnadeau</a></li>
<li>Signing documents with Preview now supports using an iOS device to draw a signature. This is a great improvement since the experience of drawing on a trackpad has always been suboptimal compared to an iOS device touch screen. <a href="https://twitter.com/MacRumors/status/1136752054762856448">@MacRumors</a></li>
</ul>
<h2 id="swift">Swift</h2>
<ul>
<li>GitHub already announced that they will be adding support for Swift packages to the GitHub Package Registry. What this means for our everyday use is still unclear, but possibly it could be help with indexing all Swift packages in a better way. <a href="https://twitter.com/github/status/1135678233368809478">@github</a></li>
<li>Some of the new features in SwiftUI required changes in the language that did not go through the normal review process. This may be suprising at first but an explanation can be found in the following <a href="https://forums.swift.org/t/important-evolution-discussion-of-the-new-dsl-feature-behind-swiftui/25168">Swift Forums post</a>.</li>
<li><code class="language-plaintext highlighter-rouge">SwiftUI</code> uses <code class="language-plaintext highlighter-rouge">SwiftSyntax</code> when you command + click to inspect and modify an element. If you’ve contributed to its open-source version, you can probably brag about your code running inside Xcode now. High five! <a href="https://twitter.com/akyrtzi/status/1135630320978386945">@akyrtzi</a></li>
</ul>
<h2 id="other">Other</h2>
<ul>
<li>The developer portal used to manage certificates, identifiers and profiles has been updated with a fresh design that matches App Store Connect. <a href="https://twitter.com/BalestraPatrick/status/1135831678608392192">@BalestraPatrick</a></li>
<li>An update to the App Store Review Guidelines has been published with two important changes:
<ul>
<li>Apps intended for kids cannot include third-party advertising or analytics software and may not transmit data to third parties.</li>
<li>Because MDM provides access to sensitive data, MDM apps must request the mobile device management capability, and may only be offered by commercial enterprises, such as business organizations, educational institutions, or government agencies, and, in limited cases, companies utilizing MDM for parental controls. MDM apps may not sell, use, or disclose to third parties any data for any purpose, and must commit to this in their privacy policy. (referring to apps that abused MDM for Screen Time-like features)</li>
<li>Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.</li>
</ul>
</li>
<li>TestFlight users are automatically presented with a “What’s New” screen when updating to a newer build. No change is required from developers. <a href="https://twitter.com/MikeBeas/status/1135714588224364544">@MikeBeas</a></li>
<li>When a user takes a screenshot in an app being tested via TestFlight, a new composer will automatically pop up and allow to send a quick feedback to the developer (Instabug sherlocked). <a href="https://twitter.com/_eliperkins/status/1135667969097383936">@_eliperkins</a></li>
<li>iPadOS is just a marketing name to make everything more confusing. It’s still iOS, and even the docs don’t mention iPadOS has a separate platform at the moment. <a href="https://twitter.com/_inside/status/1135640410175332356">@_inside</a></li>
<li>Radar is now Feedback Assistant for external developers. Apple seem to have listened the many complaints about the closeness and the black hole that radar is for external developers, and it has moved its feedback system to a brand new tool (all existing radars have been migrated to the new system). Feedback numbers have a different format too and they look like FB12345678. Apple now tells you how and why a radar was closed. Duplicates are now referred to as similar issues, and it will actually tell you if a fix has been shipped. <a href="https://twitter.com/steipete/status/1135701345573384192">@steipete</a>, <a href="https://twitter.com/kylesethgray/status/1135778423907934208">@kylesethgray</a></li>
<li>macOS 10.15 uses zsh as the default shell. Some of your scripts may be completely broken on macOS Catalina when creating new users with zsh as the default shell, so keep that in mind. The reason for this change is rumoured to be related to the fact that Apple is trying to remove all GPL-licensed code from macOS. <a href="https://twitter.com/davedelong/status/1136389036174561280">@davedelong</a></li>
<li>The public App Store Connect API announced at WWDC 2019 to manage provisioning has been finally released. You can create Bundle IDs, Capabilities, Certificates, Devices and Profiles. <a href="https://twitter.com/BalestraPatrick/status/1136242863128436736">@BalestraPatrick</a></li>
<li>Two new classes that should make it easier to convert dates have been added to Foundation: <code class="language-plaintext highlighter-rouge">ListFormatter</code> and <code class="language-plaintext highlighter-rouge">RelativeTimeFormatter</code>. <a href="https://twitter.com/olebegemann/status/1136663784511213568">@olebegemann</a></li>
<li>SF Symbols is a new framework that contains over 1,500 consistent, highly configurable symbols you can use in your iOS app. You can also create your own symbols by providing SVG files. A companion app to test all symbols on various devices is also available for download. <a href="https://twitter.com/kevgski/status/1135630897003110401">@kevgski</a></li>
<li>IMDF (Indoor Mapping Data Format) is a new concept introduced by Apple that provides a generalized, yet comprehensive model for any indoor location, providing a basis for orientation, navigation and discovery. <a href="https://twitter.com/ortwingentz/status/1135985660332953600">@ortwingentz</a></li>
<li>Apple decreased the number of legal text an app that provides subscriptions has to show to the user. Only the title, length and price of the subscription is required to be shown on every paywall. <a href="https://twitter.com/jeiting/status/1137043638985216000">@jeiting</a>, <a href="https://twitter.com/macguru17/status/1137144925164752896">@macguru17</a></li>
<li>App Store Connect will soon get a near real time sales view showing you the last 24 hours. <a href="https://twitter.com/lesmond/status/1136777940773957632">@lesmond</a></li>
<li>App deletions statistics will also be available as part of App Analytics in App Store Connect. <a href="https://twitter.com/ilyakuh/status/1136777597751308288">@ilyakuh</a></li>
<li>The <code class="language-plaintext highlighter-rouge">Photos</code> framework on the Mac has now pretty much the same feature availability as iOS. <a href="https://twitter.com/toco91/status/1137898246683144192">@toco91</a></li>
<li><code class="language-plaintext highlighter-rouge">NSListFormatter</code> is a new API in Foundation that makes it easier to format a list of items for the user’s locale. <a href="https://twitter.com/qdoug/status/1137909572381872128">@qdoug</a></li>
</ul>
<h2 id="funny">Funny</h2>
<ul>
<li>iOS 9999 is not a thing unfortunately. <a href="https://twitter.com/slava_pestov/status/1135748058942074881">@slava_pestov</a></li>
</ul>Patrick BalestraWWDC 2019 was definitely the biggest event in the last few years. I was in the audience when Swift was announced in 2014, but I can say that this year is probably bigger than WWDC 2014. Given the many changes across frameworks, OSes, developers tools and web services that Apple offers, many interesting minor long-awaited improvements may have gone unnoticed. I tried to collect some of the announcements that may have been shadowed by the bigger announcements in a single and short post. Every item has an associated source or link where you can learn more about it. I am planning to keep this list up to date over the next few weeks as a personal reference, so feel free to send me anything you discover. I hope you enjoy the list!Contributing to the Swift Benchmark Suite2018-11-12T00:00:00+00:002018-11-12T00:00:00+00:00https://balestrapatrick.github.io/blog/2018/11/12/contributing-to-the-swift-benchmark-suite<p><img src="/assets/blog/contributing-to-the-swift-benchmark-suite/header.jpg" alt="" />
In this post I will explain what the Swift Benchmark Suite is, why is it useful and how you can contribute to it. The Swift benchmark suite is part of the Swift open source project available on on GitHub.
<!--more--></p>
<p>The Swift team <a href="https://swift.org/blog/swift-benchmark-suite/">announced on February 8, 2016</a> that they just open sourced the Swift benchmark suite which wasn’t included in the initial release of the Swift compiler and standard library. In the blog post, it is described that the suite contains “source code for benchmarks, libraries and utilities designed to help track Swift performance and catch performance regressions before they are committed”. The blog post mentions over 75 benchmarks at the time, and today that number has increased to over 150 benchmarks (each defining multiple tests). The suite is well-thought-out and contains various components that can be useful to learn if you plan to contribute with new benchmarks (which is what we’re going to do later!). The benchmark suite contains:</p>
<ul>
<li>Libraries providing commonly needed benchmarking functions so you don’t need to reinvent the wheel in every benchmark.</li>
<li>A driver for running benchmarks, displaying performance metrics and estimate how many times each benchmark should be ran to get a good statistical result.</li>
<li>A utility for comparing benchmark metrics across Swift versions.</li>
</ul>
<p>The benchmark suite is integrated with the <code class="language-plaintext highlighter-rouge">swift-ci</code> GitHub bot that is used in the Swift project to perform many useful actions in pull requests. When a PR is opened, a Swift team member may comment with the command <code class="language-plaintext highlighter-rouge">@swift-ci please benchmark</code>. This will start a build on Jenkins that runs the benchmarks and comments the PR with the results.</p>
<p><img src="/assets/blog/contributing-to-the-swift-benchmark-suite/swift-ci.png" alt="" />
<em>The typical workflow of merging a PR to the Swift project.</em></p>
<h1 id="getting-started">Getting Started</h1>
<p>The main README in the repository is pretty short and links to external resources such as the <a href="https://swift.org/contributing/">Contributing Guide</a> on <a href="https://swift.org">swift.org</a>.
The README in the swift directory is a very good and straightforward guide on how to get started with the project. You can follow the guide there but I will report the main steps here too:</p>
<ol>
<li>Install <code class="language-plaintext highlighter-rouge">cmake</code> and <code class="language-plaintext highlighter-rouge">ninja</code> which are used to compile pretty much everything in the Swift repo.
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew <span class="nb">install </span>cmake ninja
</code></pre></div> </div>
</li>
<li>Create a directory to clone the whole Swift project into it.
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>swift-source
<span class="nb">cd </span>swift-source
</code></pre></div> </div>
</li>
<li>Clone the repo and invoke the built-in script that completes the checkout.
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com:apple/swift.git
./swift/utils/update-checkout <span class="nt">--clone-with-ssh</span>
</code></pre></div> </div>
</li>
</ol>
<p>You’re done, that was easy! You should now have the full Swift source code in the <code class="language-plaintext highlighter-rouge">swift-source</code> folder. The folder itself is about 2GB in size, but if you plan to work on it, make sure you to have a lot more free space. 😅</p>
<p><img src="/assets/blog/contributing-to-the-swift-benchmark-suite/repo-size.png" alt="" />
<em>Make sure to clean the build folder every so often.</em></p>
<h1 id="building-swift">Building Swift</h1>
<p>Swift contains a <code class="language-plaintext highlighter-rouge">build-script</code> that can compile different parts of the project. You can choose between using Xcode or Ninja as the build system. I went with <code class="language-plaintext highlighter-rouge">ninja</code> since I wanted to get familiar with it. To compile a release build with debug info (which will take a ton of space on your machine), run the following command:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>utils/build-script <span class="nt">--release-debuginfo</span>
</code></pre></div></div>
<p>The are many flags that can be used to compile different configurations supported by the build script. You can list all the available arguments by passing the <code class="language-plaintext highlighter-rouge">-h</code> flag to the build script. Building the project in debug mode will take longer and the execution time will be impacted as well. This is why a release build is used to benchmark Swift code.</p>
<p>The documentation suggests to perform a full build right after cloning the project, to verify that everything is set up correctly. Make sure you have a charger nearby before starting the build. The first time I started the build, I decided to leave my Mac building with 60% battery left while going for dinner only to discover that it was out of battery less than 20 minutes later.</p>
<h1 id="string-benchmark-gaps">String Benchmark Gaps</h1>
<p><a href="https://twitter.com/Ilseman/status/1047562831476842501">Michael Ilseman tweeted</a> a couple of weeks ago about a new set of starter bugs in the standard library. <a href="https://bugs.swift.org/browse/SR-8905">SR-8905</a> includes a pretty thorough description of the gaps in the String benchmarks with some advices on where to look to address the problems. At the moment of writing, all gaps are still open for volunteers except the one I fixed which I describe in this post. To start a task, create a new JIRA bug with the title and description of which <code class="language-plaintext highlighter-rouge">String</code> method you would like to benchmark. Assign it to yourself and comment back on the main issue to make sure other people don’t start the same task. This is what I did with <a href="https://bugs.swift.org/browse/SR-8908">SR-8908</a>. Having a separate task that tracks a subset of the work is very useful to ask for help too. Simply ping an Apple engineer who works on that specific area and he or she will be happy to guide you through the process. Michael Ilsman helped me a lot in understanding type of benchmarks expected to be written in the suite. He was also kind enough to provide some tips he had to iterate faster when writing benchmarks and more details that helped me understand each built-in function.</p>
<p>After creating the bug and assigning it to yourself in the Swift JIRA, it’s time to dive into the Swift standard library source code. 🛠</p>
<h1 id="browsing-the-project">Browsing the project</h1>
<p>If you have cloned the repo correctly as instructed before, you will now see a <code class="language-plaintext highlighter-rouge">swift</code> folder. Inside it, you can see the <code class="language-plaintext highlighter-rouge">stdlib</code> folder that contains the standard library source code. It’s a good idea to take a look at the different folders and see how the project is structured. The area of the project where we will focus in this post is the <code class="language-plaintext highlighter-rouge">benchmark</code> folder, which contains the benchmark suite of the standard library.</p>
<p>Most of the benchmarks can be found in the <code class="language-plaintext highlighter-rouge">single-source</code> folder. Here you will find over 150 files at the time of writing, that benchmark many standard library types and methods to monitor the performance and catch regressions. The scripts that are responsible to run all the benchmarks are inside the <code class="language-plaintext highlighter-rouge">scripts</code> folder and are written in Python. Some skeleton files used to register all benchmarks are defined inside the <code class="language-plaintext highlighter-rouge">utils</code> folder, such as the <code class="language-plaintext highlighter-rouge">main.swift</code> file.</p>
<h1 id="how-a-benchmark-is-defined">How a benchmark is defined</h1>
<p>Benchmarks are usually defined as a single operation that can be executed multiple times in order to get a good and confident statistical value. Once the value is obtained for every benchmark, they are compared with historical values in order to understand the effect of changes in the standard library source code. As a pure example, let’s imagine that a big refactor of the sorting algorithm needs to happen. A very good starting point would be to make sure that there’s a benchmark for it in order to assess the difference in execution time before and after the refactor. The suite is a set of micro benchmarks which should be executed fairly quickly. Every benchmark should thus target an execution time of around 1000 microseconds (1 ms). As explained by <a href="https://bugs.swift.org/browse/SR-8905?focusedCommentId=40332&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-40332">Pavol Vaskovic</a>, <em>longer runtimes accumulate measurement errors due to context switching between processes by OS scheduler</em>.</p>
<h1 id="defining-a-new-benchmark">Defining a new benchmark</h1>
<p>As mentioned earlier, it’s a good idea to perform a full build after the first clone. There is one small change that you need to do to the previously mentioned command to build the standard library. Each benchmark must be executed against a release build of Swift to get the real execution time. You need to build the standard library without assertions, which you can do by appending the <code class="language-plaintext highlighter-rouge">--no-swift-stdlib-assertions</code> flag:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./swift/utils/build-script <span class="nt">--release-debuginfo</span> <span class="nt">--no-swift-stdlib-assertions</span>
</code></pre></div></div>
<p>Defining a new benchmark is explained in the <a href="https://github.com/apple/swift/tree/master/benchmark">README</a> of the benchmark directory. There are two types of test that can be added: single file and multiple files tests. There aren’t many multiple files tests defined in the <code class="language-plaintext highlighter-rouge">multi-source</code> directory, so I think most tests are supposed to be single source.
There are a few very simple steps in order to have a new benchmark registered with the benchmark driver and automatically be executed when running the benchmark suite:</p>
<ol>
<li>
<p>Add a new Swift file to the <code class="language-plaintext highlighter-rouge">single-source</code> folder named according to the benchmark you’re about to write. We will worry about its contents later.</p>
</li>
<li>
<p>Add the path to the new file in <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code>. Make sure to insert the new file name in the right position since all the tests are listed in alphabetical order.</p>
</li>
</ol>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#===-----------------------------------------------------------------------===#</span>
<span class="c1"># Declarative Description of Benchmarks</span>
<span class="c1">#===-----------------------------------------------------------------------===#</span>
<span class="nb">set</span><span class="p">(</span>SWIFT_BENCH_MODULES
...
single-source/InsertCharacter
...
<span class="p">)</span>
</code></pre></div></div>
<ol>
<li>Open <code class="language-plaintext highlighter-rouge">main.swift</code> in the <code class="language-plaintext highlighter-rouge">utils</code> directory and import the new file (which is compiled as a module) and register the benchmark with the driver, which is a fancy way of saying adding it to the internal array of benchmarks 🤪:</li>
</ol>
<pre>
<code>
<span class="comment">//</span> <span class="comment">This</span> <span class="comment">is</span> <span class="comment">just</span> <span class="comment">a</span> <span class="comment">driver</span> <span class="comment">for</span> <span class="comment">performance</span> <span class="comment">overview</span> <span class="comment">tests.</span>
<span class="comment">//</span> <span class="comment">more</span> <span class="comment">imports...</span>
<span class="keyword">import</span> InsertCharacter
<span class="comment">//</span> <span class="comment">more</span> <span class="comment">benchmark</span> <span class="comment">registration...</span>
<span class="call">registerBenchmark</span>(<span class="type">InsertCharacter</span>)
</code>
</pre>
<p>This was a rather manual and error-prone process, maybe you could turn this into new starter bug? 😏</p>
<p>Let’s now get into the interesting stuff: how to write a benchmark.</p>
<h1 id="writing-a-benchmark">Writing a benchmark</h1>
<p>The README provides a template that is a good starting point. I simply pasted it into a new file named <code class="language-plaintext highlighter-rouge">InsertCharacter.swift</code> and replaced “YourTestName” with “InsertCharacter” in my case.</p>
<pre>
<code>
<span class="comment">//</span> <span class="comment">YourTestName</span> <span class="comment">benchmark</span>
<span class="comment">//</span>
<span class="comment">//</span> <span class="comment">rdar://problem/00000000</span>
<span class="keyword">import</span> TestsUtils
<span class="keyword">public</span> <span class="keyword">let</span> <span class="type">YourTestName</span> = <span class="type">BenchmarkInfo</span>(
name: <span class="string">"YourTestName"</span>,
runFunction: run_YourTestName,
tags: [.regression])
<span class="keyword">@inline</span>(never)
<span class="keyword">public</span> <span class="keyword">func</span> run_YourTestName(<span class="type">N</span>: <span class="type">Int</span>) {
<span class="comment">//</span> <span class="comment">Declare</span> <span class="comment">variables</span>
<span class="keyword">for</span> i <span class="keyword">in</span> <span class="number">1</span>...<span class="type">N</span> {
<span class="comment">//</span> <span class="comment">Perform</span> <span class="comment">work</span>
<span class="comment">//</span> <span class="comment">Verify</span> <span class="comment">work</span> <span class="comment">was</span> <span class="comment">done;</span> <span class="comment">break</span> <span class="comment">otherwise</span>
}
<span class="comment">//</span> <span class="comment">Assert</span> <span class="comment">with</span> <span class="comment">CheckResults</span> <span class="comment">that</span> <span class="comment">work</span> <span class="comment">was</span> <span class="comment">done</span>
}
</code>
</pre>
<p>First of all, many benchmarks start with the Apple copyright header (not reported here for brevity) and with a simple description of the benchmark and a link to the relative radar or JIRA bug. The <code class="language-plaintext highlighter-rouge">TestUtils</code> module (found in <code class="language-plaintext highlighter-rouge">benchmark/utils/</code>) is imported which contains useful functions and data types such as benchmark categories and test functions like:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">CheckResults</code>: allows to assert the result of an operation</li>
<li><code class="language-plaintext highlighter-rouge">blackHole</code>: an <code class="language-plaintext highlighter-rouge">@inline(never)</code> function which does nothing</li>
<li><code class="language-plaintext highlighter-rouge">identity</code>: an <code class="language-plaintext highlighter-rouge">@inline(never)</code> function which simply returns its parameter)</li>
</ul>
<p>One interesting point to keep in mind is that the <code class="language-plaintext highlighter-rouge">TestUtils</code> and the benchmark files are defined in two different modules. In this way, if the benchmark calls an utility function defined in <code class="language-plaintext highlighter-rouge">TestUtils,</code> it will prevent the optimizer to optimize the operation we’re trying to benchmark.</p>
<p>Continuing with the code in the template, we define one or more tests, the name of the associated function that defines the benchmark and an array of tags. Tags can be used to group benchmarks together and run them easily through the benchmark driver (i.e: run all the <code class="language-plaintext highlighter-rouge">Codable</code> benchmarks).</p>
<p>The benchmark is then implemented in a function that starts with “run” for convention. The function takes a parameter <code class="language-plaintext highlighter-rouge">N</code> of type <code class="language-plaintext highlighter-rouge">Int</code> which is estimated by the benchmark driver. The driver first runs the benchmark with <code class="language-plaintext highlighter-rouge">N = 1</code> and estimates how many times it can run the benchmark in one second. This is why the benchmark should be fast and ideally run in a few milliseconds. The driver will then invoke the benchmark with the estimated value in the future and compare the execution time in order to catch regressions.</p>
<p>The file defining the benchmark is a pure Swift file and can contain global variables (such as data structures used in multiple benchmarks) as well as utility functions.</p>
<h1 id="string-benchmarks">String benchmarks</h1>
<p>I decided to take on the task of writing the first benchmarks for <code class="language-plaintext highlighter-rouge">insert(_:character)</code>. I started by reading the <a href="https://developer.apple.com/documentation/swift/string/3018525-insert">documentation</a> of the method and making sure I understood its complexity when inserting a character at different positions. Starting Swift 4, <code class="language-plaintext highlighter-rouge">String</code> is now a collection again and many methods are shared between <code class="language-plaintext highlighter-rouge">Array</code> and <code class="language-plaintext highlighter-rouge">String</code> for example.</p>
<p>I asked for clarification in the JIRA bug to make sure that what the benchmarks that I was about to write were meaningful and correct. Michael suggested a few tweaks and improvements to make sure the benchmarks would be linear on the input parameter estimated by the driver and that the optimizer wouldn’t optimize the insertions of the same character multiple times.</p>
<p>I decided to write 3 benchmarks with 2 variants, for a total of 6 benchmarks. Let’s take a closer look at their implementation:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">insertAtStartIndex</code> is benchmarked with an ASCII and non-ASCII character parameter. It inserts a character at the beginning of the string. Since the insertion of a character at the front requires all subsequent characters to be shifted in memory, the complexity of this benchmark would be O(n²). The benchmark driver estimates the number of times each benchmark has to be executed to get a good statistical value, so having a benchmark with non-linear complexity isn’t a good idea. This was the most challenging benchmark to write and with Michael’s suggestion, the solution it to wrap the quadratic loop in a linear loop. By doing that, the quadratic operation is executed a linear amount of times which allows the driver to estimate the total number of iterations the benchmark should perform.</li>
</ul>
<p><img src="/assets/blog/contributing-to-the-swift-benchmark-suite/insertAtStartIndex.jpg" alt="" />
<em>A visualization of inserting a character at the start of the string.</em></p>
<pre>
<code>
<span class="comment">//</span> <span class="comment">Insert</span> <span class="comment">at</span> <span class="comment">start</span> <span class="comment">index</span>
<span class="keyword">@inline</span>(__always)
<span class="keyword">func</span> insertAtStartIndex(<span class="keyword">_</span> c: <span class="type">Character</span>, <span class="keyword">in</span> string: <span class="type">String</span>, count: <span class="type">Int</span>, insertions: <span class="type">Int</span>) {
<span class="keyword">var</span> workload = str
<span class="keyword">for</span> <span class="keyword">_</span> <span class="keyword">in</span> <span class="number">0</span>..<count {
<span class="keyword">for</span> <span class="keyword">_</span> <span class="keyword">in</span> <span class="number">0</span>..<insertions {
workload.<span class="call">insert</span>(<span class="call">identity</span>(c), at: workload.<span class="property">startIndex</span>)
}
workload = str
}
<span class="call">blackHole</span>(workload)
}
<span class="keyword">@inline</span>(never)
<span class="keyword">func</span> run_InsertCharacterStartIndex(<span class="keyword">_</span> <span class="type">N</span>: <span class="type">Int</span>) {
<span class="call">insertAtStartIndex</span>(<span class="string">"w"</span>, in: str, count: <span class="type">N</span> * <span class="number">75</span>, insertions: <span class="number">50</span>)
}
<span class="keyword">@inline</span>(never)
<span class="keyword">func</span> run_InsertCharacterStartIndexNonASCII(<span class="keyword">_</span> <span class="type">N</span>: <span class="type">Int</span>) {
<span class="call">insertAtStartIndex</span>(<span class="string">"👩🏾🏫"</span>, in: str, count: <span class="type">N</span> * <span class="number">75</span>, insertions: <span class="number">25</span>)
}
</code>
</pre>
<ul>
<li><code class="language-plaintext highlighter-rouge">insertAtEndIndex</code> is benchmarked with an ASCII and non-ASCII character parameter. It inserts a character at <code class="language-plaintext highlighter-rouge">endIndex</code> which should be a O(1) operation (equal to <code class="language-plaintext highlighter-rouge">append</code>). You may think that this benchmark is useless, but in my opinion it’s still a good idea to have it to make sure the performance of inserting a character at the end of a <code class="language-plaintext highlighter-rouge">String</code> doesn’t deviate from simply appending an element to a generic <code class="language-plaintext highlighter-rouge">Array</code>.</li>
</ul>
<p><img src="/assets/blog/contributing-to-the-swift-benchmark-suite/insertAtEndIndex.jpg" alt="" />
<em>A visualization of inserting a character at the end of the string.</em></p>
<pre>
<code>
<span class="comment">//</span> <span class="comment">Insert</span> <span class="comment">at</span> <span class="comment">end</span> <span class="comment">index</span>
<span class="keyword">@inline</span>(__always)
<span class="keyword">func</span> insertAtEndIndex(<span class="keyword">_</span> c: <span class="type">Character</span>, <span class="keyword">in</span> string: <span class="type">String</span>, count: <span class="type">Int</span>) {
<span class="keyword">var</span> workload = string
<span class="keyword">for</span> <span class="keyword">_</span> <span class="keyword">in</span> <span class="number">0</span>..<count {
workload.<span class="call">insert</span>(<span class="call">identity</span>(c), at: workload.<span class="property">endIndex</span>)
}
<span class="call">blackHole</span>(workload)
}
<span class="keyword">@inline</span>(never)
<span class="keyword">func</span> run_InsertCharacterEndIndex(<span class="keyword">_</span> <span class="type">N</span>: <span class="type">Int</span>) {
<span class="call">insertAtEndIndex</span>(<span class="string">"s"</span>, in: str, count: <span class="type">N</span> * <span class="number">3000</span>)
}
<span class="keyword">@inline</span>(never)
<span class="keyword">func</span> run_InsertCharacterEndIndexNonASCII(<span class="keyword">_</span> <span class="type">N</span>: <span class="type">Int</span>) {
<span class="call">insertAtEndIndex</span>(<span class="string">"👩🏾🏫"</span>, in: str, count: <span class="type">N</span> * <span class="number">1000</span>)
}
</code>
</pre>
<ul>
<li><code class="language-plaintext highlighter-rouge">insertTowardsEndIndex</code> is benchmarked with an ASCII and non-ASCII character parameter. The function inserts a character at the initial <code class="language-plaintext highlighter-rouge">endIndex</code> as many times as the estimated parameter. Every 1000 insertions, the <code class="language-plaintext highlighter-rouge">endIndex</code> is updated and the next characters are inserted at the new <code class="language-plaintext highlighter-rouge">endIndex</code>.
<img src="/assets/blog/contributing-to-the-swift-benchmark-suite/insertTowardsEndIndex.jpg" alt="" />
<em>A visualization of inserting a character close to the end of the string.</em></li>
</ul>
<pre>
<code>
<span class="comment">//</span> <span class="comment">Insert</span> <span class="comment">towards</span> <span class="comment">end</span> <span class="comment">index</span>
<span class="keyword">@inline</span>(__always)
<span class="keyword">func</span> insertTowardsEndIndex(<span class="keyword">_</span> c: <span class="type">Character</span>, <span class="keyword">in</span> string: <span class="type">String</span>, count: <span class="type">Int</span>) {
<span class="keyword">var</span> workload = string
<span class="keyword">var</span> index = workload.<span class="property">endIndex</span>
<span class="keyword">for</span> i <span class="keyword">in</span> <span class="number">0</span>..<count {
workload.<span class="call">insert</span>(<span class="call">identity</span>(c), at: index)
<span class="keyword">if</span> i % <span class="number">1000</span> == <span class="number">0</span> {
index = workload.<span class="property">endIndex</span>
}
}
<span class="call">blackHole</span>(workload)
}
<span class="keyword">@inline</span>(never)
<span class="keyword">func</span> run_InsertCharacterTowardsEndIndex(<span class="keyword">_</span> <span class="type">N</span>: <span class="type">Int</span>) {
<span class="call">insertTowardsEndIndex</span>(<span class="string">"s"</span>, in: str, count: <span class="type">N</span> * <span class="number">3000</span>)
}
<span class="keyword">@inline</span>(never)
<span class="keyword">func</span> run_InsertCharacterTowardsEndIndexNonASCII(<span class="keyword">_</span> <span class="type">N</span>: <span class="type">Int</span>) {
<span class="call">insertTowardsEndIndex</span>(<span class="string">"👩🏼💻"</span>, in: str, count: <span class="type">N</span> * <span class="number">1000</span>)
}
</code>
</pre>
<p>As you can see, the common logic between the two tests is abstracted away in an always-inlineable function which accepts different parameters. If we want to insert an ASCII or non-ASCII character, we can simply pass in a different character instead of duplicating the code. The <code class="language-plaintext highlighter-rouge">@inline(__always)</code> attribute tells the optimizer to always replace the function call with the implementation. If you want to read more about this attribute, check <a href="https://github.com/vandadnp/swift-weekly/blob/master/issue11/README.md#inline">this</a> out.</p>
<h1 id="faster-iterations">Faster iterations</h1>
<p>I was interested in seeing if there was a way to run benchmarks without the needs of recompiling the suite again (which can take some time). Michael suggested to abstract the code into a separate executable and re-implement some of the helper functions that the benchmark suite provides. This setup doesn’t exactly represent the real scenario since the source code is compiled into a single module instead of using functions from another module to prevent optimizations. The following code snippet is what I used to iterate faster on String benchmarks based on Michael’s snippet shared as a <a href="https://gist.github.com/milseman/9b579ab001f12676b15b40b1b87e9143">gist</a>.</p>
<pre>
<code>
<span class="keyword">import</span> Dispatch
<span class="call">print</span>(<span class="string">"start"</span>)
<span class="keyword">public</span> <span class="keyword">var</span> i = <span class="number">0</span>
<span class="keyword">@inline</span>(never)
<span class="keyword">public</span> <span class="keyword">func</span> blackHole(<span class="keyword">_</span> x: <span class="type">Bool</span>) {
i += x ? <span class="number">1</span> : <span class="number">0</span>
}
<span class="keyword">@inline</span>(never)
<span class="keyword">public</span> <span class="keyword">func</span> blackHole<C: <span class="type">Collection</span>>(<span class="keyword">_</span> x: <span class="type">C</span>) {
i += x.<span class="property">isEmpty</span> ? <span class="number">1</span> : <span class="number">0</span>
}
<span class="keyword">@inline</span>(never)
<span class="keyword">public</span> <span class="keyword">func</span> blackHole<T>(<span class="keyword">_</span> x: <span class="type">UnsafeMutablePointer</span><T>) {
i += <span class="type">UInt</span>(bitPattern: x) % <span class="number">2</span> == <span class="number">0</span> ? <span class="number">1</span> : <span class="number">0</span>
}
<span class="keyword">@inline</span>(never)
<span class="keyword">public</span> <span class="keyword">func</span> <span class="type">CheckResults</span>(<span class="keyword">_</span> x: <span class="type">Bool</span>) {
<span class="keyword">guard</span> x <span class="keyword">else</span> { <span class="call">fatalError</span>() }
}
<span class="keyword">@inline</span>(never)
<span class="keyword">public</span> <span class="keyword">func</span> identity<T>(<span class="keyword">_</span> x: <span class="type">T</span>) -> <span class="type">T</span> {
<span class="keyword">return</span> x
}
<span class="keyword">func</span> time<T>(<span class="keyword">_</span> _caller : <span class="type">String</span> = #function, <span class="keyword">_</span> block: () -> <span class="type">T</span>) -> <span class="type">T</span> {
<span class="keyword">let</span> start = <span class="type">DispatchTime</span>.<span class="call">now</span>()
<span class="keyword">let</span> res = <span class="call">block</span>()
<span class="keyword">let</span> end = <span class="type">DispatchTime</span>.<span class="call">now</span>()
<span class="keyword">let</span> milliseconds = (end.<span class="property">uptimeNanoseconds</span> - start.<span class="property">uptimeNanoseconds</span>) / <span class="number">1_000_000</span>
<span class="call">print</span>(<span class="string">"</span>\(_caller)\<span class="string">t</span>\(milliseconds)<span class="string">"</span>)
<span class="keyword">return</span> res
}
<span class="call">print</span>(<span class="string">"Running..."</span>)
<span class="call">time</span>(<span class="string">"Benchmark</span> <span class="string">name</span> <span class="string">here"</span>) {
<span class="comment">//</span> <span class="comment">run_YourBenchmarkFunctionNameHere</span>
}
</code>
</pre>
<p>I suggest using <a href="https://coderunnerapp.com">CodeRunner</a> which I recently discovered to quickly run your code if you want to iterate faster when writing new benchmarks.</p>
<h1 id="profiling-with-instruments">Profiling with Instruments</h1>
<p>After abstracting a benchmark into a single file, it’s much easier to profile it with Instruments too. To profile a benchmark, you can first compile it and then invoke Instruments by specifying the template that you would like to use.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>swiftc <span class="nt">-O</span> benchmarks.swift <span class="o">&&</span> instruments <span class="nt">-t</span> <span class="s2">"Time Profiler"</span> ./benchmarks
</code></pre></div></div>
<p>Instruments executes the Swift binary and produces a <code class="language-plaintext highlighter-rouge">.trace</code> file that can be opened in Instruments to visualize the information captured.
Initially, I was using the <code class="language-plaintext highlighter-rouge">CheckResults</code> function to assert that the benchmark was performing the right amount of work. This assertion required to invoke the <code class="language-plaintext highlighter-rouge">count</code> method (which is a O(n) operation) on a very long string at the end of the benchmark. I was able to track down that ~2-3% of the total time of the benchmark was spent doing this operation. Since this is not a unit test but rather a benchmark, I decided to remove all <code class="language-plaintext highlighter-rouge">CheckResults</code> in order to spend 100% of the time in executing the operation we’re benchmarking. As you can see in the following screenshot, the <code class="language-plaintext highlighter-rouge">count</code> method takes 1.3% of the benchmark time in this case.
<img src="/assets/blog/contributing-to-the-swift-benchmark-suite/instruments.png" alt="" />
<em>Trace generated by running the time profiler on a benchmark.</em></p>
<h1 id="executing-a-benchmark">Executing a benchmark</h1>
<p>We can now use the benchmark driver to run our tests (or only a subset too!). This part took me a while to figure out since some commands didn’t work for me or I was executing them in the wrong directories.
After the compilation has finished successfully, a <code class="language-plaintext highlighter-rouge">build</code> folder should appear at the root of the project. It contains a different folder for every configuration that you have built, which is handy if you want to experiment in parallel with different build configurations. You should see a <code class="language-plaintext highlighter-rouge">Ninja-RelWithDebInfo</code> folder which contains the artifacts of the compilation. You may need to recompile the project again to have your new benchmark show up in it. Inside the folder you’ll notice three other folders, one for each product that was compiled. We are interested in <code class="language-plaintext highlighter-rouge">swift-macosx-x86_64</code>. Take a look at the <code class="language-plaintext highlighter-rouge">bin</code> directory which contains many executables. Let’s try to run the benchmark driver in the following way:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./bin/Benchmark_O
</code></pre></div></div>
<p>The driver will start to execute every test one by one and report the recorded values along with their names. The logs are printed in a CSV format, which should make it very easy to create graphs to visualize the data over time (maybe it’s already used internally by the Swift team?).</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs)</span>
2,AngryPhonebook,1,3415,3415,3415,0,3415
3,AnyHashableWithAClass,1,91148,91148,91148,0,91148
...
</code></pre></div></div>
<p>Launching the driver directly is useful if you want to run all the 650+ benchmarks, but hopefully you want to save some CPU cycles. Passing the <code class="language-plaintext highlighter-rouge">-h</code> flag to the driver will show all the comands that are supported, such as <code class="language-plaintext highlighter-rouge">--list</code>, which will simply print all available benchmarks.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./bin/Benchmark_O <span class="nt">--list</span>
<span class="c">#,Test,[Tags]</span>
2,AngryPhonebook,[String, api, validation]
3,AnyHashableWithAClass,[abstraction, cpubench, runtime]
4,Array2D,[Array, api, validation]
...
</code></pre></div></div>
<p>Every benchmark can be referenced by its identifier (show in the # column). Keep in mind that this number can change when adding/removing benchmarks, since it’s simply the index of the benchmark in the array. By listing all the benchmarks you can quickly verify that your new benchmark is correctly registered. You can then take note of the test that you will be working on to run it directly with the <code class="language-plaintext highlighter-rouge">--run</code> flag:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ./bin/Benchmark_O run 332 333 334 335 336 337
#,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs)
332,InsertCharacterEndIndex,1,985,985,985,0,985
333,InsertCharacterEndIndexNonASCII,1,326,326,326,0,326
334,InsertCharacterStartIndex,1,1531,1531,1531,0,1531
335,InsertCharacterStartIndexNonASCII,1,770,770,770,0,770
336,InsertCharacterTowardsEndIndex,1,1007,1007,1007,0,1007
337,InsertCharacterTowardsEndIndexNonASCII,1,689,689,689,0,689
Total performance tests executed: 6
</code></pre></div></div>
<p>Here I run the 6 benchmarks that I wrote in <code class="language-plaintext highlighter-rouge">InsertCharacter.swift</code>.</p>
<h1 id="create-a-pr">Create a PR</h1>
<p>After completing your changes it’s time to push them to your fork. After that is done, you can then open a PR in the Swift repo by following the code of conduct and reading the contributing guidelines. A member of the Swift team will then review and give advices on how to improve your changes even more. In my case, the PR was first approved but the merge failed due to some unrelated tests failing on Jenkins. Another member of the Swift team later reviewed the changes and noticed some possible improvements that could be made. After pushing the new improvements, the PR was approved and immediately merged! 🚢</p>
<p><img src="/assets/blog/contributing-to-the-swift-benchmark-suite/pr.png" alt="" />
<em>Ship it!</em></p>
<h1 id="conclusion">Conclusion</h1>
<p>If you’re looking to learn more about the internals of Swift and you’re up for some new challenges, you should definitely start taking a look at the Swift repo and starter bugs. Starting with the benchmark suite is a good opportunity to contribute to the project if you don’t have knowledge about C++ (like myself). Don’t be scared about the size of the project and the many different unknown components. The Swift team is very nice and kind and every contributor is always welcome to the project. Give it a try!</p>
<p>Feel free to <a href="https://twitter.com/BalestraPatrick">tweet me</a> with any questions or comments. 👍</p>
<p>Big thanks to <a href="https://twitter.com/Ilseman">Michael Ilseman</a> for the help throughout this project, to <a href="https://twitter.com/a2">Alexsander Akers</a> and <a href="https://twitter.com/maxbaeumle">Max Bäumle</a> for proofreading the article.</p>Patrick BalestraIn this post I will explain what the Swift Benchmark Suite is, why is it useful and how you can contribute to it. The Swift benchmark suite is part of the Swift open source project available on on GitHub.Improving Your Build Time in Xcode 102018-08-27T00:00:00+00:002018-08-27T00:00:00+00:00https://balestrapatrick.github.io/blog/2018/08/27/improving-your-build-time-in-xcode-10<p>I finally had time to watch some of the WWDC talks related to Xcode 10 today, and I wanted to share some very interesting and useful new tips to improve the build times of Swift and Objective-C projects in Xcode 10.
<!--more--></p>
<p>Most of the content in this post is taken from <a href="https://developer.apple.com/videos/play/wwdc2018/408/">WWDC 2018 Session 408 - Building Faster in Xcode</a>.</p>
<h2 id="parallelizing-your-build-process">Parallelizing your build process</h2>
<p>Previously to Xcode 10, all the targets were built serially, which means that only one target can be built at any given time. Xcode 10 is now much faster in building since it distributes tasks across multiple cores to build targets in parallel whenever possible. Let’s take the example shown in the session to see how the timeline would look in order to build 5 targets in Xcode 9.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/serialized-timeline.png" alt="Serialized Work" />
<em>In Xcode 9 every target is built after the other.</em></p>
<p>All the targets are built one after the other, starting from the ones that are dependencies of other targets. One real example of where you may have noticed this behavior is when using CocoaPods. If you have 10 dependencies in your <code class="language-plaintext highlighter-rouge">Podfile</code>, Xcode needs to build all the Pods before building your target. This is why using Carthage usually decreases your build times, since the dependencies are compiled once and only linked at runtime with your app target.</p>
<p>Xcode 10 tries to make better utilization of the available hardware by distributing on multiple cores the targets to build. Thus, the timeline could look like something like this.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/parallelization-timeline.png" alt="Serialized Work" />
<em>By reducing the size of your targets, you will obtain a better parallelization.</em></p>
<p>When opening your project in Xcode 10, build parallelization should already be enabled. To check or change this option, open your scheme editor, select “Build” in the sidebar and make sure “Parallelize Build” is checked at the top.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/parallelized-build.png" alt="Parallelized Build" />
<em>Xcode Scheme editor build options.</em></p>
<p>Of course, Xcode can’t build all your targets at once. Your project will most likely have some dependencies between the targets. A cool algorithm that is usually used to solve dependencies and figure out the order of compilation is <a href="https://en.wikipedia.org/wiki/Topological_sorting">topological sorting</a>.</p>
<p><em>Fun fact: this is a common topic in technical interviews at <a href="https://www.reddit.com/r/cscareerquestions/comments/6tkc59/what_is_a_big_n_company/">Big N</a> companies, so definitely learn more about it if you’re interested in computer science problems.</em></p>
<p>There’s one thing that you can do to help Xcode in parallelizing the work: split up your targets into smaller units. One example is creating a separate testing target for each framework, instead of testing all the libraries in a single unit testing bundle.</p>
<p>You can view the dependencies of a target directly in the “Build Phases” section. Let’s take one of my side projects that I have been working on lately, <a href="https://github.com/BalestraPatrick/Tweetometer/">Tweetometer</a>. <code class="language-plaintext highlighter-rouge">TweetometerKit</code> is a framework that contains the business logic of the app, such as network requests and models. The main app target <code class="language-plaintext highlighter-rouge">Tweetometer</code> specifies <code class="language-plaintext highlighter-rouge">TweetometerKit</code> as an explicit target dependency, in order to tell Xcode that it requires the framework to be ready before it can compile itself. In the “Link Binary with Libraries”, implicit target dependencies are specified which are also used to figure out the dependency order.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/build-phases.png" alt="Build Phases" />
<em>An example of build phases that specify dependencies between modules.</em></p>
<p>If your Xcode project is a few years old and survived some refactorings, make sure you are not specifying unnecessary target dependencies that may slow down your build.</p>
<p>One last improvement in the Xcode 10 build process worth mentioning is the parallelization of some parts of the build process. Xcode starts the compilation of a target as soon as the build and the run script phases of its dependencies are complete. This means that the next target to be built will start a little bit early compared to Xcode 9, since linking and other operations can now be done in parallel.</p>
<h2 id="declaring-script-inputs-and-outputs">Declaring script inputs and outputs</h2>
<p>A run script phase allows you to execute custom code during the compilation of the target. You may have created a run script to invoke Carthage’s <code class="language-plaintext highlighter-rouge">copy-frameworks</code> script. I also use this feature in Tweetometer in combination with <a href="https://github.com/SwiftGen/SwiftGen">swiftgen</a> to generate boilerplate code to safely access Storyboards views, Localizable strings and resources stored in the Asset Catalog. A run script is always run if a list of input files is not specified, the list of inputs changes or the output files are missing.
The following run script is only executed in case <code class="language-plaintext highlighter-rouge">carthage update</code> is run and the frameworks are re-built, otherwise it’s skipped saving precious time in your builds.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/run-script-carthage.png" alt="Run Script Carthage" />
<em>A common run script required when using Carthage.</em></p>
<p>The following run script invokes <code class="language-plaintext highlighter-rouge">swiftgen</code> every time the projects builds since no input or output files are specified.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/run-script-swiftgen.png" alt="Run Script Swiftgen" />
<em>A custom run script that invokes an external tool to generate source code.</em></p>
<p>As you may have noticed from these screenshots, Xcode 10 has a new option to specify an input and output file lists. In case you have many files to list, you can do so by simply creating a <code class="language-plaintext highlighter-rouge">.xcfilelist</code> file and specify all the directories in it. You could for example set up a script to automatically update a <code class="language-plaintext highlighter-rouge">Carthage.xcfilelist</code> every time you add a new dependency in order to avoid forgetting to add a new input and output file. The format of the file is pretty straightforward:</p>
<pre>
<code>
$(SRCROOT)/Carthage/Build/iOS/Presentr.framework
$(SRCROOT)/Carthage/Build/iOS/ValueStepper.framework
$(SRCROOT)/Carthage/Build/iOS/Whisper.framework
$(SRCROOT)/Carthage/Build/iOS/Kingfisher.framework
</code>
</pre>
<p>Xcode 10 got much better in diagnosing dependency cycles in your project by giving detailed errors in the build log. A <a href="https://help.apple.com/xcode/mac/10.0/#/dev621201fb0">new guide</a> has also been published online to learn how to troubleshoot and fix a cycle.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/dependency-cycle.png" alt="Dependency Cycle" />
<em>A new error message is displayed if your build presents cycles.</em></p>
<p>Apple also released <a href="https://help.apple.com/xcode/mac/10.0/#/devc8c930575">more documentation</a> about these features and a lot of other details related to the Xcode build process (such as a <a href="https://help.apple.com/xcode/mac/10.0/#/itcaec37c2a6">build settings reference page</a> for example).</p>
<h2 id="measuring-your-build-time">Measuring your build time</h2>
<p>Xcode 10 brings some new features to identify how long each component of your project is taking to compile. In previous versions, there was no official way to know how long each file took to compile, except some third-party tools or undocumented compiler flags. Xcode now shows directly in the build log how long each file took to compile as shown in the following image.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/build-log.png" alt="Build Log" />
<em>The build now displays the compilation time for each file.</em></p>
<p>There’s also a new feature that allows you to debug and see how long each step of the build process is taking. This enables to quickly see if a run script phase is configured properly to run only when necessary. Select <code class="language-plaintext highlighter-rouge">Product -> Perform Action -> Build With Timing Summary</code> to build and see the timing summary at the end of the build log. You can also set the <code class="language-plaintext highlighter-rouge">-showBuildTimingSummary</code> parameter if you’re using <code class="language-plaintext highlighter-rouge">xcodebuild</code>.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/build-timing-summary.png" alt="Build Timing Summary" />
<em>The Build Timing Summary is a quick way to see the overall time distribution.</em></p>
<h2 id="dealing-with-complex-swift-expressions">Dealing with complex Swift expressions</h2>
<p>You may remember from your researches on how to improve the Swift compilation time about the “Compilation Mode” build setting. In some projects, setting the “Compilation Mode” to “Whole Module” resulted in faster build times with previous versions of the compiler. The Swift compiler has been now updated to be more efficient in incremental builds so this workaround is not applicable anymore. It may slow down your builds since it turns off incremental builds. Make sure to select the setting in your Xcode project and press “delete” to set it back to the default value “Incremental”.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/compilation-mode.png" alt="Compilation Mode" />
<em>The debug and release Compilation Mode build setting.</em></p>
<p>Another source of slowdown in the compilation of your Swift source code is the evaluation of complex expressions. The following is an extreme example of what you should avoid doing in your code. If you really have to write code like this, try to break it up into multiple expressions and specify the return types or local variables types manually. Including complex expressions in the ternary operator, or using very generic operators such as <code class="language-plaintext highlighter-rouge">+=</code> instead of <code class="language-plaintext highlighter-rouge">append</code> on <code class="language-plaintext highlighter-rouge">Array</code> are other examples of possible slow-downs to be aware of.</p>
<pre>
<code>
<span class="keyword">func</span> sumNonOptional(i: <span class="type">Int</span>?, j: <span class="type">Int</span>?, k: <span class="type">Int</span>?) -> <span class="type">Int</span>? {
<span class="keyword">return</span> [i, j, k].<span class="call">reduce</span>(<span class="number">0</span>) { soFar, next <span class="keyword">in</span>
soFar != <span class="keyword">nil</span> && next != <span class="keyword">nil</span> ? soFar! + next! : (soFar != <span class="keyword">nil</span> ? soFar! : (next != <span class="keyword">nil</span> ? next! : <span class="keyword">nil</span>))
}
}
</code>
</pre>
<h2 id="understanding-dependencies-in-swift">Understanding dependencies in Swift</h2>
<p>Swift doesn’t have header files like Objective-C, therefore it’s important to understand how the Swift compiler recognizes which files to recompile when a change is made. Swift supports multiple objects in the same source code file so you could define all your project’s entities in a single file if you really wanted (please don’t). The compiler tracks files and not single entities such as different <code class="language-plaintext highlighter-rouge">struct</code>, <code class="language-plaintext highlighter-rouge">enum</code> or <code class="language-plaintext highlighter-rouge">class</code>. If you happen to have a single file with 10 different entities defined in it such as a <code class="language-plaintext highlighter-rouge">protocol</code>, <code class="language-plaintext highlighter-rouge">enum</code>, <code class="language-plaintext highlighter-rouge">struct</code> and <code class="language-plaintext highlighter-rouge">class</code>, adding or removing entities in the same file or simply changing source code outside the function bodies will trigger a re-compilation of the whole file. Let’s see an example to better understand this concept.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/swift-dependencies.png" alt="Swift Dependencies" />
<em>A very simple example that shows why Swift re-compiles both files.</em></p>
<p>The file on the left defines a <code class="language-plaintext highlighter-rouge">Point</code> struct. The file on the right instead, simply defines two top-level properties which invoke the <code class="language-plaintext highlighter-rouge">Point</code> initializer. Adding the new <code class="language-plaintext highlighter-rouge">PathSegment</code> struct to the same file where <code class="language-plaintext highlighter-rouge">Point</code> is defined, will cause the Swift compiler to conservatively rebuild both files. This wouldn’t happen if the <code class="language-plaintext highlighter-rouge">point</code> constant on the right file was defined inside a function, but it’s still something to keep in mind. The Swift compiler is only able to avoid recompiling other files if your changes are confined to the function bodies. Changes to a method implementation obviously don’t affect the file’s interface but in all other cases, the compiler will trigger a recompilation of all the files that depend on it. To reduce this behavior, you should try to split up your entities in separate files. Creating a new file for each entity will not only make your incremental builds shorter but also make it even easier to find what you’re looking for in your project.</p>
<h2 id="limiting-your-objective-cswift-interface">Limiting your Objective-C/Swift interface</h2>
<p>Let’s now see how the previous concept of code dependency plays in a mixed-source target written in both Swift and Objective-C.</p>
<p>There are two types of headers:</p>
<ul>
<li>Bridging Header: collects the Objective-C interfaces that should be exposed to Swift.</li>
<li>Generated Header: collects the Swift interfaces that should be exposed to Objective-C.</li>
</ul>
<p>These files are used in order to figure out the dependencies between Swift and Objective-C. If the following Swift class is changed, it will require a recompilation of all Objective-C files that reference it for example.</p>
<pre>
<code>
<span class="keyword">class</span> EmptyStateViewController: <span class="type">UIViewController</span> {
<span class="keyword">@IBOutlet</span> <span class="keyword">var</span> messageLabel: <span class="type">UILabel</span>!
}
</code>
</pre>
<p>It is a good idea to define properties or functions which are exposed to Objective-C by default as <code class="language-plaintext highlighter-rouge">private</code>. This also benefits the encapsulation of your code since no other object in the same module will be able to modify the <code class="language-plaintext highlighter-rouge">messageLabel</code> by mistake.</p>
<p>One last build setting to check in your target is the “Swift 3 @objc Inference”. You may not even know about this build setting at all because it was created automatically during the Swift 4 migration performed by Xcode. This behavior caused every property in an <code class="language-plaintext highlighter-rouge">NSObject</code> subclass to be exposed to Objective-C in the Generated Header. You should now set the build setting to the default value by pressing “delete” on it. If your project fails to compile since Objective-C can’t find a method defined in Swift, simply add <code class="language-plaintext highlighter-rouge">@objc</code> to the function declaration in order to comply with the new Swift 4 behavior.</p>
<p><img src="/assets/blog/improving-your-build-time-in-xcode-10/objc-inference.png" alt="Objective-C Inference" /></p>
<p>I hope this post was useful and will save some time to your Mac’s CPU with the upcoming Xcode 10 update.</p>
<p>Feel free to <a href="https://twitter.com/BalestraPatrick">tweet me</a> with any questions or comment. 👍</p>
<p>P.s: all Swift snippets in this post have been generated with <a href="https://github.com/johnsundell/Splash">Splash</a>, a new Swift syntax highlighter just open-sourced by my friend John Sundell. Check it out!</p>Patrick BalestraI finally had time to watch some of the WWDC talks related to Xcode 10 today, and I wanted to share some very interesting and useful new tips to improve the build times of Swift and Objective-C projects in Xcode 10.My Tech Interviews Experience&#58 Failures, Successes and Tips for you2018-08-06T00:00:00+00:002018-08-06T00:00:00+00:00https://balestrapatrick.github.io/blog/2018/08/06/my-tech-interviews-experience<p><img src="/assets/blog/my-tech-interview-experiences/header.jpg" alt="The Climb to Success" />
<em>The climb to your next job.</em>
I have spent the last 3 years studying informatics at the University of Lugano where I recently graduated with a Bachelor degree in Science of Informatics.
I also interned at different companies as an iOS engineer for the last four summers. In this post I am going to explain my process of finding my first full-time job as an iOS engineer, explaining it step by step. I will also give advice on what I learned by interviewing at some of the top tech companies, in order to help you prepare for your next interview.
<!--more--></p>
<p>⚠️ I’d like to highlight that what I am going to describe in this post is based on my personal experience. You may find some of my assumptions don’t apply to you or maybe a different approach would work better in your specific case. I really hope everyone will be able to get some interesting and useful points out of this post independently from their experience or location.</p>
<p><strong>Table of Contents:</strong></p>
<ul>
<li><a href="#find-your-opportunity">Find Your Opportunity</a></li>
<li><a href="#your-cv-and-experience">Your CV and Experience</a></li>
<li><a href="#use-your-network">Use Your Network</a></li>
<li><a href="#how-to-prepare">How to Prepare</a></li>
<li><a href="#dealing-with-rejections">Dealing with Rejections</a></li>
<li><a href="#be-brave">Be Brave</a></li>
<li><a href="#interview-process">Interview Process</a></li>
<li><a href="#my-personal-experience">My Personal Experience</a>
<ul>
<li><a href="#facebook">Facebook</a></li>
<li><a href="#google">Google</a></li>
<li><a href="#apple">Apple</a></li>
<li><a href="#spotify">Spotify</a></li>
<li><a href="#deliveroo">Deliveroo</a></li>
</ul>
</li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
<h2 id="find-your-opportunity">Find Your Opportunity</h2>
<p>Depending on the country and type of job you’re looking for, various resources exist to discover new positions. I usually start with a Google search for the name of the position and location and often end up on <a href="https://www.glassdoor.com/">Glassdoor</a>, <a href="http://indeed.com">Indeed</a>, <a href="https://angel.co">Angel</a> or similar websites. This is a great starting point if you’re not really sure which companies are looking for a person with your skills or if you’re not really selecting your next job based on specific criteria.</p>
<p>What I usually do is focus on a few companies that I am really interested in. An important factor for me is to enjoy the product I am working on and to use myself every day, in order to maximize the personal reward of contributing to it. Focusing on a few companies gives you the chance to carefully manage your resources and adapt to their recruiting process. Interviewing is a very time-consuming task because you’re either writing or answering emails, building your portfolio, doing research or studying for your next interview.</p>
<p>In my opinion, you will have a greater chance of getting a job if the company sees passion in your application instead of just randomly sending your CV.</p>
<p>There are generally two ways to apply for a job:</p>
<ul>
<li>Apply to the job posting online, either on the company’s website or on an external website.</li>
<li>Apply through a current company’s employee (aka as a referral). This is generally the best option if you see a job posting on Twitter or other social media.</li>
</ul>
<p>The only difference between the two ways is that being referred usually leads to a secure first interview round. If you apply through the website, the company may receive hundreds or thousands of applications and a recruiter will have to select only a subset of the applicants to start the interview process.
Knowing someone at the company allows you to ask for more information about the company culture and structure before applying to the job, which gives you a better idea of what to expect regarding the interview process and the company itself.</p>
<p>Attending conferences and meetups is a very effective way to meet new people and learn more about other companies and possible jobs. LinkedIn can also be useful to find jobs or get in touch with recruiters. You could search “recruiters who work at Google” and you should be able to get in touch with people who can help you. Recruiters use LinkedIn to try and fill their open positions, so you can help them and directly get in touch. Write a message to explain why you would like to work for the company and why you would be a great fit for them. If they think you could be a great fit, send them your CV and you should start your interview process soon.</p>
<h2 id="your-cv-and-experience">Your CV and Experience</h2>
<p>You should take some time to write a clean CV that showcases what you have done in the past and which technologies you have experience with. Build a simple and clean design with Pages if you don’t know where to start. It may take you multiple iterations to get it right, but it’s the content that really matters. Some people even A/B tested their CV to find the combination that makes the best impression. Feel free to take a look at my CV available <a href="/CV.pdf">here</a> if you need some inspiration.</p>
<p>If it makes sense, think about customizing your CV for a specific company or team. If you’re applying for a position where maintaining open-source projects is important, you may want to list yours to show that you match their requirements. In the past, I have customized my CV for a position on a very specific team at Apple to show that I previously worked with the APIs they build.</p>
<p>To speed up the process of writing an efficient CV, you can ask for feedback to friends you trust. Before starting to apply for a full-time job, I asked for feedback to most of my previous experienced managers. If you don’t know anyone who is willing to review yours, you can join the <a href="https://www.facebook.com/groups/1487708811477672/">HH Websites and Resumes</a> Facebook group where almost 20,000 members review each other’s CV and websites before applying for jobs. If you don’t know where to start writing your own, this group is also a good place to get inspired. Feel free to <a href="mailto:me@patrickbalestra.com">email me</a> with your CV if you need feedback and I will try my best to get back to you as soon as possible.</p>
<p>Let me also tell you a short story about the most random CV review I ever received: I was at a WWDC party in 2017 where I met an Apple engineer and we started talking. I told him I was soon looking for a job after graduating from university but I still had to improve my CV and website before applying for jobs. He gave me some tips on what to add to the CV since he knew what Apple recruiters look for. I showed him mine on my iPhone and he pointed out a few improvements I could make to increase my chances of being noticed by the recruiters. Always be open for feedback even in the most random situations!</p>
<h2 id="use-your-network">Use Your Network</h2>
<p>Your network can make a big difference while looking for a job. What helped me a lot in my job search is my presence in the community. I started a few years ago by being active on Twitter and contributing to the open-source community with a couple of projects. I’ve been involved in running two different conferences where I had the opportunity to meet a lot of speakers and attendees. Exposing yourself to the community will take some time and effort but it can definitely increase your chances of a successful career in my opinion. Please refer to the great talk by Peter Steinberger on <a href="https://www.youtube.com/watch?v=0c6izSzP-KQ">how to build a personal brand for introverts</a> if you want more information on the topic.</p>
<p>Companies receive a lot of applications every day through the application form online. It’s always difficult for the recruiter or engineer who will do the initial screening to notice the right people when just looking at their CV. For this reason, you should try your best to be noticed in a different way. Think outside the box. Send an email to the company or one of your friends who works there to demonstrate your interest in them. That shows that you’re willing to do much more than just send your CV online like everyone else does.</p>
<p>Check out <a href="https://twitter.com/bainboozled">Jessica Bain</a>’s creative way of getting noticed by Spotify which landed her the job in exactly one month.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Hey <a href="https://twitter.com/Spotifyjobs?ref_src=twsrc%5Etfw">@Spotifyjobs</a>! I heard you were looking for a Black History & Culture fellow, so this is me shooting my best shot✊🏾 RT to help them see this! <a href="https://t.co/eh8z1XY5Xt">https://t.co/eh8z1XY5Xt</a> <a href="https://t.co/2vyzox46pi">pic.twitter.com/2vyzox46pi</a></p>— Jessica Bain (@bainboozled) <a href="https://twitter.com/bainboozled/status/988234731732045824?ref_src=twsrc%5Etfw">April 23, 2018</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<h2 id="how-to-prepare">How to Prepare</h2>
<p>Depending on the company and position you’re looking for, you will need to adjust your preparation based on their expectations. First of all, you can start by collecting information on the interview process of the company. Their recruiters will most likely give you all information you need, but if the company is big enough, you may be able to find more details online in blog posts or articles. Glassdoor collects <a href="https://www.glassdoor.com/Reviews/index.htm">interview reviews</a> from past interviewees that can help you gain more insights on the process.</p>
<p>If your goal is to join a big company, you will definitely need to learn some computer science fundamental concepts. Depending on your previous experience and knowledge, you may want to start by reading the book <a href="http://www.crackingthecodinginterview.com"><em>Cracking the Coding Interview</em></a>. It explains in more detail the processes and questions to expect in this kind of interviews. Reading the book is useful to get a general idea on what to expect. If there’s one thing you should remember from this post, it’s the following: <strong>interviewing is a skill</strong>. You can be the best engineer on the planet and still fail every whiteboard interview. This is because there are a lot of skills required to be successful in this specific interview set-up. Interviewing is a stress exercise where you are asked to solve an unknown problem by speaking loudly and code a solution at the same time with someone constantly looking at you for 45 minutes. What could be more stressful than that?</p>
<p>You should take every opportunity you have to practice your interviewing skills.
First of all, start practicing on a website like <a href="https://leetcode.com">LeetCode</a>, <a href="https://www.interviewbit.com">InterviewBit</a>, <a href="https://www.interviewcake.com">Interview Cake</a> or <a href="https://www.geeksforgeeks.org">GeeksforGeeks</a> to practice solving exercises related to algorithms and data structures. I bought the LeetCode premium subscription for a month to be able to run my code faster and select questions based on the company who asked them. Do as many exercises as you can and spend at least 30 minutes thinking about each possible solution. If you can’t figure it out, look at the tips and discussions to understand a possible solution. Repeat this process for as many problems as you can to train your problem recognition skills. This is the part that allows you quickly find the most appropriate tool to solve a problem.</p>
<p>I would be lying if I said I didn’t hate studying this way. Every time I had some free time, I had to choose between studying algorithms or working on some cool side projects. I could have studied a lot more than I actually did, but looking for a job while simultaneously attending a university full-time with a part-time job really limited my free time. My advice would be to start studying a few months before your first interview or to take a few weeks off to completely focus on this project.</p>
<p>You can start practicing for interviews even before starting to apply for positions. The more techniques you know for solving problems, the better you’ll perform. After practicing for a while, you may be able to solve some problems efficiently. You should now make sure you can solve the same problems in a stressful environment. <a href="https://www.pramp.com/">Pramp</a> makes it very easy to practice by reproducing a similar scenario to the first interview round at Google, Facebook and Apple, just to name a few. Pramp is a free website that matches you with another developer who is practicing exactly like you are doing. After scheduling a time for your interview, you will receive the question to ask to your peer. They will also receive a question to ask to you. When the interview starts, a video call will start with a shared text editor and the question details all in one screen. You even have hints that you can give to your peer to perfectly simulate what a real interview looks like. This is great to practice talking to your interviewer through your solution while coding at the same time, which is a non-trivial skill to have. When I first started interviewing, I couldn’t think deeply about the problem while speaking. Again, this is a skill that you can train by practicing over time. There are other similar services that match you with a real experienced engineer that could give you better advice, but those are usually paid services and not available in all countries. Two examples are <a href="https://interviewing.io">interviewing.io</a> and <a href="https://careercup.com/interview">career cup</a>.</p>
<p>You would think that starting to interview with the companies that you like the most would be a good idea, but I would argue against it. Start with the companies that you like the least to gain some experience. After you feel more confident and with some interviews under your belt, you should be more comfortable to take on the companies that matter the most to you.</p>
<p>Everything I have described so far is very focused on algorithmic questions, which are very common in big companies. Smaller companies usually don’t require such knowledge and prefer to test candidates on domain-specific knowledge. If you’re interviewing for an iOS position, you will be asked about Swift and Objective-C features. I personally start by doing some research about common questions and pitfalls to avoid. I can then focus in specific areas by reading books or interesting blog posts.</p>
<p>Check out Andyy Hope’s great <a href="https://medium.freecodecamp.org/software-engineering-interviews-744380f4f2af">article</a> on how he got his developer job at Facebook where he talks more about his preparation process for whiteboard interviews.</p>
<h2 id="dealing-with-rejections">Dealing with Rejections</h2>
<p>You will be rejected by companies during your career almost assuredly. I’ve been rejected countless times for jobs that I really wanted and I know how it feels. I really wanted to work for Spotify for a few years. I tried applying to their internship programs in 2016 and 2017 but I wasn’t even selected for the first round of interviews. Google, Facebook, Apple, and Twitter rejected me, some even multiple times. What matters is that I persisted and took those rejections as a learning opportunity. Interviewing is a skill that you have to train over time, exactly like programming. Continue to improve yourself by doing what you love every day. Each company has a different way of hiring and testing engineers, and it will take you some practice to understand what they expect to see in candidates. Take every chance you have to interview and improve yourself because very few people succeed on the first try.</p>
<p>It’s easy to forget all the failures and struggles that successful people encountered throughout their career. A great example is the resume of failures by <a href="https://blog.jisungkim.com/effortless-perfection-a-resume-of-failures-69909810216">Ji-Sung Kim</a> which strikes the successes and highlights the failures and struggles to see what took him to get to the point where he is today. Take every failure as a learning opportunity and continue to improve.
<img src="/assets/blog/my-tech-interview-experiences/ji-sung.jpg" alt="Ji-Sung Kim" /></p>
<h2 id="be-brave">Be Brave</h2>
<p>There have been many discussions recently about companies not offering positions for junior developers, which in my experience is true. If you look at the careers page of most companies nowadays, very few mention jobs for junior engineers. Job titles are fictitious because they vary a lot between companies and countries. Internships may be your best bet in getting a pretty good job with low entry barriers and they look very good on your CV. If the company is happy with your work, they will most likely offer you a full-time job since it’s hard and expensive to find tech talent these days.</p>
<p>Apply to positions where you don’t fulfill literally all the criteria listed on the description. If a job position lists as skills requirements Swift, Objective-C and React Native and you’ve never wrote a project in React Native but you still know your way around JavaScript, you should still apply. Reach out to them by saying you’re experienced in Swift and Objective-C and would love to pick up React Native and because of your existing mobile development experience. It won’t be that difficult to learn a new mobile technology for you. Similarly, if a job position requires two years of professional experience in iOS development but you have already shipped a couple of apps to the store and have a few previous internships, you should still try to apply or get in touch with them. Don’t be scared to get in touch with a company to ask for more information, most of them will appreciate your interest.</p>
<p>For example, last summer I wanted to work at N26 because I really liked the company’s app and I wanted to experience the fintech world. I didn’t know anyone working at the company and they didn’t have any internship positions listed on the website. I tried applying to the full-time iOS engineer position on their website and the recruiter immediately reached out to schedule the first call. At that point I explained my situation and asked if they would be able to hire me as a summer intern instead. They hadn’t yet internally discussed the idea of having an intern so that’s why the position wasn’t available. They liked the idea and after the interview process I was offered an internship position for the summer.</p>
<h2 id="interview-process">Interview Process</h2>
<p>Depending on the company you’re interviewing at, the process may be very different. Here is a small list that tries to summarize the process by size of the company. Obviously, there are exceptions: I will soon describe how my interview process was at various companies to give you some real-world examples. The process may look like some variant and mix of one of the following:</p>
<ul>
<li>Small company (< 100 employees): a small team usually needs people who can get the work done. You may be asked to complete a take-home project and show it off in a video call. The video call is usually with an engineer of the company whose task is to asses your knowledge by asking various quiz questions to see if you have the knowledge required for the position you’re applying to. Depending on their culture and resources, they may choose to invite you for an on-site interview: on that day, you may meet the team and managers in person. This gives the team the opportunity to assess if you fit the company’s culture. Some more interviews regarding your specific knowledge (iOS development, Android development, JavaScript, etc.) can take place, but very rarely you’ll be asked to code a solution to a complex algorithmic problem on a whiteboard.</li>
<li>Medium-size company (< 500 employees): the interview process with these type of companies may consist of 3-4 steps. You first get introduced to the company with a recruiter call that doesn’t involve any technical questions and only describes the overall process. After that, the technical process starts with a 45-90 min call with an engineer. Depending on the company, you may be asked some quiz questions to check if you have the knowledge required for the specific position. A practical exercise to be solved in a shared code editor or by screen sharing is often employed in this interview. The next step is the onsite interview where the interviewers will ask more in-depth questions in regards to your experience. All companies of this size usually have the resources to fly you out to their office. This is an amazing opportunity to meet the team and impress them with your best skills during the last round of interviews.</li>
<li>Big company (>500 employees): big companies interview candidates in many different ways. It’s also possible to see different interview processes inside the same company. This is why there’s usually an introductory call with the recruiter who illustrates the process. In my experience, there’s always at least an algorithmic coding problem to solve over a live call with an engineer to begin with. If that step goes well, you’re usually invited for the on-site interview at the company’s office. Since every big company has specific processes and resources allocated, they will usually book flights and a hotel and reimburse you a fixed amount per day of travel. The on-site interview consists of 4-5 interviews in a single day with different engineers and managers. Lunch is also provided to network with employees and ask as many questions as you’d like, to get to know the team or company in details. The interviews are most likely focused on algorithmic problems and computer science fundamentals. You could be asked to bring one of your projects to present to the team, so that they can see how you explain your code in a clear and concise way to other people. A cultural fit interview is also mandatory where one or two managers will ask about your previous experience in working with other people. This is usually the easiest part of the process where you just have to make sure that you can tell a few stories on how you performed by working in a team. If you don’t have such stories, the interviewers may ask you to imagine you’re in a situation they describe and explain how you would behave.</li>
</ul>
<p>The recruiter should get back to you with the next steps a couple of days or weeks later. I received interviews feedback and offers both via phone call and email, so every company does it differently.
Some companies will also refuse to give you feedback about your performance because of lack of time or possible lawsuits against them (especially in the U.S.). Other companies instead will give you a detailed feedback encouraging you to try again in a couple of months. In case of an offer, you can now proceed to negotiate your compensation and benefits or choose the exact team you will join. There are plenty of great resources online on how to properly negotiate the offer, so don’t underestimate this step and do some research before accepting the offer.</p>
<h2 id="my-personal-experience">My Personal Experience</h2>
<p>I will now describe what my process looked like in the first half of 2018 when I started looking for my first full-time job. My graduation was planned for June 2018 but I wanted to take the summer off and start the new job in September 2018.
I began my process in October 2017 by updating my CV and website to make sure all my information was accurate and up-to-date. I knew it was still early to look for a job with my late starting date and a couple of companies specifically asked me to get back to them again in a couple of months. After taking note of each company’s requirements and policy, I was able to adapt my job hunting timeline.</p>
<p>I wanted to work in a big engineering team as my first full time job. I have already experienced the small and medium size companies at Scandit, N26 and BCG Digital Ventures, and I wanted to try something different this time. I also think that as a new graduate, the more people you get to work with, the more you may be able to learn. Bigger companies also have processes and resources in place to properly train new employees.</p>
<p>I started my job hunting process by creating a spreadsheet with the name of the companies I wanted to work for and some information regarding at which step of the process I was.</p>
<p><img src="/assets/blog/my-tech-interview-experiences/job-hunting.jpg" alt="Job Hunting Spreadsheet" />
<em>My initial job hunting spreadsheet quickly written in Numbers.</em></p>
<p>After the spreadsheet was done, it was time to get to work: reach out to the companies. I reached out to the companies by either applying on their website or by contacting a friend who worked there. By contacting someone on the inside, I was able to ask for more information about the position and culture of the company. After considering the details of each position and its location, I decided to apply by sending my CV to their recruiting team.</p>
<p>I will now describe the interview process for some of the companies I interviewed at in the last couple of months. For each of them, I will describe my personal experience along with some of my thoughts. The experience in interviewing is very personal and it really depends on your recruiter, interviewers and a lot of other factors.</p>
<h3 id="facebook">Facebook</h3>
<p>I still wasn’t done with my internship last summer when I was offered a referral by a former friend who was a Facebook employee at the time. I was planning on starting to study and practice for algorithmic interviews a few months later, but I decided to still give it a try even though I wasn’t feeling confident. Since interviewing is all about practice, I took this opportunity as an exercise to learn more about the process and gain some insights on the type of questions asked. The first call was with a recruiter who explained me the process and asked for a few dates I was available to schedule the next step. It consisted of solving some algorithmic problems on <a href="https://coderpad.io">CoderPad</a> while talking to the interviewer over a phone call. In my case it consisted of two problems but depending on the time it takes to solve them, there could also be some follow-up questions to improve the efficiency or extend the solution to cover more use cases.</p>
<p>The important skill that I tried to put in practice in this first coding interview is the “think and explain” process. One of the most important things to do during an interview is to explain your thought process while coding at the same time. You have to be able to communicate your ideas clearly to allow your interviewer to understand your solution. I was able to correctly understand the problem and code a solution but I didn’t get to the most efficient solution in time. A few days later I received an automated rejection email which didn’t contain any explanation. This is pretty common especially if rejected in the first stages of the process.</p>
<h3 id="google">Google</h3>
<p>A Google recruiter got in touch with me around September 2017 because the Zurich office was organizing a rather interesting event called Google Backstage in December 2017. Their intro email also mentioned where they found my contact which is something that recruiters usually don’t disclose. They used <a href="http://git-awards.com">Git Awards</a> to find out the most popular GitHub users in Switzerland to invite to this event.
The event was very interesting and Google invited about 30 engineers to learn more about the interview process at Google. I think that that Google realized how hard it is to hire engineers with their current process and they’re trying to help candidates get familiar with it to make them feel more comfortable. There were a few talks during the morning explaining how to succeed in Google interviews. After having lunch with some engineers, the afternoon was spent conducting a mock interview. Each candidate was interviewed by a Google engineer for an hour as if it were a real interview. I tried to put in practice all the advice received and the interview went better than I expected. I was lucky enough to be invited for a real onsite interview a few weeks later. The day at the Zurich office consisted of 4 interviews: 2 about algorithms and data structures and 2 about iOS skills, which where specific to my experience. All Google recruiters were incredibly helpful and supportive and I felt encouraged to succeed at all times. Two interviews were conducted remotely because of some last-minute unavailability so they took place over Google Hangouts. I later had lunch with an engineer who answered all my questions about the culture and benefits of the company. I enjoyed the interviews but the difficulty was definitely the hardest I ever encountered in a tech interview.</p>
<p>A couple of days later, the recruiter reached out via email to schedule a call to discuss the feedback of the interviewers. She explained for each interview what the interviewers liked and what I should do next time in order to give a better impression. It was the best and most accurate feedback I ever received and I loved that they took the time to provide it to me. Every interviewer writes their own feedback and sends it to the final committee which makes the “hire” or “no hire” decision. In some cases, more interviews may be required to make a final decision. All companies obviously gather detailed feedback regarding the performance of each candidate, but very few make the effort to let the candidate know about it. <strong>Receiving feedback is definitely one of the advantages that may persuade a candidate to re-apply to the same company a couple of months later. Don’t leave your candidates clueless about their performance results. Treat them with the due respect by providing feedback for the time they have invested in your process.</strong> Props to Google for their great process.</p>
<h3 id="apple">Apple</h3>
<p><img src="/assets/blog/my-tech-interview-experiences/apple-park.jpg" alt="Apple Park" />
<em>Apple Park in Cupertino.</em>
Apple hires in a very different way compared to other companies. You interview for each specific team which would like to hire you. Interviewing with two different teams at the same time is completely normal. Instead, most other tech companies have a single hiring process and the candidate can discuss which team to join towards the end of the process. Because of this difference, each team at Apple can have a different hiring process.
I was referred by a friend I met at a conference a couple of years ago. The first call was the usual introductory call with the recruiter. It was followed by a technical interview over the phone with an engineer on the team. Various technical questions about my previous iOS experience were asked but no coding was involved. I found this a great way to actually assess the knowledge required for the job I was being considered for. I was flown out to Cupertino in all-expenses paid trip a couple of weeks later, including Lyft vouchers to make the trip as smooth as possible. I spent 5 days in Cupertino including a full day consisting of 4 interviews and lunch at Apple Park. The building is incredible and something that you can experience only by walking inside yourself.</p>
<p>I was first welcomed by the recruiter who walked me through the schedule of the day and made sure she knew exactly my expectations such as location of work and other details in case of an offer. The interviews were very broad in topic and included iOS knowledge discussions, Objective-C pair-programming and two whiteboards interviews about computer science fundamentals and algorithmic questions. I found the algorithmic questions a little bit easier compared to Google and I was pretty happy with my performance. It felt good to see some progress on my interviewing skills after practicing for a while and failing the Google onsite.
My recruiter unfortunately wasn’t very responsive during the whole process and after about a week of patiently waiting, I reached out asking for feedback about my onsite. She answered by saying that I wasn’t a good fit for the team but she would be happy to look into other teams at Apple. (Remember how their hiring process works.) I asked that I would be happy to receive some feedback if possible and learn more about the opportunities in other teams. The recruiter simply disappeared and, after sending 3 other emails over the following 3 weeks, I finally gave up. I spent 5 days and 30+ hours travelling for this job opportunity and to be ignored or forgotten was very disappointing.</p>
<h3 id="spotify">Spotify</h3>
<p><img src="/assets/blog/my-tech-interview-experiences/spotify-hq.jpg" alt="Spotify HQ" />
<em>The newest Spotify’s HQ in central Stockholm.</em>
Since the beginning of my job-hunting process, Spotify was the top choice as a place to work in Europe. I’ve been a huge fan of the company and its product for a long time and the company’s culture seemed amazing from what I learned by some previous employees I met.</p>
<p>A friend referred me for the position very early in my job hunting process and the recruiter was very nice, telling me to reach out in a couple of months to start the actual process. The initial call with the recruiter illustrated me the whole process. The first technical interview was a 90 min call with two engineers who asked about 20 quiz questions in the first part of the call. The second part consisted of a technical task to be completed by sharing my screen and coding directly in Xcode. Everything went well and I moved onto the next step which consisted in a 60 min cultural fit interview with two managers. I was then flown out for the on-site interview in Stockholm where my trip was paid for by the company. The onsite consisted of 3 interviews from 9:30 AM until 2 PM. Every interviewer was very friendly and I got the feeling that everyone really enjoyed their work there. The first interview consisted in me presenting the source code to one of my previous projects. It took me some time to prepare a presentation and practice how to best explain it. I really liked this format compared to that at other companies where completing a take-home project is mandatory to proceed to the next step. The company can also have a better idea of your coding skills by seeing how you maintained a non-trivial project over time. The second interview was again a cultural fit interview with a different manager this time. Lunch was brought into the office and I had the possibility to meet some employees to learn more about living in Sweden and their current work. After lunch, the last interview consisted in solving an algorithmic problem on the whiteboard. The question was of medium difficulty and I was able to solve it this time. After the interview was over, I realized that, thanks to my practice, I immediately recognized the data structure required to solve the problem in an efficient way. The interview process was very well organized and I had a lot of possibilities to ask questions and learn more about the company. I received an offer a few days later via email for a position in Stockholm.</p>
<h3 id="deliveroo">Deliveroo</h3>
<p>Deliveroo is one of the very few companies that exactly describes their interview process on their <a href="https://deliveroo.engineering/2017/11/23/engineering-interviews.html">engineering blog</a>. This is great since the candidate has the chance to discover the process ahead of time and it avoids wasting everyone’s time. You can read their blog post to see in details what the interview process looks like, but I will summarize it for you since it’s a little bit different from the other companies I described so far. There is no phone screening or initial interview, just a recruiter call. The first task is to complete a take-home project and submit it to the team a few days before the onsite. The project isn’t used as a screening step like many other companies do. After agreeing to the completion of the project, the onsite interview is scheduled and the project has to be completed before the onsite at a time it best fits the candidate. Once completed, the interviewers will receive it and can then prepare the interview. During the onsite interview, the candidate is asked to make some improvements and explain the project. This is an amazing opportunity to better explain the choices face-to-face for the candidate. Take-home projects are often misjudged since a new developer has to look at the codebase for a short amount of time and decide if it’s good enough to proceed to the next step. This doesn’t give any possibility of interaction or explanation to the candidate. The on-site interview consisted of the following three interviews: a cultural fit interview with a manager, an interview focused on the take-home project and one testing the iOS knowledge. After the on-site, a call with the manager of a specific team was set up to further discuss the type of work they do. A couple of days later I received an official offer. The overall process was very smooth and fast. The fact that the coding challenge project isn’t a prerequisite to proceed to the onsite interview, makes it a lot more comfortable for candidates to spend time on the take-home.</p>
<h2 id="conclusion">Conclusion</h2>
<p>While looking for a job has definitely been a very stressful process, I am happy that I took the time to prepare as much as I could. I did a lot of research for each company to better gain insights on the interview process which definitely helped me in preparing in an effective way.</p>
<p>Interviewing for a job may be one of the most nerve-racking tasks you will be faced with during your career, but it will get easier as you improve your interviewing skills and network hopefully.</p>
<p>I am excited to have accepted a job as an iOS Engineer at Spotify and I am moving to Stockholm in September. Working at Spotify is a dream come true for me. 🎶🚀✨</p>
<p>I hope that this post may be able to help you and make it a little bit easier to prepare for your next job.</p>
<p>If you got it here, thank you very much. Just so you know, this post was longer than my bachelor thesis. I would also like to thank all my friends who helped me proofread this article.</p>
<p>As always, <a href="https://twitter.com/BalestraPatrick">tweet</a> or <a href="mailto:me@patrickbalestra.com">email</a> me any feedback or questions that you may have.</p>Patrick BalestraThe climb to your next job. I have spent the last 3 years studying informatics at the University of Lugano where I recently graduated with a Bachelor degree in Science of Informatics. I also interned at different companies as an iOS engineer for the last four summers. In this post I am going to explain my process of finding my first full-time job as an iOS engineer, explaining it step by step. I will also give advice on what I learned by interviewing at some of the top tech companies, in order to help you prepare for your next interview.WWDC 2017 Organizational Thoughts2017-06-11T13:41:28+00:002017-06-11T13:41:28+00:00https://balestrapatrick.github.io/blog/2017/06/11/wwdc-2017-organizational-thoughts<img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc1.jpg"/><p>I attended WWDC 2017 on a student scholarship this year. I had the possibility to attend it in San Francisco back in 2014 too. Now that I am back home and I have the time to reflect on the week I spent with the best Apple minds, I found some interesting differences between how the two conferences were organized.</p>
<p>As a conference organizer myself, I know how much work goes into making such an event happen. I always appreciate when people give feedback about <a href="https://appbuilders.ch" target="_blank">App Builders</a> and <a href="http://theswiftalps.com" target="_blank">Swift Alps</a>. It’s important to keep improving future events for everyone!</p>
<p>First of all, I would like to thank the whole Apple team that was able to do an extraordinary job in planning the conference. Every staff member was always nice, polite, and super helpful.</p>
<p>This is a very personal opinion and other attendees will have a different opinion for sure. Happy to hear other takes on everything I am going to list!</p>
<p>I would like to write about what I liked and what could be improved in the future editions. Sorry Apple people, but I couldn’t find the WWDC category in radar, so here I am! 😉</p>
<ul><li><strong>Pins</strong>: pins were definitely one of the highlights of the conference. We were given a set of 6 random pins when checking-in. Together with the WWDC 2017 Levi’s jacket, a country pin was also available for the attendees to collect. <a href="https://twitter.com/nicorsm" target="_blank">Nicola Giancecchi</a>, also a scholarship recipient, lives in San Marino (the 4th smallest country in the world with only 31,781 people) and I was surprised to see they printed his flag too! 🇸🇲
<img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc2.jpg"/><p>During the conference, some Staff members were distributing new special pins. That was a really nice touch.</p>
<p>Soon the exchange market started. A really nice way to bring the community together.</p></li>
<li><strong>Staff</strong>: As mentioned before, the Staff was very helpful in every occasion. They had explosive-sniffing dogs for the whole week inside and outside the convention center (with even their own dub dub badge) and they were happy to have people pet them. </li>
<img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc3.jpg"/><li><strong>Keynote</strong>: I was a little disappointed to see nobody distributing coffee or food while in line. This was most probably because in San Jose there are fewer companies looking to promote themselves. In 2014, companies were distributing free food and drinks to help kill the time and promote their company while the attendees lined up during the night. As students, we were told to be in the convention center by 8.15 AM to be able to enter our reserved area. I was in line since 4.30 AM but surprisingly our reserved sector was the second one (> 25th row). A few friends and I joined another friend in the 7th row to have a better view though 🙃
<p>Security for the keynote was very fast, just a quick bag check and metal detector for everyone.</p></li>
<img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc4.jpg"/><li><strong>Food</strong> was very disappointing. The 2014 catering in Moscone Center had many more choices for breakfast (the more 🍩, the better). Box lunch was very disappointing. Almost the same burrito box every day. Some sandwiches were also available but calling “italian”, a sandwich with multiple 2cm pieces of onion inside it is way too much for my taste. 🙈
<p>I know, it’s very difficult to feed 5k developers in a very short amount of time, but more quality could go into the food in my opinion. Nonetheless, I had the opportunity to explore a few food places in San Jose.</p></li>
<li><strong>Music</strong> in the breakfast and lunch room was a little bit boring. Only 4-5 songs were playing all day. It was supposed to be a background music for people to be able to work, but after a few days I couldn’t stand the music anymore. More songs would have helped a lot. 😬</li>
<li><strong>Wi-Fi</strong> was a little bit disappointing. For most of the conference, it was unusable. So unusable, that when I was told to file a radar, bugreport.apple.com didn’t even load 😭
<p>I think a better Wi-Fi would benefit everyone, but again, having 5k developers in the same building makes the IT team very sad.</p></li>
<li><strong>Bash</strong>: I loved the Bash. The new location was huge and it felt like being at a real music festival for one night. In 2014, students who weren’t allowed to drink were located on the terrace of the Yerba Buena Gardens. Good landscape for sure, but impossible to interact with other 21+ attendees. Food was better in this case, a lot more choice than lunch. A few social games were also available to play during the party. A very nice idea 👍</li>
<img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc5.jpg"/><img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc6.jpg"/><img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc7.jpg"/><li><strong>San Jose</strong> has very few people in the streets at all times. It felt like a ghost town. The weather was definitely an improvement over San Francisco, but in contrast San Jose had less choices of places to go.</li>
<li><strong>Convention Center</strong>: I loved the convention center. The outdoor location in front of it was spectacular. Having lunch with the sun shining instead of being in dark room with everyone on their computers was a big improvement. The hallway was actually smaller than Moscone Center and this caused some issues when many people queued up for the same session. The entrance for the lunch room was blocked sometimes but the staff managed that pretty well. Shortly said, big 👍 for the same location in the future.</li>
</ul><img src="/assets/blog/wwdc-2017-organizational-thoughts/wwdc8.jpg"/><p>I hope you enjoyed my short report about WWDC 2017 whether you were there in person or followed it from your comfortable home. If you were there, please share your thoughts about the conference, I would love to read other attendee’s opinion.</p>
<p>I would like to thank everyone again, I met a lot of amazing people thanks to WWDC. I can’t wait to experience it again in the future! </p>
<p>Thanks to <a href="https://twitter.com/a2" target="_blank">Alexsander Akers</a> for proof-reading. </p>Patrick BalestraI attended WWDC 2017 on a student scholarship this year. I had the possibility to attend it in San Francisco back in 2014 too. Now that I am back home and I have the time to reflect on the week I spent with the best Apple minds, I found some interesting differences between how the two conferences were organized.How to Improve Your GitHub README2017-01-28T09:04:37+00:002017-01-28T09:04:37+00:00https://balestrapatrick.github.io/blog/2017/01/28/how-to-improve-your-github-readme<p><meta content="width=device-width, initial-scale=1.0"><meta><link rel="stylesheet" type="text/css" href="css/style.css"></p><p>I spend quite some time browsing GitHub every day. I use the <a href="https://github.com/trending" target="_blank">Trending</a> section to filter the projects by language. I then proceed to explore each project by reading the README and maybe browsing the code, some issues and pull requests to see how the project is being maintained. The community is creating an immense number of projects and it’s one of the things I like the most about the Swift community. </p>
<p>By browsing new open source projects almost every day, I noticed that many of them don’t take full advantage of some cool Markdown features. The README is the first thing that people see when approaching your repository. If you want to attract users, contributors or simply interest, it is crucial to give them the best possible first impression. In this post, I would like to show some tips and tricks to take your README to the next level.</p>
<p>This post is focused on Swift but many of the following points can be applied to any other language.</p>
<h3>Syntax Highlighting </h3>
<p>This is a very simple feature that you can add to your code snippets. GitHub uses <a href="https://github.com/github/linguist" target="_blank">Linguist</a> to do the syntax highlighting and automatically set your repo language. Just add the language name after triple backticks.</p>
<pre>
```swift
print("Hey")
```
</pre>
<p>The result will be much easier to read and understand.</p>
<h3>Spoiler Effect</h3>
<p>Markdown doesn’t provide a lot of features to make text interactive but we can use some supported HTML tags given that GitHub uses what’s called “<a href="https://help.github.com/categories/writing-on-github/" target="_blank">GitHub Flavored Markdown</a>”. I recently discovered this feature after using fastlane which heavily uses it to make submitting and browsing issues a joy.</p>
<img src="http://i.imgur.com/LdtqZ0n.gif" alt="image"/><p>It allows to collapse text inside a section. You can then click on the arrow to reveal the full content. This is especially useful to keep the text short to read but still preserve the information for those who need are interested.</p>
<p>There are a lot of use cases. For example you could offer both Swift and Objective-C example code for your library or show multiple methods of integration with different dependency managers. This is what the HTML code could look like:</p>
<pre>
<details>
<summary>CocoaPods</summary>
Add the following line to your `Podfile`:
```ruby
pod 'YourAwesomeLibrary'
```
</details>
<details>
<summary>Carthage</summary>
Add the following line to your `Cartfile`:
```swift
github "YourUsername/YourAwesomeLibrary"
```
</details>
<details>
<summary>Manual</summary>
Clone the repo and drag and drop the files into your project.
</details>
</pre>
<p>This is what it looks like in action.</p>
<pre>
<details>
<summary>CocoaPods</summary>
Add the following line to your `Podfile`:
```ruby
pod 'YourAwesomeLibrary'
```
</details>
<details>
<summary>Carthage</summary>
Add the following line to your `Cartfile`:
```swift
github "YourUsername/YourAwesomeLibrary"
```
</details>
<details>
<summary>Manual</summary>
Clone the repo and drag and drop the files into your project.
</details>
</pre>
<h3>Demo Image or Video</h3>
<p>An image is worth a thousand words, you know that. If I don’t see a demo image, GIF or video for a project, chances are high that I will leave without trying it out. You should try as much as possible to grab the user attention with a concise image or GIF to show off what your project does. A great example is an animation library called <a href="https://github.com/lkzhao/Hero" target="_blank">Hero</a>. It was released a few weeks ago and the developer published a Youtube video showing all the power of the library. The video went viral in my timeline and that brought traffic to the project which today has over 5K ⭐️.</p>
<p>Unfortunately Markdown doesn’t support embedded videos, so your options are:</p>
<ul><li>If the video isn’t too long, create a GIF out of it and add it to the repo.</li>
<li>Display an image with a link to the video.</li>
<li>Simply mention the video and add a link somewhere in your README.</li>
</ul><p>I usually try to go with the first option as it doesn’t require the user to switch context to watch the video.</p>
<h3>Links Grouping</h3>
<p>This was a very new addition that I didn’t know was supported. If you find yourself writing more than once the same link in your Markdown file, you can create an alias so that you can define it only once. </p>
<pre>
Find me on [Twitter][my twitter].
If you need support, [tweet me][my twitter].
[my twitter]: https://www.twitter.com/BalestraPatrick
</pre>
<p>This pattern makes it really easy to change a link later on without having to go through the whole file to make sure every link was changed.</p>
<h3>Coding Guidelines</h3>
<p>Try to stick to a single coding style for your whole project. I recommend reading the <a href="https://github.com/raywenderlich/swift-style-guide" target="_blank">Swift Style Guide</a> so that other developers can see your coding style in case they would like to contribute.</p>
<h3>Structure</h3>
<p>Try to structure your README in a easy way to navigate. Write your first version and then come back after a few days to make sure it’s understandable for someone who has never seen your project.</p>
<p>To insert a line to divide sections use 5 consecutive “-” for example. Take a look at the Markdown syntax in <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" target="_blank">this guide</a>.</p>
<h3>Code of Conduct and Contributing Guidelines</h3>
<p>Having a code of conduct is always a nice addition if you plan to scale your library to the next level. Contributing guidelines are also useful for new developers who would like to contribute to your project. A simple list of required step to open an issue or pull request is a very nice idea. Check out the GitHub <a href="https://help.github.com/articles/helping-people-contribute-to-your-project/">documentation</a> to learn what you can do to make it easier for people to contribute to your project.</p>
<h3>Contact Information</h3>
<p>Don’t forget to mention who is part of the project, it’s always nice to see who is behind any cool idea on the internet. 😎</p>
<p>Please let me know of any tips you think are useful for improving a README on <a href="https://www.twitter.com/BalestraPatrick" target="_blank">Twitter</a>.</p>Patrick BalestraI spend quite some time browsing GitHub every day. I use the Trending section to filter the projects by language. I then proceed to explore each project by reading the README and maybe browsing the code, some issues and pull requests to see how the project is being maintained. The community is creating an immense number of projects and it’s one of the things I like the most about the Swift community.Automating my Bedroom with HomeKit2016-12-28T03:39:50+00:002016-12-28T03:39:50+00:00https://balestrapatrick.github.io/blog/2016/12/28/homekit-automation<p>I’ve been wanting to play with HomeKit for a few months but I never actually bought any HomeKit compatible device until a few weeks ago. I wanted to start slow and see how HomeKit has improved over the last iOS versions. <br/>I am completely new to this <a href="https://twitter.com/internetofshit">@internetofshit</a> thing, so here are my thoughts! 😄</p>
<p>I started by buying a simple control switch built specifically for the swiss plug type J and it’s called <a href="https://mystrom.ch/en/">myStrom</a>. The price is inline with other similar plugs, 39 CHF. <br/>It unofficially supports HomeKit and a few friends confirmed that it worked well for them. After connecting it with my Christmas tree lights, I was able to quickly turn it on/off from the Control Center of my iPhone. The result is pretty nice.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Got my first HomeKit accessory. Scheduling my Christmas tree comfortably from my couch. Love this 👍🏻🎄 <a href="https://t.co/SP4zRv0vtd">pic.twitter.com/SP4zRv0vtd</a></p><div>— Patrick Balestra (@BalestraPatrick) </div><a href="https://twitter.com/BalestraPatrick/status/805865337724010496">December 5, 2016</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script><p>I then automated this behavior by turning on the plug everyday at 6.00pm and turning it off at 11.00pm by creating a simple automation in the Home app.</p>
<figure data-orig-height="2208" data-orig-width="2484" data-orig-src="https://www.dropbox.com/s/st7cozui3b38oqp/christmas-setup.png?raw=1"><img src="https://78.media.tumblr.com/b7a37cbcaa8c536e8637a6ec32784cf5/tumblr_inline_padqs5ZBAA1sgewn1_540.png" alt="image" data-orig-height="2208" data-orig-width="2484" data-orig-src="https://www.dropbox.com/s/st7cozui3b38oqp/christmas-setup.png?raw=1"/></figure><p>This works even remotely if you have an Apple TV or iPad that you can use as <a href="https://support.apple.com/en-us/HT207057">home hub</a>. I have an Apple TV 4th generation and after a restart, HomeKit was enabled via iCloud. I didn’t want my family to ask me to light the Christmas tree when I wasn’t home (even though the plug has a small button that can turn it on and off manually). </p>
<p>I discovered that you can easily grant other people access by adding them to your house. </p>
<blockquote>
<p>The Home app is a very beautiful app in terms of user interface, but the user experience could be improved. I took me some minutes to find a few basic features like this one. </p>
</blockquote>
<p>I added my mom and sister to my House and they can now simply swipe up the control center to light the Christmas tree! 🎄🔆<br/>As soon as my mom enters the house, she can switch it on from her iPhone with Siri. Awesome!<br/>I could automate it even further by using geofencing, but I haven’t tried this feature yet.</p>
<p>As a Christmas gift for myself, I decided to convert my room to smart lightbulbs. I ordered the <a href="http://www.apple.com/shop/product/HJCA2VC/B/philips-hue-white-and-color-wireless-ambiance-starter-kit-a19-e26?fnode=820f897daff897ef75bb9461d25222c3279c7e31e8f5ff791d395c6d63b20a377f9c6ae3c740c497a033aadd1c8b9c0d37b61c13f26dac1ca7b296d5098d4c8075c035e8e3cecaebd4b3397ccb88be6a12412a38d118a3a8932be9dc70a6fdf2">Philips Hue White and Color Starter Kit</a> and the <a href="http://www.apple.com/shop/product/HFV22VC/B/philips-hue-tap-switch?fnode=820f897daff897ef75bb9461d25222c3279c7e31e8f5ff791d395c6d63b20a377f9c6ae3c740c497a033aadd1c8b9c0d37b61c13f26dac1ca7b296d5098d4c8075c035e8e3cecaebd4b3397ccb88be6a12412a38d118a3a8932be9dc70a6fdf2">Philips Hue tap Switch</a>. I also wanted to get the new <a href="https://www.elgato.com/en/eve/eve-motion">Elgato Eve Motion</a> at the same time but it wasn’t available to order online. While visiting the Apple Store in Bergamo, I saw it on the shelves and decided to pick it up as well to automate my room even further.</p>
<figure data-orig-height="3024" data-orig-width="4032" data-orig-src="https://www.dropbox.com/s/h4xi35rlfhw3uaf/boxes.jpg?raw=1"><img src="https://78.media.tumblr.com/0f20707c8f2a2b2fe3de57e1e75a31c7/tumblr_inline_padqs9b4na1sgewn1_540.jpg" alt="image" data-orig-height="3024" data-orig-width="4032" data-orig-src="https://www.dropbox.com/s/h4xi35rlfhw3uaf/boxes.jpg?raw=1"/></figure><p>The current lamp in my room supports light bulbs of type <a href="https://www.google.ch/search?q=e14+led+light+bulb">E14</a> but the Philips Hue was only sold with the type <a href="https://www.google.ch/search?q=gu10+led+light+bulb">GU10</a>. The solution was to buy a <a href="http://www.ebay.ch/itm/GU10-to-E27-MR16-or-B22-E14-E27-to-GU10-Light-Bulb-Socket-Lamp-Adaptor-Holder-/221017939556?var=520086589271">cheap adapter</a> from Ebay. </p>
<figure data-orig-height="3024" data-orig-width="4032" data-orig-src="https://www.dropbox.com/s/ou3zk2xh2ler5o8/lamp.jpg?raw=1"><img src="https://78.media.tumblr.com/ba80e25033f367e3db7abcf194bbd318/tumblr_inline_padqsbzUYe1sgewn1_540.jpg" alt="image" data-orig-height="3024" data-orig-width="4032" data-orig-src="https://www.dropbox.com/s/ou3zk2xh2ler5o8/lamp.jpg?raw=1"/></figure><p>The Hue bridge was very easy to set up, just wire it to the router with the provided Ethernet cable and to the power. The <a href="http://www2.meethue.com/en-us/philipshueapp">Hue iOS app</a> will do the rest. Setting up the Eve Motion was very straightforward too after having downloaded the Eve iOS app. Just scan the barcode and that’s it. The fun (and most difficult) part is automating the whole system.</p>
<p>I thought that I could set up all my actions through the Home app and manage everything from one place, but I was wrong. The third-party apps are actually more powerful and allow for more complicated automations. <br/>If you would like to add multiple conditions to a trigger, you can not do that with the Home app even though HomeKit supports this feature. You have to use a third-party app like <a href="https://www.elgato.com/en/eve/eve-app">Eve</a> or <a href="https://hesperus.io">Hesperus</a>. This inconsistencies complicate the user experience.</p>
<p>Let’s now take my room as example.</p>
<figure data-orig-height="493" data-orig-width="460" data-orig-src="https://www.dropbox.com/s/lw64unbztj34lb1/room-setup.png?raw=1"><img src="https://78.media.tumblr.com/a1953273ca6549708b61b2e682ce12ea/tumblr_inline_padqsd8XNP1sgewn1_540.png" alt="image" data-orig-height="493" data-orig-width="460" data-orig-src="https://www.dropbox.com/s/lw64unbztj34lb1/room-setup.png?raw=1"/></figure><p>I have a lamp hanged on the ceiling of my room where I mounted the three Hue bulbs. As I step into my room, the motion sensor triggers my lights depending on the time of the day. When I exit my room, I simply press the button on the Hue tap next to my door to turn everything off. I couldn’t find a way to automate this behavior. Let me know if you have any idea.</p>
<p>As I mentioned before, multiple conditions in a trigger are very useful. The brightness of the lights during the night should be lower compared to other times of the day. For this reason I created two different scenes that set the color and brightness differently. Here you can see my actions in Hesperus.</p>
<figure data-orig-height="2208" data-orig-width="1242" data-orig-src="https://www.dropbox.com/s/rzopir0ck7imrx4/hesperus.png?raw=1"><img src="https://78.media.tumblr.com/2e151f071b40d8db9158a223d28c3508/tumblr_inline_padqsgQgrE1sgewn1_540.png" alt="image" data-orig-height="2208" data-orig-width="1242" data-orig-src="https://www.dropbox.com/s/rzopir0ck7imrx4/hesperus.png?raw=1"/></figure><p>The cool thing is that HomeKit actions, scenes and accessories are shared between apps. You can use any app you want to set up your home. </p>
<p>Given that I only have a single motion sensor, before getting into bed I move my motion sensor closer to the bed. In this way, as soon as I step out of my bed one of the lights turns on at the minimum brightness to show me the way to the door.</p>
<blockquote>
<p>I took inspiration for this night setup from the <a href="http://www.marriott.com/hotels/travel/milox-moxy-milan-malpensa-airport/">MOXY Milan Malpensa Airport hotel</a>. As soon as I was stepping out of the bed, a motion sensor would switch on the LED strip under the edges of the bed at the minimum brightness. It was a pretty amazing effect for the guests.</p>
</blockquote>
<p>One of the problems I encountered was that the motion sensor was not working 100% initially, but after discovering how to change the sensitivity of the sensor in the Eve app, it started to work more reliably.</p>
<p>I am pretty happy with the setup after a few days of usage. I still have to create a few custom scenes to fully obtain the effect and colors that I want. For example, I would like to slowly turn on the lights to wake me up in the morning. As I am currently in winter break from school and I am not on a regular sleep schedule, I was not able to test this feature yet. 😴</p>
<p>If anyone’s interested, I’ll share more opinions about this topic in the future.</p>
<p>Thanks to <a href="https://twitter.com/KhaosT">@KhaosT</a> for the help in understanding HomeKit.</p>Patrick BalestraI’ve been wanting to play with HomeKit for a few months but I never actually bought any HomeKit compatible device until a few weeks ago. I wanted to start slow and see how HomeKit has improved over the last iOS versions. I am completely new to this @internetofshit thing, so here are my thoughts! 😄Playground in Xcode 82016-06-16T12:22:00+00:002016-06-16T12:22:00+00:00https://balestrapatrick.github.io/blog/2016/06/16/playground-in-xcode-8<p>During <a href="https://developer.apple.com/videos/play/wwdc2016/213/">session 213 of WWDC 2016</a>, some changes to Playground in Xcode 8 were mentioned. The talk shows more tips and tricks to make use of the powerful Xcode features such as Assets Catalogs to avoid writing more code than what is necessary. I highly reccomend you to watch it!</p>
<p>To manage the execution of a Playground, the <code>PlaygroundSupport</code> framework can now be used. By ⌘ + clicking the framework name, this is what you can find:</p>
<ul><li>A <code>UIViewController</code> and <code>UIView</code> extension that implement the <code>PlaygroundLiveViewable</code> protocol.</li>
<li>The <code>PlaygroundLiveViewRepresentation</code> enum which describes if the current live view shows a <code>UIView</code> or a <code>UIViewController</code>.</li>
<li>The <code>PlaygroundLiveViewable</code> protocol itself that has a variable to hold the current live view representation.</li>
<li>The <code>PlaygroundPage</code> class that allows you to modify the playground execution.</li>
</ul><p>A Playground is compiled like a script, line after line. This is great until you want to test a network request that is performed asynchronously. You will never see the callback result because the Playground is simply stopped before the response can arrive.
To fix this problem you have to tell Xcode that your page <code>needsIndefiniteExecution</code>. Let’s take a look at a common <code>URLSession</code> usage.</p>
<pre>
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let url = URL(string: "https://emergency-phone-numbers.herokuapp.com")!
let session = URLSession.shared()
let q = session.dataTask(with: url) { data, response, error in
do {
if let d = data, let dictionary = try JSONSerialization.jsonObject(with: d, options: []) as? [String: AnyObject] {
print(dictionary)
}
} catch {
print("Error \(error)")
}
}
q.resume()
</pre>
<p>We first import the new <code>PlaygroundSupport</code> framework at the top. We then set the <code>PlaygroundPage.current.needsIndefiniteExecution</code> property to true so that the playground will continue the execution of the Swift file even after reaching the last line. In this way, we are able to debug and see the response of our request.</p>
<p>You can also tell your Playground to stop waiting for something to happen. You could for example add this line in your completion handler to stop the execution of the page.</p>
<pre>
PlaygroundPage.current.finishExecution()
</pre>
<p>Another cool feature shown in the session which was added in Xcode 7.3, is the ability to interact with the live view. You can for example create a <code>UIViewController</code> and assign it to the Playground <code>liveView</code> as follows:</p>
<pre>
PlaygroundPage.current.liveView = viewController.view
</pre>
<p>This is useful to test a component before actually implement it into your project. To read more about this specific feature, watch the <a href="https://developer.apple.com/videos/play/wwdc2016/213/">WWDC session 213 video</a> or read this blog post on the <a href="https://developer.apple.com/swift/blog/?id=35">Swift official blog</a>.</p>
<p>Thanks for reading 🤓</p>Patrick BalestraDuring session 213 of WWDC 2016, some changes to Playground in Xcode 8 were mentioned. The talk shows more tips and tricks to make use of the powerful Xcode features such as Assets Catalogs to avoid writing more code than what is necessary. I highly reccomend you to watch it! To manage the execution of a Playground, the PlaygroundSupport framework can now be used. By ⌘ + clicking the framework name, this is what you can find: A UIViewController and UIView extension that implement the PlaygroundLiveViewable protocol. The PlaygroundLiveViewRepresentation enum which describes if the current live view shows a UIView or a UIViewController. The PlaygroundLiveViewable protocol itself that has a variable to hold the current live view representation. The PlaygroundPage class that allows you to modify the playground execution. A Playground is compiled like a script, line after line. This is great until you want to test a network request that is performed asynchronously. You will never see the callback result because the Playground is simply stopped before the response can arrive. To fix this problem you have to tell Xcode that your page needsIndefiniteExecution. Let’s take a look at a common URLSession usage.