<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Artem Loenko on Medium]]></title>
        <description><![CDATA[Stories by Artem Loenko on Medium]]></description>
        <link>https://medium.com/@dive?source=rss-47536a8cb274------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*AKnTLwyPBOSQMbXLqA4uHg.jpeg</url>
            <title>Stories by Artem Loenko on Medium</title>
            <link>https://medium.com/@dive?source=rss-47536a8cb274------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 13 Jul 2026 09:35:34 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dive/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[How to get the current selected Xcode and list installed]]></title>
            <link>https://dive.medium.com/how-to-get-the-current-selected-xcode-and-list-installed-e16278c8c65a?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/e16278c8c65a</guid>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[xcodebuild]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Thu, 20 May 2021 17:36:07 GMT</pubDate>
            <atom:updated>2021-05-20T17:36:07.460Z</atom:updated>
            <content:encoded><![CDATA[<h3>Current Selected Xcode</h3><h4>xcode-select</h4><p>This is the most common way to get the path to the selected instance:</p><pre>xcrun xcode-select --print-path</pre><pre># Output<br>/Volumes/Extended/Archives/Xcode_12.5.app/Contents/Developer</pre><p>According to the documentation:</p><blockquote><em>Prints the path to the currently selected developer directory. This is useful for inspection, but scripts and other tools should use xcrun(1) to locate tool inside the active developer directory.</em></blockquote><p><em>Note</em>: If you wonder why I prefix the xcode-select with xcrun command, please, check the <a href="https://gist.github.com/dive/d2df088567b25971a44f02b1f05d6916">Multiple Xcode versions or Why </a><a href="https://gist.github.com/dive/d2df088567b25971a44f02b1f05d6916">xcrun is your friend</a> article.</p><h4>readlink</h4><p>There is a trick to get the current selected Xcode version without the xcode-select tool. It can be helpful in some cases, but I recommend using xcode-select if you have no additional requirements. To check the current selected Xcode version without xcode-select, evaluate the following command:</p><pre>readlink /private/var/db/xcode_select_link</pre><pre># Output<br>/Volumes/Extended/Archives/Xcode_12.5.app/Contents/Developer</pre><p>Every time you switch the default Xcode, xcode-select changes the link to the selected version. Perhaps, this is the fastest way to obtain the path, but it is not documented, and Apple can break it with any following Xcode release.</p><h3>List of installed Xcode versions</h3><h4>Spotlight</h4><p>The easiest way to get the list of installed Xcode versions is to ask the Spotlight with the following command:</p><pre>mdfind &quot;kMDItemCFBundleIdentifier = &#39;com.apple.dt.Xcode&#39;&quot;</pre><pre># Output<br>/Volumes/Extended/Archives/Xcode_12.5.app<br>/Volumes/Extended/Archives/Xcode_12.4.app<br>/Volumes/Extended/Archives/Xcode_12.1.app<br>/Volumes/Extended/Archives/Xcode_12.3.app<br>/Volumes/Extended/Archives/Xcode_12.2.app</pre><p><em>Note</em>: This approach is usually not suitable for CI/Remote Builds because this is a popular option to disable Spotlight to improve performance.</p><h4>system_profile</h4><p>The less obvious way to get the list of installed Xcode versions is to use the system_profiler. It registers all the versions immediately when you extract them from the xip file.</p><pre>system_profiler -json SPDeveloperToolsDataType</pre><p>The problem here is the output. It is vast and looks like the following for each installed version:</p><pre>{<br>  &quot;SPDeveloperToolsDataType&quot; : [<br>    {<br>      &quot;_name&quot; : &quot;spdevtools_info&quot;,<br>      &quot;spdevtools_apps&quot; : {<br>        &quot;spinstruments_app&quot; : &quot;12.5 (64544.130)&quot;,<br>        &quot;spxcode_app&quot; : &quot;12.5 (18205)&quot;<br>      },<br>      &quot;spdevtools_path&quot; : &quot;/Volumes/Extended/Archives/Xcode_12.5.app&quot;,<br>      &quot;spdevtools_sdks&quot; : {<br>        &quot;iOS&quot; : {<br>          &quot;14.5&quot; : &quot;(18E182)&quot;<br>        },<br>        &quot;iOS Simulator&quot; : {<br>          &quot;14.5&quot; : &quot;(18E182)&quot;<br>        },<br>        &quot;macOS&quot; : {<br>          &quot;11.3&quot; : &quot;(20E214)&quot;,<br>          &quot;20.4&quot; : &quot;&quot;<br>        },<br>        &quot;tvOS&quot; : {<br>          &quot;14.5&quot; : &quot;(18L191)&quot;<br>        },<br>        &quot;tvOS Simulator&quot; : {<br>          &quot;14.5&quot; : &quot;(18L191)&quot;<br>        },<br>        &quot;watchOS&quot; : {<br>          &quot;7.4&quot; : &quot;(18T187)&quot;<br>        },<br>        &quot;watchOS Simulator&quot; : {<br>          &quot;7.4&quot; : &quot;(18T187)&quot;<br>        }<br>      },<br>      &quot;spdevtools_version&quot; : &quot;12.5 (12E262)&quot;<br>    },<br>...<br>}</pre><h4>Parse the system_profiler output with jq</h4><p>You have to parse the system_profiler output to provide meaningful information. One option is to use <a href="https://github.com/stedolan/jq">jq</a> – a lightweight and flexible command-line JSON processor. For example, if you want to list paths:</p><pre>system_profiler -json SPDeveloperToolsDataType | jq &#39;.SPDeveloperToolsDataType[].spdevtools_path&#39;</pre><pre># Output<br>&quot;/Volumes/Extended/Archives/Xcode_12.5.app&quot;<br>&quot;/Volumes/Extended/Archives/Xcode_12.4.app&quot;<br>&quot;/Volumes/Extended/Archives/Xcode_12.3.app&quot;<br>&quot;/Volumes/Extended/Archives/Xcode_12.2.app&quot;<br>&quot;/Volumes/Extended/Archives/Xcode_12.1.app&quot;</pre><p>Or for installed versions:</p><pre>system_profiler -json SPDeveloperToolsDataType | jq &#39;.SPDeveloperToolsDataType[].spdevtools_apps.spxcode_app&#39;</pre><pre># Output<br>&quot;12.5 (18205)&quot;<br>&quot;12.4 (17801)&quot;<br>&quot;12.3 (17715)&quot;<br>&quot;12.2 (17535)&quot;<br>&quot;12.1 (17222)&quot;</pre><h3>Tips &amp; Tricks</h3><h4>How to get the installed Xcode version</h4><p>When you have the path to the current selected Xcode, then you can use the following function to extract CFBundleShortVersionString or ProductBuildVersion:</p><pre>#!/bin/sh -e</pre><pre>function xcodeBundleVersion() {<br>    defaults read &quot;${1}/../version.plist&quot; &quot;CFBundleShortVersionString&quot;<br>}</pre><pre>function xcodeBuildVersion() {<br>    defaults read &quot;${1}/../version.plist&quot; &quot;ProductBuildVersion&quot;<br>}</pre><pre>function xcodeVersion() {<br>    BUNDLE_VERSION=$(xcodeBundleVersion ${1})<br>    BUILD_VERSION=$(xcodeBuildVersion ${1})<br>    echo &quot;Xcode ${BUNDLE_VERSION} (${BUILD_VERSION})&quot;<br>}</pre><pre># Note that you can replace the `xcode-select` call with other methods to extract the path<br>XCODE_VERSION=$(xcodeVersion $(xcrun xcode-select --print-path))<br>echo $XCODE_VERSION</pre><h4>Faster Xcode secure-archive expansion (xip)</h4><p>When you download a xip secure archive, you can expand it from CLI with xip tool. In this case, the validation of the archive will not be attempted. On Mac mini M1, it takes around four minutes to expand it.</p><pre>% du -h Xcode_12.0.1.xip<br>  10G    Xcode_12.0.1.xip</pre><pre>% time xip --expand Xcode_12.0.1.xip<br>xip: signing certificate was &quot;Development Update&quot; (validation not attempted)<br>xip: expanded items from &quot;/Users/dive/Downloads/Xcode_12.0.1.xip&quot;<br>xip --expand Xcode_12.0.1.xip  901.47s user 139.39s system 420% cpu 4:07.79 total</pre><h4>xcodes – a command-line tool to install and switch between multiple versions of Xcode</h4><p>I can recommend <a href="https://github.com/RobotsAndPencils/xcodes">xcodes</a> as a tool to manage your Xcode installation. The tool itself has a few benefits:</p><ul><li>When <a href="https://aria2.github.io/">aria2</a> (a lightweight multi-protocol &amp; multi-source command-line download utility) installed, then xcodes will default to use it for downloads. It uses up to 16 connections to download Xcode 3-5x faster than usual</li><li>xcodes written in Swift. Improve, fix and evolve if you need something from the tool</li></ul><pre>% xcodes installed <br>12.1 (12A7403)           /Volumes/Extended/Archives/Xcode_12.1.app<br>12.2 (12B45b)            /Volumes/Extended/Archives/Xcode_12.2.app<br>12.3 (12C33)             /Volumes/Extended/Archives/Xcode_12.3.app<br>12.4 (12D4e)             /Volumes/Extended/Archives/Xcode_12.4.app<br>12.5 (12E262) (Selected) /Volumes/Extended/Archives/Xcode_12.5.app</pre><p>It relies on <a href="https://xcodereleases.com/">xcodereleases.com</a> data (<a href="https://xcodereleases.com/data.json">JSON</a>), so you can expect delays between releases and the tool updates. But usually, it takes 10–20 minutes for an update.</p><p><em>Note</em>: The tool downloads Xcode versions directly from the Apple Developer Portal. And this is the only way to do so. Please, do not download Xcode versions from third-party storages.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e16278c8c65a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Multiple Xcode versions or Why xcrun is your friend]]></title>
            <link>https://dive.medium.com/multiple-xcode-versions-or-why-xcrun-is-your-friend-ed3935b054b?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/ed3935b054b</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[continuous-deployment]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Fri, 02 Apr 2021 12:16:43 GMT</pubDate>
            <atom:updated>2021-04-05T09:48:38.943Z</atom:updated>
            <content:encoded><![CDATA[<h3>The story</h3><p>I recently spent a few hours helping a friend of mine investigate a weird issue in their Continuous Development infrastructure. Builds were failing with different fatal errors mostly related to SDK paths and .platform directory locations. At first sight, it was clear that something is wrong with the current selected Xcode, but all our initial attempts to catch the problem failed.</p><p>In the end, we isolated the problem; one of the tools they use changes PATH silently for the environment to simplify access to Xcode tools. Due to their internal logic, the CD pipeline changes a current selected Xcode a few times on the way within the same script. In some cases, the pipeline ended with xcodebuild in the environment’s PATH that does not reflect the expected version after the xcode-select — switch command.</p><p>How? Pretty easy, actually. A simplified sequence looked like this:</p><pre># Innocent tool extends the `PATH`<br># With the `bin` directory within the current selected Xcode<br>% export PATH=”/Xcode_12.5_beta_3.app/Contents/Developer/usr/bin:${PATH}”</pre><pre># We change Xcode in a proper way<br>% sudo xcode-select — switch /Xcode_12.1.app/Contents/Developer</pre><pre># Due to the overridden `PATH`, `xcodebuild` points to an incorrect version<br>% xcodebuild -version <br>Xcode 12.5<br>Build version 12E5244e</pre><pre># `xcrun` knows the truth<br>% xcrun xcodebuild -version<br>Xcode 12.1<br>Build version 12A7403</pre><h3>xcrun — Invoke Xcode tools in a safer way</h3><p>According to the documentation:</p><blockquote>xcrun provides a means to locate or invoke developer tools from the command-line, without requiring users to modify Makefiles or otherwise take inconvenient measures to support multiple Xcode toolchains.<br>The tool xcode-select(1) is used to set a system default for the active developer directory and may be overridden by the DEVELOPER_DIR environment variable.</blockquote><p>In real life, it means that you can prefix all the calls to Xcode tools with xcrun on CI/CD to avoid the situation I described in the beginning. Want to run xcodebuild — call it via xcrun xcodebuild command, need to run/invoke simulators, use the xcrun simctl command.</p><p>It can save a few hours for your RE/DevOps team at the end of the day. And, depends on the company size, from 5 to 100 hours for your engineers.</p><h4>What else?</h4><p>xcrun has a few additional commands.</p><p>find — enables “find” mode, in which the resolved tool path is printed instead of the tool being executed.</p><pre>$ xcrun — find xcodebuild<br>/Xcode_12.1.app/Contents/Developer/usr/bin/xcodebuild</pre><pre>$ xcrun — find clang<br>/Xcode_12.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang</pre><p>A few helpers to print paths/versions of the selected SDKs.</p><pre># Print the path to the selected SDK<br>$ xcrun — show-sdk-path<br>/Xcode_12.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk</pre><pre># Print the version number of the selected SDK<br>$ xcrun — show-sdk-version<br>10.15.6</pre><pre># Print the build version number of the selected SDK<br>$ xcrun — show-sdk-build-version<br>19G68</pre><pre># Print the path to the platform for the selected SDK<br>$ xcrun — show-sdk-platform-path<br>/Xcode_12.1.app/Contents/Developer/Platforms/MacOSX.platform</pre><pre># Print the version number of the platform for the selected SDK<br>$ xcrun — show-sdk-platform-version<br>10.15.6</pre><p>verbose option shows the logic behind the xcrun. For example, you can see that all the mappings are stored within a temporary xcrun_db and populated on the stage when you select a different Xcode version.</p><pre>% xcrun — verbose — find git <br>xcrun: note: PATH = ‘/Xcode_12.5_beta_3.app/Contents/Developer/usr/bin/:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin’<br>xcrun: note: SDKROOT = ‘/Xcode_12.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk’<br>xcrun: note: TOOLCHAINS = ‘’<br>xcrun: note: DEVELOPER_DIR = ‘/Xcode_12.1.app/Contents/Developer’<br>xcrun: note: XCODE_DEVELOPER_USR_PATH = ‘’</pre><pre># The database with all the links<br>xcrun: note: xcrun_db = ‘/var/folders/gn/8j0pyrwj5j3ggxprkczkpwtc0000gn/T/xcrun_db’</pre><pre>xcrun: note: xcrun via git (xcrun)<br>xcrun: note: database key is: git|/Xcode_12.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk||/Xcode_12.1.app/Contents/Developer|<br>xcrun: note: lookup resolved in ‘/var/folders/gn/8j0pyrwj5j3ggxprkczkpwtc0000gn/T/xcrun_db’ : ‘/Xcode_12.1.app/Contents/Developer/usr/bin/git’<br>/Xcode_12.1.app/Contents/Developer/usr/bin/git</pre><h4>Side notes</h4><p>- Check the previous note about xed — <a href="https://gist.github.com/dive/8d8f222f6851afaea338f853c7d51410">Xcode invocation tool</a><br>- Create a minor task for your DevOps team to prefix all the calls to Xcode tools with xcrun</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ed3935b054b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Grammarly iOS Keyboard — Unboxing]]></title>
            <link>https://dive.medium.com/grammarly-ios-keyboard-unboxing-15fe4db91b56?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/15fe4db91b56</guid>
            <category><![CDATA[grammarly]]></category>
            <category><![CDATA[privacy]]></category>
            <category><![CDATA[tracking]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Thu, 30 Jul 2020 12:48:00 GMT</pubDate>
            <atom:updated>2020-07-30T12:48:00.230Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bXt56gUHNw9VVwr8rAb7dg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@ev?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">ev</a> on <a href="https://unsplash.com/s/photos/privacy?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>Grammarly iOS Keyboard — Unboxing</h3><p><a href="https://www.grammarly.com">Grammarly</a> is a lovely writing assistant. Twenty million people use the tool across the globe according to the statistics available on the site. I use it too. No complaints, it does its job quite well, and I am a happy user. The only thing that always worried me is the <a href="https://www.grammarly.com/keyboard">Grammarly iOS Keyboard</a>. As an iOS engineer, I know how easily you can collect different data, sensitive information, and even do not ask users about the consent. So, let’s check what is inside the Grammarly iOS application.</p><h3>TL;DR</h3><ul><li>Grammarly iOS uses at least three trackers (Adjust, AppsFlyer, Internal analytics)</li><li>Grammarly Keyboard has access to keystrokes, sensitive data, and able to send them over the network</li></ul><h3>Frameworks</h3><h4>Facebook</h4><p>From the Grammarly.ipa file it is clear that they are using Facebook SDKs:</p><pre>➜ Grammarly.app_unzip $ find . -iname &#39;*.framework&#39;<br>./Frameworks/FacebookLogin.framework<br>./Frameworks/FBSDKLoginKit.framework<br>./Frameworks/FBSDKCoreKit.framework<br>./Frameworks/FacebookCore.framework</pre><p>Yes, they are using Facebook as a Sign In/Sign Up provider, and Facebook explicitly said that this is the only way to authorise users. From the <a href="https://developers.facebook.com/policy/">Facebook Platform Policy</a>:</p><blockquote><em>Section 8. Login</em></blockquote><blockquote><em>Point 2. Native iOS and Android apps that implement Facebook Login must use our official SDKs for login.</em></blockquote><p>The only concern here is the way how Facebook treats users and applications that use their SDKs. During 2020, Facebook already damaged a lot of application twice. Check <a href="https://rambo.codes/posts/2020-05-07-the-big-facebook-crash">The big Facebook crash of 2020 and the problem of third-party SDK creep</a> by Guilherme Rambo.</p><h4>MSpell framework</h4><p>This framework also ships with the application, and it seems that this is the engine the Grammarly uses for spell and grammar checks. Some exported functions from the framework, just as an example:</p><pre>0000000000080808 T __ZN10Dictionary21_loadCommonlyConfusedERKNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEE<br>0000000000080d54 T __ZN10Dictionary24_loadProfanityDictionaryERKNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEE<br>0000000000082034 T __ZN10Dictionary24_loadSensitiveDictionaryERKNSt3__16vectorINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEENS5_IS7_EEEE<br>00000000000822ac T __ZN10Dictionary27isValidCommonlyConfusedPairERKNSt3__112basic_stringIDsNS0_11char_traitsIDsEENS0_9allocatorIDsEEEES8_</pre><h3>Trackers</h3><p>No surprises here. There are at least three trackers within the application:</p><ol><li><a href="https://www.adjust.com">Adjust</a> — Maximize the impact of your mobile marketing!</li><li><a href="https://www.appsflyer.com">AppsFlyer</a> — Attribute every app install to a marketing campaign and media source!</li><li>Internal tracker located by the <a href="https://f-log-mobile-ios.grammarly.io">https://f-log-mobile-ios.grammarly.io</a> address</li></ol><p>Also, worth to mention that <a href="https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nsapptransportsecurity/nsallowsarbitraryloads">NSAllowsArbitraryLoads</a> is disabled for the application. This is good, at least there is no way to send the data to additional third-party services, etc. According to the documentation:</p><blockquote><em>A Boolean value indicating whether App Transport Security restrictions are disabled for all network connections. Disabling ATS means that unsecured HTTP connections are allowed.</em></blockquote><h3>Grammarly Custom Keyboard</h3><p>There is a helpful guide from Apple about custom keyboards — <a href="https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/CustomKeyboard.html">Designing for User Trust</a>:</p><blockquote><em>For keyboards, the following three areas are especially important for establishing and maintaining user trust:</em></blockquote><blockquote><strong>- Safety of keystroke data</strong>. Users want their keystrokes to go to the document or text field they’re typing into, and not to be archived on a server or used for purposes that are not obvious to them.</blockquote><blockquote><strong>- Appropriate and minimized use of other user data</strong>. If your keyboard employs other user data, such as from Location Services or the Address Book database, the burden is on you to explain and demonstrate the benefit to your users.</blockquote><blockquote><strong>- Accuracy</strong>. Accuracy in converting input events to text is not a privacy issue per se but it impacts trust: With every word typed, users see the accuracy of your code.</blockquote><blockquote><em>To design for trust, first consider whether to request open access. Although open access makes many things possible for a custom keyboard, it also increases your responsibilities.</em></blockquote><p>And the Grammarly iOS Keyboard uses the Open Access by default. To demonstrate the difference, this is a comparison with significant capabilities and restrictions for both modes:</p><h4><strong>Open access off (default)</strong></h4><ul><li>No shared container with containing app</li><li>No access to file system apart from keyboard’s own container</li><li>No ability to participate directly or indirectly in iCloud, Game Center, or In-App Purchase</li></ul><h4><strong>Open access on</strong></h4><ul><li>Keyboard can access Location Services and Address Book, with user permission</li><li>Keyboard and containing app can employ a shared container</li><li>Keyboard can send keystrokes and other input events for server-side processing</li></ul><p>So, the Grammarly iOS application has access to a lot of things. And what is more important, is able to send keystrokes to the server.</p><h3>Network requests</h3><p>To illustrate the situation with trackers and the Open Access, let’s check which requests are initiated when the Grammarly iOS Keyboard is enabled on your iOS device.</p><p>When you open the Spotlight and Grammarly is the default keyboard, you see the following sequence of requests:</p><pre>https://f-log-mobile-ios.grammarly.io<br>https://gnar.grammarly.com<br>https://data.grammarly.com<br>https://f-log-mobile-ios.grammarly.io<br>https://t.appsflyer.com</pre><p>All the requests made with the GRKeyboardExtension/1.9.2.3 CFNetwork/1185.2 Darwin/20.0.0 user-agent. Also, all the end-points use <a href="https://developer.apple.com/documentation/foundation/url%5Floading%5Fsystem/handling%5Fan%5Fauthentication%5Fchallenge/performing%5Fmanual%5Fserver%5Ftrust%5Fauthentication">Certificate Pinning</a>, so, there is no easy way to check the body of the requests. But it is not the point for the article.</p><p>To illustrate the point, I recorded a video with network activity. Main takeaways are:</p><ul><li>Connections to <a href="https://gnar.grammarly.com/">https://gnar.grammarly.com</a> and <a href="https://f-log-mobile-ios.grammarly.com/">https://f-log-mobile-ios.grammarly.com</a> are active all the way when you use the keyboard</li><li>It seems that all the actions (when you select a word to fix) are sent to Adjust</li></ul><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FKz4AhLatdyE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DKz4AhLatdyE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FKz4AhLatdyE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/53550a1e6725fe4acf365376492326de/href">https://medium.com/media/53550a1e6725fe4acf365376492326de/href</a></iframe><p>And yes, the sequence is the same for Safari when you fill in credentials, etc. But do not worry, Apple does not allow to use custom keyboards to fill in passwords. Though, for usernames, phones, emails, etc. Grammarly sends the requests above.</p><h3>Grammarly Privacy Policy</h3><p><a href="https://www.grammarly.com/privacy-policy">Privacy Policy | Grammarly</a> states that:</p><ol><li>We do not and will not sell your information. We don’t help companies advertise their products to you.</li><li>We use a small number of trusted third parties to help provide our products.</li></ol><p>But on the other hand, there is a <a href="https://www.grammarly.com/privacy-policy#does-grammarly-share-my-information">Does Grammarly share my Information?</a> section that states:</p><blockquote><em>We only disclose Personal Data to third parties when we have your explicit consent to share your Personal Data.</em></blockquote><p>Standard words, usual phrases. I am not a specialist in this field, but I did not find an option to opt-out in the mobile application.</p><h3>Conclusions</h3><p>To be clear, I do not think that Grammarly steals your passwords, selling the data, trying to spy on sensitive information intentionally. I am a user of their services for two years and will continue to use it. With one exception — no more Grammarly iOS Keyboard application on my iOS devices. This is too much.</p><h3>Software I used</h3><ul><li><a href="http://www.manpagez.com/man/1/nm/osx-10.12.6.php">nm</a> tool — lists the symbols from object files</li><li><a href="https://www.manpagez.com/man/1/otool/">otool</a> — displays specified parts of object files or libraries</li><li><a href="https://proxyman.io">ProxyMan</a> — Modern and Delightful Web Debugging Proxy</li></ul><p>Checked by Grammarly</p><p><em>Originally published at </em><a href="https://justsitandgrin.net/posts/grammarly_ios_unboxing/"><em>https://justsitandgrin.net</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=15fe4db91b56" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Xcode invocation tool — xed]]></title>
            <link>https://dive.medium.com/xcode-invocation-tool-xed-deb04d03cf98?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/deb04d03cf98</guid>
            <category><![CDATA[command-line]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[productivity]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Sat, 25 Jul 2020 09:42:56 GMT</pubDate>
            <atom:updated>2020-07-25T09:42:56.473Z</atom:updated>
            <content:encoded><![CDATA[<h3>Xcode invocation tool — xed</h3><p>xed is a command-line tool that launches the Xcode application and opens the given documents ( xcodeproj, xcworkspace, etc.), or opens a new document, optionally with the contents of standard input.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RIzNp-TiXtc4-OpvCiU8-w.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@blakeconnally?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Blake Connally</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>If you work from the command line, this tool is a better option than open (which can open Xcode projects as well). Why?</p><ul><li>xed knows about the current selected Xcode version (open behaves unpredictably if you have multiple Xcode installed)</li><li>You can use it open all files from a specific commit (with a little help explained below). It is useful on code-reviews or when you want to explore significant changes in the repository</li><li>You can use it as a “quick open” helper. Helps with monorepo phenomena, when you have hundreds of projects in the repository (I will show you an example below)</li></ul><h3>Note about the current selected Xcode version</h3><p>The current selected Xcode is controlled by xcode-select tool. You can check the current selected version with xcode-select -p (or xcode-select --print-path) and change it with sudo xcode-select -s PATH_TO_XCODE (or sudo xcode-select --switch PATH_TO_XCODE).</p><p><strong>Tips &amp; Tricks</strong>: There is a trick to get the current selected Xcode version without the tool. But your command line has to have full disk access. In some cases, it can be useful, but I recommend to use xcode-select if you have no additional requirements. To check the current selected Xcode version without xcode-select, execute the following command:</p><pre>$ readlink /private/var/db/xcode_select_link<br>/Volumes/Extended/Archive/Xcode_11.5.app/Contents/Developer</pre><h3>Base commands</h3><pre>xed --launch<br># or<br>xed -x</pre><p>Launches the current selected Xcode.</p><pre>xed Client.xcodeproj<br># or<br>xed Client.xcworkspace</pre><p>Will open the project with the current selected Xcode and terminate (the process that invoked xed remains in control).</p><pre>xed SourceFile.swift AnotherExample.swift</pre><p>Will open the files. There are two possible outcomes:</p><ul><li>Xcode will navigate to these file within the project if the project that contains these files is already opened</li><li>Xcode will open the files as separate units</li></ul><p>There are more options, like --wait or --line. Please, consult the man page for xed.</p><p><strong>Tips &amp; Tricks</strong>: If you are browsing this article on macOS, you can open the x-man-page://xed link, and it will show you the man page for the command in Terminal.app. There is a special scheme — x-man-page - than can open man pages for any available commands on macOS.</p><h3>Open all files with changes</h3><p>You can browse the git history directly in Xcode, and this is a convenient way to navigate the history. But I am not too fond of the Xcode Code Review tool because of the layout (when they show the original source and the version side-by-side), and there is no option to open all the files in the editor. Sometimes it is useful to open all files changed by the commit as regular source files and navigate them one by one.</p><p>To do so, you need a hash of the commit you want to browse. The following command will list all the files in the commit and open them in Xcode:</p><pre>xed $(git diff-tree --no-commit-id --name-only -r COMMIT_HASH)</pre><p>You can use the command as an alias for your Bash or zsh configurations.</p><p>Note: if the Xcode project for these files is already opened then Xcode will open them in the context of the project. Otherwise, it will open each file in a separate window.</p><h3>Quick search and open projects</h3><p>You need a quick way to search and open projects when you have hundreds of them in your git repository. In my case, I work with two monorepos daily, and I have a significant number of different projects in my “projects” folder. To be able to navigate and open them as quickly as possible, I developed a script that scans the current folder for all .xcodeproj files, produces a list of them according to the provided search term and then open a specific project with the xed tool.</p><p>Let’s take the <a href="https://github.com/mozilla-mobile/firefox-ios">Firefox iOS project</a> as a simple example. The project contains 65 .xcodeproj files in the repository (most of them are third-party Carthage dependencies). Imagine that I work with the repository every day and have to switch between these projects (check demos, run tests, apply fixes, etc.). To help myself, I am using the following script:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c5fe008a3baadb341819d5254f900a7b/href">https://medium.com/media/c5fe008a3baadb341819d5254f900a7b/href</a></iframe><p>The script will produce the full list of projects when you run it in the Firefox iOS project and ask you to provide a number to select a project to open:</p><pre>$ sh pxed.sh<br>...<br>60) ./Carthage/Checkouts/sentry-cocoa/Sentry.xcodeproj<br>61) ./Carthage/Checkouts/swift-protobuf/SwiftProtobuf.xcodeproj<br>62) ./Carthage/Checkouts/telemetry-ios/Telemetry.xcodeproj<br>63) ./Client.xcodeproj<br>64) ./FxA/FxA.xcodeproj<br>65) ./ThirdParty/Deferred/Deferred.xcodeproj<br>#?</pre><p>If you run it with a search term, “demo” for example, the list will be limited to projects with the keyword in the name:</p><pre>$ sh pxed.sh demo<br>Collecting .xcodeproj...<br>Please select a project:<br>1) ./Carthage/Checkouts/Fuzi/FuziDemo/FuziDemo.xcodeproj<br>2) ./Carthage/Checkouts/SDWebImage/Examples/SDWebImage Demo.xcodeproj<br>3) ./Carthage/Checkouts/XCGLogger/DemoApps/iOSDemo/iOSDemo.xcodeproj<br>4) ./Carthage/Checkouts/XCGLogger/DemoApps/macOSDemo/macOSDemo.xcodeproj<br>5) ./Carthage/Checkouts/XCGLogger/DemoApps/tvOSDemo/tvOSDemo.xcodeproj<br>6) ./Carthage/Checkouts/onepassword-app-extension/Demos/App Demo for iOS Swift/App Demo for iOS Swift.xcodeproj<br>7) ./Carthage/Checkouts/onepassword-app-extension/Demos/App Demo for iOS/App Demo for iOS.xcodeproj<br>8) ./Carthage/Checkouts/onepassword-app-extension/Demos/WebView Demo for iOS Swift/WebView Demo for iOS Swift.xcodeproj<br>9) ./Carthage/Checkouts/onepassword-app-extension/Demos/WebView Demo for iOS/WebView Demo for iOS.xcodeproj<br>#?</pre><p>And, finally, the script will open the project straight away if there is only one search result for the keyword:</p><pre>$ sh pxed.sh sent<br>Collecting .xcodeproj...<br>Opening ./Carthage/Checkouts/sentry-cocoa/Sentry.xcodeproj...</pre><h3>Thanks for reading</h3><p><a href="https://twitter.com/justsitandgrin">Let me know</a> if you have questions or want to discuss something. Feel free to comment the <a href="https://gist.github.com/dive/aa5b6713216ba87c0a07ab73440078f4">script</a> on GitHub as well.</p><p><em>Originally published at </em><a href="https://justsitandgrin.net/posts/xed_xcode_invocation_tool/"><em>https://justsitandgrin.net</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=deb04d03cf98" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[About Bob Martin’s talk — The Future of Programming (2016)]]></title>
            <link>https://dive.medium.com/about-bob-martins-talk-the-future-of-programming-2016-f9408ee2e8ae?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/f9408ee2e8ae</guid>
            <category><![CDATA[robert-martin]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[engineering]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Tue, 17 Mar 2020 10:15:10 GMT</pubDate>
            <atom:updated>2020-03-17T10:15:10.308Z</atom:updated>
            <content:encoded><![CDATA[<h3>About Bob Martin’s talk — The Future of Programming (2016)</h3><h3>Overview</h3><p>I am a bit late to the party, but still. <a href="https://en.wikipedia.org/wiki/Robert%5FC.%5FMartin">Robert C. Martin</a>, colloquially known as “Uncle Bob”, gave an exciting <a href="https://www.youtube.com/watch?v=ecIWPzGEbFc">talk</a> in May 2016 about the future of programming. The relevance of his words still stands, and it is a beautiful history lesson about software engineering, programming as a profession with remarks about Agile and possible future of the industry.</p><p>Below you will find main topics from this talk that captured my attention, links to the facts, articles and papers he mentioned; plus, my personal opinion on some of them. Still, the best course of action is to watch the talk itself.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FecIWPzGEbFc%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DecIWPzGEbFc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FecIWPzGEbFc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/3c19e6649c559f1f2f2d07c699a615ca/href">https://medium.com/media/3c19e6649c559f1f2f2d07c699a615ca/href</a></iframe><h3>Objective C history</h3><p>In the beginning, Robert briefly mentions his version of the <a href="https://en.wikipedia.org/wiki/Objective-C#History">Objective C history</a> in early ’90s. From his point of view, Objective C had to die at that point because, in general, C++ was a better evolution of ANSI C and both languages competed on the same field. But a series of circumstances saved Objective C. <a href="https://en.wikipedia.org/wiki/Steve%5FJobs">Steve Jobs</a> was forced out from Apple in 1985 and founded <a href="https://en.wikipedia.org/wiki/NeXT">NeXT, Inc</a> to compete with Apple. There were not many programmers available on the market, but Objective C specialists experienced some problems finding new jobs. As Robert said:</p><blockquote><em>There were a bunch of guys on the street holding up signs “We will code Objective C for food.”</em></blockquote><blockquote><em>– Robert C. Martin</em></blockquote><p>NeXT hired them, and all these programmers produced <a href="https://en.wikipedia.org/wiki/NeXTSTEP">the NeXTSTEP operating system</a>. Within a few years, Apple announced that it would buy NeXT for $427 million, bringing Jobs back to the company. And Steve brought all the NeXT team along including all Objective C programmers. NeXTSTEP OS was part of the deal as well. It was the team that started to work on the <a href="https://www.cultofmac.com/303469/steve-jobs-drowned-first-ipod-prototype/">iPod prototype</a> and, as you can imagine, Objective C was the primary language. So, in short, that is how Objective C was resurrected from the dead. Or saved.</p><h3>Alan Turing</h3><p>During the talk, Robert references <a href="https://en.wikipedia.org/wiki/Alan%5FTuring">Alan Turing</a> a lot. Probably, the first person actually to write code that we can recognise as code, Robert said. In his works, Alan Turing defined variables, subroutines, floating-point principles, many things we use every day as programmers.</p><p>There is a remarkable paper from Alan Turing, <a href="https://londmathsoc.onlinelibrary.wiley.com/doi/abs/10.1112/plms/s2-43.6.544">“On computable numbers, with an application to the Entscheidungsproblem”</a> (November 1936) that set the limits of computer science. It defined the <a href="https://en.wikipedia.org/wiki/Turing%5Fmachine">Turing Machine</a>, a model for all computations. On the other hand, it proved the undecidability of the halting problem and <a href="https://en.wikipedia.org/wiki/Entscheidungsproblem">Entscheidungsproblem</a> and by doing so, found the limits of possible computation.</p><p>If you want to learn more about the guy, I highly recommend <a href="https://www.goodreads.com/book/show/2333956.The%5FAnnotated%5FTuring%5FA%5FGuided%5FTour%5FThrough%5FAlan%5FTuring%5Fs%5FHistoric%5FPaper%5Fon%5FComputability%5Fand%5Fthe%5FTuring%5FMachine">“The Annotated Turing”</a> book from <a href="https://en.wikipedia.org/wiki/Charles%5FPetzold">Charles Petzold</a> (the guy behind <a href="https://en.wikipedia.org/wiki/Microsoft%5FFoundation%5FClass%5FLibrary">Microsoft Foundation Class Library (MFC)</a> and former software engineer) that Robert mentions in the talk as well.</p><p>Robert says a lot about programming discipline and why it was supposed to be based on the shoulders of mathematicians. In his opinion, there are many problems with mentoring new programmers and lack of fundamental knowledge. This topic is a bit controversial but the funny is thing that Alan Turing predicted the problem after writing “a few hundreds of lines of code” more than 70 years ago:</p><blockquote><em>“One of our difficulties will be the maintenance of appropriate discipline so that we do not lose track of what we are doing.”</em></blockquote><blockquote><em>– Alan Turing, </em><a href="https://www.vordenker.de/downloads/turing-vorlesung.pdf"><em>Lecture to the London Mathematieal Society on 20 February 1947</em></a></blockquote><h3>A quick note about GOTO statement and what not to do</h3><blockquote><em>At the pre-ALGOL meeting held in 1959, </em><a href="https://en.wikipedia.org/wiki/Heinz%5FZemanek"><em>Heinz Zemanek</em></a><em> explicitly threw doubt on the necessity for GOTO statements; at the time no one paid attention to his remark, including </em><a href="https://en.wikipedia.org/wiki/Edsger%5FW.%5FDijkstra"><em>Edsger W. Dijkstra</em></a><em>, who later became the iconic opponent of GOTO. The 1970s and 1980s saw a decline in the use of GOTO statements in favour of the “structured programming” paradigm, with goto criticized as leading to “unmaintainable spaghetti code”.</em></blockquote><blockquote><em>– Wikipedia, </em><a href="https://en.wikipedia.org/wiki/Goto#Criticism"><em>GOTO</em></a></blockquote><p>So, in 1968, <a href="https://en.wikipedia.org/wiki/Edsger%5FW.%5FDijkstra">Edsger W. Dijkstra</a> wrote his quite famous <a href="https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf">“Go To Statement Considered Harmful”</a> article. And it was one of the first examples of programmers starting to improve the technology and the discipline itself. I mention this fact as an example because I agree with Robert on his thoughts:</p><blockquote><em>“What we have learned since the ’70s is more on what not to do than what to do.”</em></blockquote><blockquote><em>“If we have made any advances in software, since 1945, it is almost entirely in what not to do. Structured Programming was in what not to do — don’t use unrestrained GOTO. Functional Programming — don’t use assignment. Object-Oriented Programming — don’t use pointers to functions. What we have learned over the last 70-some years is more about what not to do, than what to do. There have been no radical advances in software technology. The craft of writing software remains roughly the same as it was in 1945 — a little more modern, but not essentially any different.”</em></blockquote><blockquote><em>– Robert C. Martin</em></blockquote><p>See? Almost all modern paradigms were built on top of the “not to do” practices. From Robert’s point of view, we are more or less capable of agreeing on bad things but it is tough for us to agree on something new and go in the same direction, and this is one of the biggest challenges we have with the discipline:</p><blockquote><em>“We have a problem: we do not agree on our own technical disciplines.”</em></blockquote><blockquote><em>– Robert C. Martin</em></blockquote><p>We know a lot about which things to avoid, hundreds of bad practices and anti-patterns. But, on the other hand, there are too few general principles to follow. We are learning and creating new languages to solve specific problems, dancing with generics on top of the generics, copy-pasting templates and consuming articles about syntax sugar as best development practices. But fundamentally, since the ’70s, not many things have changed in software itself. In the end, your program will operate with if statements, assignments and while loops.</p><blockquote><em>“You would recognise the code that Alan Turing wrote on the ACE machine. You would not like it, but you would recognise it.”</em></blockquote><blockquote><em>– Robert C. Martin</em></blockquote><h3>What happened to the discipline</h3><p>It is quite interesting to listen to the guy who experienced all the changes in the discipline during all these years. For example, Robert stated that back in the ’60–70s the situation with programmers looked like this:</p><blockquote>- Up to now programmers were disciplined professionals;</blockquote><blockquote>- They did not need a lot of management or process;</blockquote><blockquote>- They knew how to manage their time, communicate, and work together;</blockquote><blockquote>- They understood deadlines &amp; commitments. What to leave in and what to leave out.</blockquote><blockquote><em>– Robert C. Martin</em></blockquote><p>At that time, with the principles mentioned above, programmers built great software. Or, as Robert said, “They knew how to get big things done”:</p><ul><li><a href="https://en.wikipedia.org/wiki/IBM%5FSystem/360">IBM 360 Virtual Memory OS</a> — the first family of computers designed to cover the complete range of applications, from small to large, both commercial and scientific;</li><li>NASA Project <a href="https://www.nasa.gov/mission%5Fpages/mercury/index.html">Mercury</a> — the United States’ first man-in-space program;</li><li>NASA Project <a href="https://en.wikipedia.org/wiki/Project%5FGemini">Gemini</a> — second human spaceflight program;</li><li>NASA Project <a href="https://www.nasa.gov/mission%5Fpages/apollo/index.html">Apollo</a> — human spaceflight program which succeeded in landing the first humans on the Moon from 1969 to 1972;</li><li>Structured, Functional, Object-Oriented paradigms;</li><li>Fortran, Cobol, Algol, Lisp, C, Unix;</li><li>And many more.</li></ul><blockquote>I want to mention <a href="https://en.wikipedia.org/wiki/Margaret%5FHamilton%5F(software%5Fengineer)">Margaret Hamilton</a> — director of the Software Engineering Division of the MIT Instrumentation Laboratory, which developed on-board flight software for NASA’s Apollo program.</blockquote><p>And, at this point, let’s talk a little about Agile.</p><h3>Agile manifesto</h3><blockquote><em>In 2001, these seventeen software developers met at a resort in Snowbird, Utah to discuss lightweight development methods: Kent Beck, Ward Cunningham, Dave Thomas, Jeff Sutherland, Ken Schwaber, Jim Highsmith, Alistair Cockburn, Robert C. Martin, Mike Beedle, Arie van Bennekum, Martin Fowler, James Grenning, Andrew Hunt, Ron Jeffries, Jon Kern, Brian Marick, and Steve Mellor. Together they published the Manifesto for Agile Software Development.</em></blockquote><blockquote><em>– Wikipedia, </em><a href="https://en.wikipedia.org/wiki/Agile%5Fsoftware%5Fdevelopment#History"><em>The Manifesto for Agile Software Development</em></a></blockquote><blockquote><em>Note: By lightweight development methods they assumed rapid application development (</em><a href="https://en.wikipedia.org/wiki/Rapid%5Fapplication%5Fdevelopment"><em>RAD</em></a><em>), from 1991; the unified process (</em><a href="https://en.wikipedia.org/wiki/Unified%5FProcess"><em>UP</em></a><em>) and dynamic systems development method (</em><a href="https://en.wikipedia.org/wiki/Dynamic%5Fsystems%5Fdevelopment%5Fmethod"><em>DSDM</em></a><em>), both from 1994; </em><a href="https://en.wikipedia.org/wiki/Scrum%5F(software%5Fdevelopment)"><em>Scrum</em></a><em>, from 1995; Crystal Clear and extreme programming (</em><a href="https://en.wikipedia.org/wiki/Extreme%5Fprogramming"><em>XP</em></a><em>), both from 1996; and </em><a href="https://en.wikipedia.org/wiki/Feature-driven%5Fdevelopment"><em>feature-driven development</em></a><em>, from 1997.</em></blockquote><p>So, Robert was part of the group behind the manifesto, and his explanation fits well with my mind. Programmers were not just operators anymore, and they needed to be part of the whole process of creation. And Agile is about all the promises you make and not a list of tasks you follow. This perception has faded in the modern world, and Robert assumes that it happened when business got in the way. The business was totally in line with what the Agile movement offered, the whole set of principles made sense to them, and they understood discipline. However, the business started to take control of some of the engineering practices, and Agile helped them. In worst cases, programmers have to discuss technical debt, refactoring and technologies with the business and ask for permissions to control simple engineering things. The issue is that business does not always understand (and, frankly, should not) what programmers are doing. So, once project managers took control over Agile (via Scrum, for example), it became less technical. Ironically, one of Agile’s goals was to “heal the divide between business and programming” (<a href="https://en.wikipedia.org/wiki/Kent%5FBeck">Kent Beck</a>).</p><p>Robert believes that Agile has failed and that things have to change. Again. Programmers have to step up and define their profession, their practices, and the discipline they use because they are the ones who have the expertise to do so. Programmers have to handle technical risks and take these risks as professionals.</p><p>There is a helpful article from <a href="https://en.wikipedia.org/wiki/Martin%5FFowler%5F(software%5Fengineer)">Martin Fowler</a> — <a href="https://www.martinfowler.com/bliki/FlaccidScrum.html">Flaccid Scrum</a> about more or less the same matters.</p><blockquote><em>“The Scrum community needs to redouble its efforts to ensure that people understand the importance of strong technical practices. … If you’re looking to introduce Scrum, make sure you pay good attention to technical practices. We tend to apply many of those from Extreme Programming, and they fit just fine. XPers often joke, with some justification, that Scrum is just XP without the technical practices that make it work.”</em></blockquote><blockquote><em>– </em><a href="https://www.martinfowler.com/bliki/FlaccidScrum.html"><em>Martin Fowler</em></a></blockquote><p>I can recognise a lot of failed/struggled projects from my experience in the way Robert describes the phenomena:</p><blockquote><em>“Flaccid Scrum — an efficient business discipline coupled to an undisciplined engineering team, will very rapidly make a mess.”</em></blockquote><blockquote><em>– Robert C. Martin</em></blockquote><p>Also, an interesting point was made about the fact that Agile is in line with Alan Turing’s thoughts on the future of the profession. Turing said that discipline and ability are essential parts of the prosperous future, and Agile declares that discipline, craftsmanship and professionalism are the directions to go.</p><h3>Historical references</h3><p>These are links to some hardware, software and events mentioned in the talk.</p><ul><li><a href="https://en.wikipedia.org/wiki/Automatic%5FComputing%5FEngine">Automatic Computing Engine</a> (ACE) — a British early electronic stored-program computer designed by Alan Turing;</li><li><a href="https://en.wikipedia.org/wiki/Delay%5Fline%5Fmemory#Mercury%5Fdelay%5Flines">Delay Line Memory</a> (Mercury delay lines) — a form of computer memory that was used on some of the earliest digital computers;</li><li><a href="https://en.wikipedia.org/wiki/Cathode-ray%5Ftube">Cathode-Ray Tube</a> — have been used as memory devices known as <a href="https://en.wikipedia.org/wiki/Williams%5Ftube">Williams tube</a>;</li><li><a href="https://en.wikipedia.org/wiki/Lisp%5F(programming%5Flanguage)">Lisp</a> — the second-oldest high-level programming language in widespread use today that refuses to die;</li><li><a href="https://en.wikipedia.org/wiki/Simula">Simula 67</a> — considered the first object-oriented programming language;</li></ul><h3>Bottom line</h3><blockquote><em>Professionalism. Discipline. Attention to details.</em></blockquote><p>These are the base principles for better programmers. It sounds easy and obvious. Why not to try?</p><h3>P.S.</h3><p>Sadly, this talk heavily foreshadows the <a href="https://www.bloomberg.com/news/articles/2019-06-28/boeing-s-737-max-software-outsourced-to-9-an-hour-engineers">situation</a> with Boeing 737 Max.</p><blockquote>Originally posted <a href="https://justsitandgrin.net/posts/bob_martin_the_future_of_programming/">here</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f9408ee2e8ae" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How emojis evolve over time]]></title>
            <link>https://uxdesign.cc/emojis-over-time-6a10c9f1d288?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/6a10c9f1d288</guid>
            <category><![CDATA[ui]]></category>
            <category><![CDATA[visual-design]]></category>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[emoji]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Sun, 12 Jan 2020 12:59:59 GMT</pubDate>
            <atom:updated>2020-01-16T04:20:33.984Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently, I noticed that one of the emojis on iOS has changed between iOS updates. It was enough to make me curious about recent changes, and now I have all the diffs for emojis between iOS 13.0 and iOS 13.3. In the article below, I will explain how I collected the changes, how you can do the same and describe the significant differences in emojis between releases. I was never particularly interested in the Emoji phenomenon, so for me, this trip was informative. You may like it too.</p><h3>Historical reference</h3><p>According to <a href="https://en.wikipedia.org/wiki/Emoji">Wikipedia</a>, Emoji are ideograms and smileys used in electronic messages and web pages. Emoji exist in various genres, including facial expressions, common objects, places and types of weather, and animals. They are much like emoticons, but emoji are actual pictures instead of typographic. Originally meaning pictograph, the word emoji comes from Japanese <em>e</em> (絵, “picture”) + <em>moji</em> (文字, “character”); the resemblance to the English words emotion and emoticon is purely coincidental.</p><p>From 2010 onward, some emoji character sets have been incorporated into Unicode, a standard system for indexing characters, which has allowed them to be standardised across different operating systems.</p><p>I recommend you to read the <a href="https://en.wikipedia.org/wiki/Emoji#The%5Fmodern%5Femoji">“The modern emoji”</a> section on Wikipedia. There are a lot of interesting facts about the standard, like:</p><blockquote><em>Some Apple emoji are very similar to the SoftBank standard, since SoftBank was the first Japanese network the iPhone launched on. For example, U+1F483 💃 DANCER is female on Apple and SoftBank standards but male or gender-neutral on others.</em></blockquote><h3>How does the comparison work</h3><p>It is tricky to convince iOS to tell you the truth about all the available emojis. To solve the problem, I took a shortcut and decided to use emojis from the Unicode standard. The current revision is <a href="http://www.unicode.org/reports/tr51/tr51-16.html">UTS #51 Unicode Emoji, Version 12.1</a>. There are <a href="https://unicode.org/Public/emoji/12.1/">some files</a> with examples, and for testing purposes, emoji-test.txt looked like a complete set of all variants. So, I built a simple tool to generate images from all available emojis and compare them with a simple diff. You can read more about the process and check the implementation on GitHub - <a href="https://github.com/dive/emojis-over-time">dive/emojis-over-time</a>.</p><h3>Notes</h3><p>To avoid unnecessary noise, I use the following limitations for the comparison:</p><ul><li>Ignore all variations for <a href="https://en.wikipedia.org/wiki/Emoji#Skin%5Fcolor">skin tones</a> (can be enabled in the tool);</li><li>Skip all unqualified &amp; minimally-qualified emojis from the standard (check the <a href="https://unicode.org/Public/emoji/12.1/emoji-test.txt">emoji-test.txt</a> for explanation). Can be enabled in the tool as well.</li></ul><h3>Comparison</h3><p>As I said, I generated all emojis for iOS 13.0–13.3, removed all emojis without any changes and then build diffs for the remaining characters. All comparisons were made retrospectively, means that I compare iOS 13.0 with 13.1, 13.1 with 13.2, etc.</p><p>All images follow the same pattern:</p><ul><li>The initial version is on the left side (e.g., for iOS 13.0 in the first example below);</li><li>An updated version is in the middle (e.g., for iOS 13.1);</li><li>Diff on the right.</li></ul><h3>iOS 13.0 → 13.1</h3><h4>Anti-aliasing</h4><p>The most obvious difference is the fact that they change a bit how they render the final images. It seems that they improved <a href="https://en.wikipedia.org/wiki/Spatial%5Fanti-aliasing">anti-aliasing</a> to make image borders more contrast and visible on the screen (especially, on dark backgrounds. Maybe, it is just a pending improvement for the dark mode). Check these light borders on the diff image.</p><p>Also, pay attention to the glare in the eyes. For some reason, it was decided to change their shape from round to semicircle.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l_HhhCk82dK2E4AbVtyEEg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cMXQLwuPrH4GPKxi51U57Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dWZH6EkPx9bI1ywylH1ucQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5oVwEuzfBgmUYMK74X3Mrw.png" /></figure><h4>The shape of the heart</h4><p>The shape of the heart symbol was re-designed. It became more elongated in height, and they added a gradient.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J84bKc3KE91Yn8dYhJPtRg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KkIwBMsvxY2evv2cwSeQNg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZrKa-ZJ7Cww4vGop-o78bw.png" /></figure><h4>Malaysia flag</h4><p>Apple made a mistake in iOS 13.1, the flag of Malaysia was re-implemented with obvious errors (<a href="https://www.soyacincau.com/2019/09/28/apple-ios-13-1-malaysia-flag-emoji/">“Apple displays Malaysia flag emoji incorrectly on iOS 13.1 and 13.1.1”</a>).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HfjIvfm-pzg0RoXFB_PlfQ.png" /></figure><h4>Mermaid</h4><p>This is my favourite change. The mermaid now holds a trident like a merman counterpart. Also, they changed a bit the shape of her hair.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C2nMujb4-3ic7V8u1ny0EQ.png" /></figure><h4>Hedgehog</h4><p>The baseline for the hedgehog was slightly lowered. Apparently, that it fits better into the text.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FrmVnxzJYC9P4SVNhqNU-Q.png" /></figure><h4>Octopus</h4><p>The octopus now has suckers on tentacles.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*feEa7pidDV_W6BTuNZJyhw.png" /></figure><h4>Squid</h4><p>Previously, the squid emoji had some issues with the real-life, and <a href="https://www.montereybayaquarium.org/">The Monterey Bay Aquariums</a> <a href="https://twitter.com/MontereyAq/status/1070410363521269760">noticed</a> it. Now it is fixed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WqKUW4SigmLNg4UzcJnnxw.png" /></figure><p>And that’s all for iOS 13.1.</p><h3>iOS 13.1 → 13.2</h3><h4>Gender-neutral fashion</h4><p>This is a new world to me and I was surprised by the diffs for iOS 13.2, but then I realised that it is somehow related to the gender. So, with iOS 13.2 all emojis without a specific gender in the description are gender-neutral. Let’s see how they look.</p><p>Noticeable and frequent changes:</p><ul><li>Haircuts were changed to the neutral style;</li><li>Colours are more indifferent to avoid associations;</li><li>Everyone began to wear clothes, and there is no more naked torso.</li></ul><p>P.S. Check the <a href="https://blog.emojipedia.org/unicode-brings-forward-gender-neutral-timeline/">“Unicode Brings Forward Gender Neutral Timeline”</a> blog post from Emojipedia if you want to know more.</p><p>P.P.S. As before, iOS 13.1 emoji is on the left, iOS 13.2 in the middle, the diff is on the right side.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FnZU1YJ_oSkjDkaXRDs0LQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5-Nr0c8NYzCKi_AxJDwgJQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1a7b95XyZ9el32ygpbeIgw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4eSNZFMYLUEsHzpoYlQfsA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MUpwprlOm_4Rn6PLrkJZlw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E-K5PoIJX02yLT0LghnQRA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dI4cY7s2RsyAt4Ppsyt28A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*obyNhy2xHbWUchwIv5hZng.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AR4F0nl3uXhB1KptQYK9-Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4NoPVumOApzkTkYq7EYIkA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D3So7F2rB8CnP5frDdNDiA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ef0url0-exUUC4omntsbaQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VOHj5P330JNvCE8Nkh0jNA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BdSYefTiNXWjCGB1u1frWw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xFP1rmRKt37tEn875rMHRw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_FUr7qvMR2o4_6JPMsd3ow.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZJoHwFYipgl1vzSsJQSiEA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uylfvgSyOxRsSAy3VPDcoA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KCr6Jfa8K2FMu4Oqh-yhPg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RCbywlIIMp78mXrv_9U8lQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XPmqkYRF9LGaAGhD0dNq8A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1nE8xeTdYu8kFD-WAPoElg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eGhhFRwM-fn6KXXoiBYvGw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VFG-17Sp4w2GQS8mz51OiQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jyrU5fyajEfI0JALGITKPw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2p801G37fdWdvHgS8RakNQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CAVhmUylKIgVfNlrZfHk8g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G8piLleuJ48KASq7peKD2g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7dLO_JkmvmhOhU_2YzkHBg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aeZ663YKD_gmHkgo5yPyXA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hu7x975gZRMd4x0cD2drPg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1ZJXjQEl3l1hX0MBquF4_g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_95vjIrzoHOv2MQqV9TZ3Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bLXbUyF63kWmegLJ5DwVtg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-274suPObDD1iPHGC29fWw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MOd8R4sDRP_6zobi4ay8-g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tZvXGERZNQatyCcw0zhFgQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9g7BA2BOkkkQJe9rjzwlRg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pcXmwOK-XkFGJqeIAsaGGA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-PC0ifqRwb3QeJXqpXJanQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kB3vjJow_IC_3UBaMUouBQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oqP7kn5HFx0TDpqF2q-N7A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W3AcnFe2dAYTwlsNfI7ltw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mu-WZKrYO7H4MNL9w9gkNA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fzvi2FOBcdFZmjxQ8HldYg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Lu7-NFWR3XTCu6pbj6b63Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oLelCtdHMdWIpaFAXaADTA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FKz7_0BbOfDZRDMrybfR4Q.png" /></figure><h4>Malaysia flag</h4><p>The flag of Malaysia now correctly displays a red stripe.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C51VZprnvuC9C3dpdq4eEQ.png" /></figure><h4>Ear</h4><p>The ear emoji has been re-designed to appear more like the ear.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UcJGYLNuY6_NybUqqK_WgA.png" /></figure><h4>Hair colour</h4><p>Blond hair now has realistic colour.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qGVy23FwhkY3c6LtUkIRgQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KDnO-64gQNItgM3K-Q59wA.png" /></figure><p>There are no changes in emojis between iOS 13.2 and iOS 13.3 releases. So, our journey ends here.</p><p>There is no practical benefit in the article, just my curiosity and desire to know more about the world around me. Anyway, I am surprised that companies like Apple pay a lot of attention to the Emoji world; also, I am impressed by the number of details in emojis and how they develop over time. Will follow the topic as a hobby.</p><p>Originally posted <a href="https://justsitandgrin.net/posts/emojis_over_time/">here</a>. Follow me on <a href="http://twitter.com/justsitandgrin">Twitter</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6a10c9f1d288" width="1" height="1" alt=""><hr><p><a href="https://uxdesign.cc/emojis-over-time-6a10c9f1d288">How emojis evolve over time</a> was originally published in <a href="https://uxdesign.cc">UX Collective</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift Package Manager builds iOS frameworks (Updated. Xcode 10.2 Beta)]]></title>
            <link>https://medium.com/bumble-tech/swift-package-manager-builds-ios-frameworks-updated-xcode-10-2-beta-19b3e6741bda?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/19b3e6741bda</guid>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[swift-package-manager]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Mon, 25 Feb 2019 13:53:22 GMT</pubDate>
            <atom:updated>2020-12-31T18:18:21.255Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0nxznASn3SY8ekCY-DaNXA.jpeg" /></figure><h3>Swift Package Manager builds iOS frameworks</h3><h4>(Updated. Xcode 10.2 Beta)</h4><p>Swift Package Manager doesn’t work with iOS. That’s probably all you can say about the current state of SPM, but insomnia forced me to expand on the issue and compile the following essay.</p><h3>TL;DR</h3><ul><li>Yes, you can build iOS frameworks with Swift Package Manager;</li><li>Yes, you can adjust settings via .xcconfig and reuse generated .xcodeproj in a real iOS application without 3rd party tools to parse a project structure, scripts on Ruby, etc.;</li><li>Yes, you can use swift build to build your package but only as a library (but with some additional limitations);</li><li>No, you cannot use swift test because you have to spawn a simulator to run them.</li></ul><h3>Current State of Swift Package Manager</h3><p>iOS support is a hot topic in the <a href="https://swift.org/package-manager/">Swift Package Manager</a> community, and from time to time someone raises this same question again but the following comments sum up the community’s reactions (<a href="https://forums.swift.org/t/spm-roadmap/6870">full thread</a> on forums.swift.org):</p><blockquote><a href="https://forums.swift.org/u/rballard"><em>@Rick Ballard</em></a><em><br></em>I think that this will be best provided by native IDE integration. However, in the meantime, I’d welcome contributions to help improve Xcode’s project generation support.</blockquote><blockquote><a href="https://forums.swift.org/u/akashivskyy"><em>@Adrian Kashivskyy</em></a><em><br></em>The last thing I want from a platform-agnostic open-source package manager is built-in integration with a single-platform commercial closed-source IDE. :confused: I think this should be done independently by the DT team, without any special favouritism by SPM.</blockquote><p>And you know what? I agree with these statements. Especially after some research. In general, SPM is a very ‘young’ and inflexible project. There are a lot of limitations, especially around generate-xcodeproj options of the swift package tool. And this is understandable given that Swift is a language, and all related tools need to be platform-agnostic as far as possible. Yeah, iOS is the biggest Swift consumer, and Apple contributes to Swift mostly because of iOS, but…</p><p>It’s going to be almost impossible to grow Swift into a mature technology if you’re limited and restricted by Xcode / iOS specific things / etc. And, it seems, this is the primary goal for Swift to remain just be a language. The fate of Objective C is a good example of why the Apple and Swift’s communities are trying to be agnostic. They are trying to build something big, and lack of iOS support is the price (among many others) at the moment. :kiss:</p><p>Having said this, we have exciting news about SPM and iOS friendship. <a href="https://forums.swift.org/t/accepted-with-modifications-se-0236-package-manager-platform-deployment-settings/18420">SE-0236: Package Manager Platform Deployment Settings</a> is accepted with some modifications. And the implementation of this proposal will help a lot to move forward in the case of iOS. The main goal is clear and straightforward:</p><blockquote><em>Packages should be able to declare the minimum required platform deployment target version. SwiftPM currently uses a hardcoded value for the macOS deployment target. This creates friction for packages which want to use APIs that were introduced after the hardcoded deployment target version.</em></blockquote><p>Why will it completely fail to solve the problem with iOS? Just read the “<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0236-package-manager-platform-deployment-settings.md">This option doesn’t resolve these problems</a>” section.</p><h3>Xcode 10.2 Beta</h3><p><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0236-package-manager-platform-deployment-settings.md">SE-0236</a> was accepted and implemented in Swift 5, and Apple shipped it with the latest Xcode 10.2 beta. This means that you can specify an iOS as a deployment target for your packages with a simple line in your Package.swift file:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6af324ab79f974077f76223b3413bdc5/href">https://medium.com/media/6af324ab79f974077f76223b3413bdc5/href</a></iframe><p>See an example in xcode_10_2_beta branch in the example <a href="https://github.com/dive/spm-ios-example/tree/xcode_10_2_beta">repository</a>. It is still a beta implementation, and you will have a lot of issues with build command, and run doesn’t work either, but it is a step toward eventual iOS support.</p><p>I hope that Apple will announce something good at WWDC’19. A new IDE for Swift, perhaps? Or open-sourced xcodebuild? Or xcodebuild replacement based on llbuild? We’ll see. The current state is as complicated as it can be. We are trying to inject open-sourced platform-agnostic tools into a legacy (?) world of Xcode, and this problem can only be solved in one of two ways: either iOS specific build tools go open source, or Xcode team supports Swift infrastructure.</p><h3>Is it possible to build an iOS framework with SPM? Yes! Absolutely!</h3><p>Search for solutions for building iOS frameworks with SPM on DuckDuckGo and you will find some instructions (<a href="https://github.com/j-channings/swift-package-manager-ios">1</a>, <a href="https://www.ralfebert.de/ios-examples/xcode/ios-dependency-management-with-swift-package-manager/">2</a>). But all of them have this one step that I hate: sudo gem install xcodeproj :disgusting:. Can we do any better? Let’s give it a try.</p><p>First of all, let’s generate a template:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/47ab389e77b52259cd3141a9c3c60bd1/href">https://medium.com/media/47ab389e77b52259cd3141a9c3c60bd1/href</a></iframe><p>Now we have to convince SPM that we want an iOS project when it generates xcodeproj. How? With xcconfig, of course. Create a file ios.xcconfig and add it to ./Sources folder. For example, let’s start with a basic version:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7e01d7779e4affcb032efdfa95a5bb98/href">https://medium.com/media/7e01d7779e4affcb032efdfa95a5bb98/href</a></iframe><p>Looks good. Let’s see what SPM thinks of it:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b525377c5f8dbf3dcfb0a0558944b0c6/href">https://medium.com/media/b525377c5f8dbf3dcfb0a0558944b0c6/href</a></iframe><p>Didn’t know about xcconfig-overrides? Me neither. It’s a hidden and undocumented feature (<a href="https://github.com/apple/swift-package-manager/commit/713a3e603e6682fe431074617343eb05852d10c5">commit</a>), thanks to <a href="https://github.com/ddunbar">@Daniel Dunbar</a>! Time to ask Xcode what it thinks of it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0otqjbUu76si-vfY" /></figure><p><strong>Note:</strong> You do not have to specify a custom .xcconfig file if you are using Xcode 10.2 Beta with Swift 5 Toolchain. Check the <a href="https://github.com/dive/spm-ios-example/tree/xcode_10_2_beta">branch</a> for more details.</p><p>It works! Let’s celebrate! But nope. We’re not there yet, need to dig deeper. Let’s check how the ‘Unit Tests’ target works, for example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b124465059f60b3299325060ca9ae74d/href">https://medium.com/media/b124465059f60b3299325060ca9ae74d/href</a></iframe><p>It doesn’t. Due to this strange and suspicious XCTestCaseEntry. What is this? According to the <a href="https://github.com/apple/swift-corelibs-xctest/blob/237d97cadbc3c51d575c705bf8e4d8456a12827a/Sources/XCTest/Public/XCTestCase.swift#L24">swift-corelibs-xctest</a> source code:</p><blockquote><em>This is a compound type used by </em><em>XCTMain to show tests to run. It combines an </em><em>XCTestCase subclass type with the list of test case methods to invoke on the class.</em></blockquote><p>And the typealias looks like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bf77a4a96fed2d82726cf8e3b8337cd3/href">https://medium.com/media/bf77a4a96fed2d82726cf8e3b8337cd3/href</a></iframe><p>Why doesn’t it work? For the same reason:</p><blockquote><em>CoreLibs XCTest only supports desktop platforms</em></blockquote><p>Thanks go to <a href="https://github.com/larryonoff">@larryonoff</a> for <a href="https://github.com/apple/swift-corelibs-xctest/pull/176">his work</a> on multi-platform support. But unfortunately we still can’t use it for our needs. Join this <a href="https://github.com/apple/swift-corelibs-xctest/pull/61">Add Unit Testing Infrastructure</a> thread if you want to learn more about the current state of swift-corelibs-xctest. We will move on and apply the fix to XCTestManifests.swift:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/74e936270471f8dc05ccc59289524b2a/href">https://medium.com/media/74e936270471f8dc05ccc59289524b2a/href</a></iframe><p>See this &amp;&amp; !os(iOS)? Let’s keep going. Run Tests again and… We got what we need.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Y4ufVTcdxxf5zBJn" /></figure><p>Then I created a simple iOS ExampleApp and added the generated xcodeproj as a dependency. Of course, I’ve added some iOS specific code to the framework:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5913f6babac9d15094087fa5bc565960/href">https://medium.com/media/5913f6babac9d15094087fa5bc565960/href</a></iframe><p>And then reuse it from the example app:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0b1572ed84589c2293d49c8168fa4c65/href">https://medium.com/media/0b1572ed84589c2293d49c8168fa4c65/href</a></iframe><p>The full example is available on <a href="https://github.com/dive/spm-ios-example">GitHub</a>. Thanks to CLANG_MODULES_AUTOLINK, all iOS frameworks will be linked automatically. I didn’t try more complex scenarios (where one iOS module depends on another, etc.) because it’s not my goal here. But, in general, it does just work albeit some limitations. SPM doesn’t set up our xcconfig for some targets, and you have to include the SPM-generated .xcodeproj to your .xcodeproj, but all these tradeoffs seem reasonable in the interests of this research and achieving our current goal.</p><h3>Back to Swift Package Manager</h3><p>See. We can do better 🥳. But we forgot about SPM during this Xcode journey. Let’s close our fancy, dark-themed Xcode, open Terminal and run swift build for our iOS’ish package (I’m going to use the package from the <a href="https://github.com/dive/spm-ios-example">example project</a> mentioned above):</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1eadbd1524652db4a021b045b4086f61/href">https://medium.com/media/1eadbd1524652db4a021b045b4086f61/href</a></iframe><p>Okay. There’s no such ‘UIKit’ module. Can we do better? I doubt it, but let’s try. First of all, we have to find out where SPM gets all these environment variables from. We can ask it with swift build — verbose:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/59780ebbfe82fa8c59a70cd7d4b769c8/href">https://medium.com/media/59780ebbfe82fa8c59a70cd7d4b769c8/href</a></iframe><p>Nice. No smoke or mirrors. Let’s try to changing some swiftc options to build the project against proper sdk and target:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/51ed1fc996f34d62c1923d2a3818a64a/href">https://medium.com/media/51ed1fc996f34d62c1923d2a3818a64a/href</a></iframe><p>Looks better. We built the binary:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e0f61609d17ffc32d07e8ae8d41d6cf1/href">https://medium.com/media/e0f61609d17ffc32d07e8ae8d41d6cf1/href</a></iframe><p>Let’s carry out some inspections, just to make sure that everything is OK:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f08ace35f8e0fc4d26dd388aa35b9b94/href">https://medium.com/media/f08ace35f8e0fc4d26dd388aa35b9b94/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2bb9cd522852788793f3bb88b5dd910d/href">https://medium.com/media/2bb9cd522852788793f3bb88b5dd910d/href</a></iframe><p>lipo is a bit useless in this case because we were building for a simulator, but nm shows us everything we need to know — iOS frameworks symbols are available. Unfortunately, swift build doesn’t produce .framework by default. I think it’s doable even in this case but let’s look at that ‘next time’.</p><h3>Epilogue: swift test</h3><p>And the final call. We already have one unit-test for our package: it uses UIKit, and I would rate this experiment as successful if we could run the test target with swift test. It’s almost impossible though, because usually unit-tests for simulator have to spawn to a simulator process. I don’t even think that it’s possible for an <em>actual</em> iOS project. Anyway.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/11b289e1ff5d47cc378842295a3a81f2/href">https://medium.com/media/11b289e1ff5d47cc378842295a3a81f2/href</a></iframe><p>And there’s another problem. .xctest bundle is compiled but xctest tool gets confused with search paths:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2ad67eae4606148b5d74572a1c98a951/href">https://medium.com/media/2ad67eae4606148b5d74572a1c98a951/href</a></iframe><p>Likely, swift build &amp; test produce beneficial debug information and store it in .build/debug.yaml with all previous options and arguments. This goes for the options for a module itself as well, so it’s time for our command line friends again:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/87db0efd31bed7343e19a5500510074a/href">https://medium.com/media/87db0efd31bed7343e19a5500510074a/href</a></iframe><p>As you can see, for some reasons, it tries to link UIKit.framework twice:</p><ul><li>via the /System/Library/Frameworks path</li><li>and via the expected @rpath/libswiftUIKit.dylib.</li></ul><p>Let’s check the information from the module itself with otool, to be sure that load is describing the correct framework to link:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/88df033cd5e1e042bf1fe855a881b00d/href">https://medium.com/media/88df033cd5e1e042bf1fe855a881b00d/href</a></iframe><p>Seems correct to me. So, to eliminate the confusion let’s pass the linking option directly with -Xswiftc “-lswiftUIKit”:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/35a70ecf7de34038028845ed6acad1e0/href">https://medium.com/media/35a70ecf7de34038028845ed6acad1e0/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7bd313f9bb6f023fb8ead728ce77223a/href">https://medium.com/media/7bd313f9bb6f023fb8ead728ce77223a/href</a></iframe><p>Yep, but built for simulator (not macOS)). This is my final conclusion, my friend. It doesn’t take that much effort to link proper frameworks, but it’s impossible to run these tests for iOS device or simulator without SPM support. It seems that not even xcrun with xctest are up to the job. xcodebuild assistance is needed here. But enough of these weird logs and useless rants, let’s summarise.</p><h3>Summary</h3><p>Thanks for reading, first of all! So, what did we learn?</p><ul><li>We can use SPM in sporadic cases for iOS, just for integration, thanks to .xcconfig;</li><li>The future of the friendship between iOS and SPM is unsure even with this <a href="https://forums.swift.org/t/accepted-with-modifications-se-0236-package-manager-platform-deployment-settings/18420">SE-0236</a> proposal;</li><li>Swift build and test helpers are useless to us without iOS-specific features and full Xcode support. And that’s unlikely to happen. Of course, SPM can be integrated on top of Xcode by Xcode team. For example, they will extend xcodebuild functionality. But concerning SPM, it is going to be a different story.</li></ul><p>Regarding SPM. Generally, I think it’s doable, and we can improve SPM to support any platform you like. My best advice at the moment is to introduce pipeline plugins for SPM, enabling you to transfer the control flow to a separate tool, with expected input and output. Something like Xcode custom build phases but is smarter and more flexible. It will allow SPM to be platform-agnostic as now, but the Xcode team can create a plugin for the whole iOS flow support. Or Uber. Or Google. Or me. Whatever.</p><p>Stay tuned and hydrated!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=19b3e6741bda" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bumble-tech/swift-package-manager-builds-ios-frameworks-updated-xcode-10-2-beta-19b3e6741bda">Swift Package Manager builds iOS frameworks (Updated. Xcode 10.2 Beta)</a> was originally published in <a href="https://medium.com/bumble-tech">Bumble Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Xcode 10.2, macOS Mojave 10.14.4, iOS 12.1 and other betas]]></title>
            <link>https://medium.com/bumble-tech/xcode-10-2-macos-mojave-10-14-4-ios-12-1-and-other-betas-99ee9bf4f858?source=rss-47536a8cb274------2</link>
            <guid isPermaLink="false">https://medium.com/p/99ee9bf4f858</guid>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift-package-manager]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Artem Loenko]]></dc:creator>
            <pubDate>Wed, 30 Jan 2019 13:29:30 GMT</pubDate>
            <atom:updated>2020-12-31T16:21:42.293Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-FTj4txdRUHa5B1byS-Npw.jpeg" /></figure><p>New betas are here and these are some of the most important things that I have learned about them.</p><h3><a href="https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_beta_release_notes/swift_5_release_notes_for_xcode_10_2_beta">Swift 5 for Xcode 10.2 beta</a></h3><h4>Swift</h4><p>Firstly, the latest Xcode beta is bundled with the following Swift version:</p><pre>Apple Swift version 5.0 (swiftlang-1001.0.45.7 clang-1001.0.37.7)<br>Target: x86_64-apple-darwin18.2.0<br>ABI version: 0.6</pre><p>Let’s start with the most exciting news:</p><blockquote><em>Swift apps no longer include dynamically linked libraries for the Swift standard library and Swift SDK overlays in build variants for devices running iOS 12.2, watchOS 5.2, and tvOS 12.2. As a result, Swift apps can be smaller when deployed for testing using TestFlight, or when thinning an app archive for local development distribution.</em></blockquote><p>Application Binary Interface stability is coming! And this is excellent news. I think this is the one of the most significant issues at the moment with Swift. Not because of side-effects but because of Swift’s failure to deliver on previous promises. Anyway, I even know people who rewrite their Apple Watch extensions to Objective C to reduce the size of binary (something like 15MB vs ~1MB in Objective C). If you want to know more about the state of ABI, follow the links: <a href="https://swift.org/abi-stability/#data-layout">Swift — ABI Dashboard</a> and <a href="https://github.com/apple/swift/blob/master/docs/ABIStabilityManifesto.md">Swift ABI Stability Manifesto</a>.</p><p>The @dynamicCallable attribute lets you call named types like you call functions using a simple syntactic sugar. The primary use case is dynamic language interoperability. (<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0216-dynamic-callable.md">SE-0216</a>)</p><p>Example:</p><pre>@dynamicCallable struct ToyCallable {<br> func dynamicallyCall(withArguments: [Int]) {}<br> func dynamicallyCall(withKeywordArguments: KeyValuePairs&lt;String, Int&gt;) {}<br>}</pre><pre>let x = ToyCallable()</pre><pre>x(1, 2, 3)<br>// Desugars to `x.dynamicallyCall(withArguments: [1, 2, 3])`</pre><pre>x(label: 1, 2)<br>// Desugars to `x.dynamicallyCall(withKeywordArguments: [“label”: 1, “”: 2])</pre><p>This is a huge topic and I have mixed feelings about the feature. So, do read the <a href="https://www.hackingwithswift.com/articles/126/whats-new-in-swift-5-0">“What’s new in Swift 5.0”</a> post from Paul Hudson if you want to know more about what is coming.</p><blockquote><em>Swift 3 mode has been removed. Supported values for the </em><em>-swift-version flag are 4, 4.2, and 5.</em></blockquote><p>The time has come. Source compatibility with Swift 3 is no more. It was expected and announced with Swift 5 Roadmap, but still. I highly recommend that you refresh your memory with <a href="https://swift.org/blog/5-0-release-process/">“Swift 5.0 Release Process”</a> because Swift 5 is almost here. Get ready.</p><blockquote><em>In Swift 5 mode, switches over enumerations that are declared in Objective-C or that come from system frameworks are required to handle </em>unknown cases<em> — cases that might be added in the future, or that may be defined privately in an Objective-C implementation file. Formally, Objective-C allows storing any value in an enumeration providing it fits in the underlying type.<br>These unknown cases can be handled by using the new </em><em>@unknown default case, which still provides warnings if any known cases are omitted from the switch. They can also be handled using a normal </em><em>default case.</em></blockquote><blockquote><em>If you’ve defined your own enumeration in Objective-C and you don’t need clients to handle unknown cases, you can use the </em><em>NS_CLOSED_ENUM macro instead of </em><em>NS_ENUM. The Swift compiler recognises this and doesn’t require switches to have a default case.</em></blockquote><blockquote><em>In Swift 4 and 4.2 modes, you can still use </em><em>@unknown default. If you omit it, and an unknown value is passed into the switch, the program traps at runtime, as does Swift 4.2 in Xcode 10.1. (</em><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md"><em>SE-0192</em></a><em>)</em></blockquote><p>It was, and is, a pain especially if you use <em>no default</em> approach within switches. I remember the ugly workarounds for the new .provisional option of UNAuthorizationOptions property that was introduced in iOS 12. Now, with an unknown case it’s much easier to handle such scenarios.</p><h3>Swift Package Manager</h3><blockquote><em>Packages can now customise the minimum deployment target setting for Apple platforms when using the Swift 5 Package.swift tools-version. Building a package emits an error if any of the package dependencies of the package specify a minimum deployment target greater than the package’s own minimum deployment target. (</em><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0236-package-manager-platform-deployment-settings.md"><em>SE-0236</em></a><em>)</em></blockquote><p>The most important news for me concerns Swift Package Manager. Technically, this change can solve a lot of issues that prevent SPM to be useful in the iOS world. In my previous article “<a href="https://dive.github.io/swift-package-manager/ios/2019/01/20/swift_package_manager_vs_ios.html">Swift Package Manager builds iOS frameworks</a>” I tried to analyse the current state of SPM in the context of iOS development. And now it seems that I’m going to have to reevaluate my thoughts and conclusions.</p><p>There are some bad issues as well:</p><blockquote><em>Some projects might experience compile time regressions from previous releases;</em></blockquote><blockquote><em>Swift command line projects crash on launch with “dyld: Library not loaded” errors.<br></em><strong><em>Workaround</em></strong><em>: Add a user-defined build setting </em><em>SWIFT_FORCE_STATIC_LINK_STDLIB=YES</em>.</blockquote><p>A lot of issues have been resolved and as well as other points in the <a href="https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_beta_release_notes/swift_5_release_notes_for_xcode_10_2_beta">changelog</a> related to Swift 5, but they are specific to what you do. Check them, maybe you want to use inherit designated initialisers with variadic parameters, or you were blocked by the deadlock problem due to complex recursive type definitions involving classes and generics, or you are struggling with generic type alias within a @objc method.</p><h3><a href="https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_beta_release_notes">Xcode 10.2 beta</a></h3><h4>Apple Clang Compiler</h4><p>There are a lot of new warnings for Apple Clang Compiler. And most of them are related to frameworks and modules. It’s quite interesting because it can be associated with Swift Package Manager integration as a dependency tool. The most important ones, in my opinion, are:</p><blockquote><em>A new diagnostic identifies framework headers that use quote includes instead of framework style includes. The warning is off by default but you can enable it by passing </em><em>-Wquoted-include-in-framework-header to clang;</em></blockquote><blockquote><em>Public headers in a framework might mistakenly </em><em>#import or </em><em>#include private headers, which causes layering violations and potential module cycles. There’s a new diagnostic that reports such violations. It’s OFF by default in clang and is controlled by the </em><em>-Wframework-include-private-from-public flag;</em></blockquote><p>The use of @import in framework headers prevent headers being used without modules. A new diagnostic detects the use of @import in framework headers when you pass the -fmodules flag. The diagnostic is OFF by default in clang and is controlled using the -Watimport-in-framework-header flag;</p><p>Previously, omitting the framework keyword when declaring a module for a framework didn’t affect compilation but it silently did the wrong thing. A new diagnostic, -Wincomplete-framework-module-declaration, and a new fix-it suggests adding the appropriate keyword. This warning is on by default when you pass the -fmodules flag to clang.</p><p>Firstly, how to turn them on: Goto to <strong><em>Build Settings</em></strong> for your application target, find <strong><em>“Apple Clang — Custom Compiler Flags”</em></strong> and put the desired flag to <strong><em>“Other C Flags”</em></strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-uIkMUjPi1Lhp1ZS" /></figure><p>I tried to build an old, Objective C-based application and found a lot of issues with private headers in public framework headers:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*q7ezl22AJXdMWIO3" /></figure><p>And some issues with double-quoted imports within frameworks:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zpnEqxfrZXl0Qrx6" /></figure><p>I recommend you run such diagnostics as well and, at least, create issues for your backlog. One day, all these problems will cause you a real headache.</p><h3>Build System</h3><p>There is also a nice, new Build System feature:</p><blockquote><em>Implicit Dependencies now supports finding dependencies in Other Linker Flags for linked frameworks and libraries specified with </em><em>-framework, </em><em>-weak_framework, </em><em>-reexport_framework, </em><em>-lazy_framework, </em><em>-weak-l, </em><em>-reexport-l, </em><em>-lazy-l, and </em><em>-l.</em></blockquote><p>It’s really interesting as well. In general, it means that you can define your implicit dependencies via .xcconfig or even with xcodebuild options and avoid these Link / Embed phases within Xcode.</p><h3>Debugging</h3><p>Debugging has got new features:</p><blockquote><em>UIStackView properties are now presented in the view debugger object inspector;</em></blockquote><blockquote><em>The view debugger presents a more compact 3D layout.</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qJIe0aHqZ0tnlH5QEP0elQ.png" /></figure><blockquote><em>Xcode can now automatically capture a memory graph, if a memory resource exception is encountered while debugging. To enable memory graph captures go to Diagnostics tab of the scheme’s run settings;</em></blockquote><blockquote><em>On iOS and watchOS, Xcode shows the memory limit for running apps in the Memory Report as you approach the limit;</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YynJHVGppWJmw-qr" /></figure><p>See the red line? Watchdog sends applicationDidReceiveMemoryWarning(...) when you reach the edge. But I thought it would be more useful than it is, to be honest. For now, it just looks like a minor, nice improvement.</p><h3>LLDB Debugger</h3><p>And LLDB Debugger got some love as well:</p><blockquote><em>You can now use </em><em>$0, $1, … shorthands in LLDB expression evaluation inside closures;</em></blockquote><blockquote><em>The LLDB debugger has a new command alias, </em><em>v, for the “frame variable” command to print variables in the current stack frame. Because it bypasses the expression evaluator, </em><em>v can be a lot faster and should be preferred over </em><em>p or </em><em>po.</em></blockquote><p>I haven’t noticed any performance improvements, but v produces a better output in some cases although it’s not a replacement for po in general, it’s only for the current stack frame with some limitations. See the examples below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zf7luFMsdKBjy63w" /></figure><h3>Playgrounds</h3><p>My favourite section? Playgrounds! Let’s start with known issues:</p><blockquote><em>Playgrounds might not execute! 😭</em></blockquote><p>Unfortunately, this is the only news concerning Playgrounds in the current beta.</p><h3>Simulator</h3><p>Some notes about Simulator:</p><blockquote><em>Siri doesn’t work in watchOS and iOS simulators;</em></blockquote><blockquote><em>Pasteboard synchronisation between macOS and simulated iOS devices is more reliable;</em></blockquote><p>I really hope it is.</p><blockquote><em>You’re now only prompted once to authorise microphone access to all simulator devices.</em></blockquote><p>This is a nice improvement because many people get issues with CI and build agents due to this problem. Now a workaround can be automated or, at least, we can update our guides to set up build agents with “Run a simulator once” step.</p><h3>Testing</h3><blockquote><em>xccov supports merging multiple coverage reports — and their associated archives — together into an aggregate report and archive. When merging reports, the aggregate report may be inaccurate for source files that changed since the time the original reports were generated. If there have been no source changes, the aggregate report and archive will be accurate;</em></blockquote><blockquote><em>xccov now supports diffing Xcode coverage reports, which can be used to calculate coverage changes over time. For example, to diff the coverage reports </em><em>before.xccovreport and </em><em>after.xccovreport, invoke </em><em>xccov as follows:</em><em> xccov diff — json before.xccovreport after.xccovreport;</em></blockquote><blockquote><em>Static library and framework targets now appear in the coverage report as top-level entries, with line coverage values that are aggregated across all targets that include the static library or framework. This also resolves an issue where the source files for a static library or framework target would be included in the coverage report even if the target itself was excluded from code coverage in the scheme.</em></blockquote><p>These changes are excellent news for Continuous Integration. Especially differing. Let your release engineering team know and anyone else responsible for such things.</p><p>However, there are some limitations related to testing parallelisation:</p><blockquote><em>Recording doesn’t work from Clones when Parallelisation is on;</em></blockquote><blockquote><em>Profiling tests don’t behave correctly when test parallelisation is enabled;</em></blockquote><p>There are also some promising bug fixes:</p><blockquote><em>If testing fails due to the test runner crashing on launch, Xcode attempts to generate a rich error message describing the failure. This failure is present in the test activity log and appears in </em><em>stdout if you’re using</em><em> xcodebuild. The error is also present in the structured logs contained in the result bundle.</em></blockquote><p>We get a lot of such issues, and usually, it’s not clear at all what is happening. Sometimes, it’s related to incorrect linking, sometimes to system overload. It should help to reduce flakiness.</p><blockquote><em>Crash reports collected during testing no longer omit important fields such as the termination reason and description.</em></blockquote><p>No comment just 😘 and 🥰.</p><p>And the last point about Xcode, useful for companies with a lot of developers, Xcode now supports <a href="https://support.apple.com/en-gb/guide/mac-help/about-content-caching-on-mac-mchl9388ba1b/mac">macOS content caching service</a>. This means that you can have a caching server with Xcode application in your local network.</p><h3>Issues</h3><p>I encounterd some problems with the beta. Mostly with third-party tools: Carthage, for example, which doesn’t work, with the following error:</p><pre>Could not find any available simulators for iOS</pre><p>I checked the available simulator, and it appears that something is broken in the current beta; it’s also impossible to download other runtimes from Xcode, the list of available simulators is just empty (a radar filled):</p><pre>$ xcrun simctl list devices --json | grep -A16 12.1<br>    &quot;com.apple.CoreSimulator.SimRuntime.iOS-12-1&quot; : [<br>      {<br>        &quot;availability&quot; : &quot;(unavailable, runtime profile not found)&quot;,<br>        &quot;state&quot; : &quot;Shutdown&quot;,<br>        &quot;isAvailable&quot; : false,<br>        &quot;name&quot; : &quot;iPhone 5s&quot;,<br>        &quot;udid&quot; : &quot;DDD36346-A76F-42E8-80F4-6F11E1EE4BEB&quot;,<br>        &quot;availabilityError&quot; : &quot;runtime profile not found&quot;<br>      },<br>      {<br>        &quot;availability&quot; : &quot;(unavailable, runtime profile not found)&quot;,<br>        &quot;state&quot; : &quot;Shutdown&quot;,<br>        &quot;isAvailable&quot; : false,<br>        &quot;name&quot; : &quot;iPhone 6&quot;,<br>        &quot;udid&quot; : &quot;21794717-BC89-45E4-9F57-8CF9D14A87D1&quot;,<br>        &quot;availabilityError&quot; : &quot;runtime profile not found&quot;<br>      },<br>--</pre><p>It is a beta, of course. And the changelog is enormous. Be patient and reasonable :)</p><p>P.S. Carthage already has a fix (<a href="https://github.com/Carthage/Carthage/issues/2691">#2691</a>).</p><h3><a href="https://developer.apple.com/documentation/ios_release_notes/ios_12_2_beta_release_notes">iOS 12.2 beta</a></h3><p>Okay. It seems like they are polishing their tech-debt and applying security patches. Two things are broken:</p><blockquote><em>You might be unable to authenticate within Wallet after selecting a card;</em></blockquote><blockquote><em>You might be unable to purchase a prepaid data plan using cellular data.</em></blockquote><p>And <em>Apple News will be available in Canada</em>. Stay tuned.</p><h3><a href="https://developer.apple.com/documentation/macos_release_notes/macos_mojave_10_14_4_beta_release_notes">macOS Mojave 10.14.4 beta</a></h3><p>The only new thing here is a potential issue with Safari 12.1. After upgrading from Safari 10.1.2:</p><blockquote><em>After updating to Safari 12.1 from Safari 10.1.2, web pages might not display.<br>Workaround: Run the following command in Terminal:<br></em><em>defaults delete com.apple.Safari</em></blockquote><p>With the following consequences:</p><blockquote><strong><em>Warning:</em></strong><em> You will lose your previous Safari settings after running the command above.</em></blockquote><h3>Final cut</h3><p>This article turned out to be much longer than I thought. Well, I did give you all my thoughts on all the sections above. A short version of the whole article is simply, ‘Swift 5 has arrived!’</p><p>Stay tuned and hydrated! And thanks for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=99ee9bf4f858" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bumble-tech/xcode-10-2-macos-mojave-10-14-4-ios-12-1-and-other-betas-99ee9bf4f858">Xcode 10.2, macOS Mojave 10.14.4, iOS 12.1 and other betas</a> was originally published in <a href="https://medium.com/bumble-tech">Bumble Tech</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>