<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>iOS Brain</title>
	<atom:link href="https://iosbrain.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://iosbrain.com</link>
	<description>Musings on iOS development, software design, testing, design patterns, and a few surprises...</description>
	<lastBuildDate>Tue, 24 Jan 2023 03:04:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.29</generator>

<image>
	<url>https://iosbrain.com/wp-content/uploads/2017/01/cropped-Very-Basic-Brain-icon-32x32.png</url>
	<title>iOS Brain</title>
	<link>https://iosbrain.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Please be patient as we perform maintenance</title>
		<link>https://iosbrain.com/blog/2023/01/23/please-be-patient-as-we-perform-maintenance/</link>
		<pubDate>Tue, 24 Jan 2023 03:04:14 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[General Technology]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3400</guid>
		<description><![CDATA[Please be patient as we perform some upgrades to enhance your experience here on iosbrain.com. For example, we&#8217;re producing more video content on our YouTube channel, better organizing our current content, and adding fresh new content that goes beyond developing apps for iOS and macOS. For example, we&#8217;ll be looking at the financial performance of &#8230; <a href="https://iosbrain.com/blog/2023/01/23/please-be-patient-as-we-perform-maintenance/" class="more-link">Continue reading<span class="screen-reader-text"> "Please be patient as we perform maintenance"</span></a>]]></description>
				<content:encoded><![CDATA[<p>Please be patient as we perform some upgrades to enhance your experience here on <a href="https://iosbrain.com">iosbrain.com</a>. For example, we&#8217;re producing more video content on our <a href="https://www.youtube.com/@iosbrain">YouTube channel</a>, better organizing our current content, and adding fresh new content that goes beyond developing apps for iOS and macOS. For example, we&#8217;ll be looking at the financial performance of Apple&#8217;s stock and the stock of related companies, all while sticking to our original purpose of helping developers improve their skills and learn about cutting-edge technologies. Check back soon!</p>
]]></content:encoded>
			</item>
		<item>
		<title>DevOps: Installing macOS 13.0 Ventura and downloading/installing older available macOS versions</title>
		<link>https://iosbrain.com/blog/2022/11/09/devops-installing-macos-13-0-ventura-from-monterey-and-downloading-older-available-macos-versions-to-monterey/</link>
		<pubDate>Thu, 10 Nov 2022 00:49:07 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[macOS]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3332</guid>
		<description><![CDATA[Apple likes to publish a new Mac operating system every year, including beta versions and incremental builds, and there can sometimes be many of those released throughout the year, like we&#8217;ve seen in 2022. On October 24 of this year, Apple graced us with macOS Ventura 13.0. Last year, 2021, the company gave us macOS &#8230; <a href="https://iosbrain.com/blog/2022/11/09/devops-installing-macos-13-0-ventura-from-monterey-and-downloading-older-available-macos-versions-to-monterey/" class="more-link">Continue reading<span class="screen-reader-text"> "DevOps: Installing macOS 13.0 Ventura and downloading/installing older available macOS versions"</span></a>]]></description>
				<content:encoded><![CDATA[<p>Apple likes to publish a new Mac operating system every year, including beta versions and incremental builds, and there can sometimes be many of those released throughout the year, like we&#8217;ve seen in 2022. On October 24 of this year, Apple graced us with macOS Ventura 13.0. Last year, 2021, the company gave us macOS 12.0 Monterey. Wouldn&#8217;t it be nice if you could just get a list of available macOS versions, select the one you want, have that macOS installer app download to your <code>/Applications</code> folder, and then you can run that installer whenever you&#8217;re ready? You can and I&#8217;ll show you how. Here&#8217;s what you see after you download the installer for macOS 13.0 Ventura (installer highlighted in <span style="color:green">green</span>):</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-1024x269.png" alt="" width="840" height="221" class="aligncenter size-large wp-image-3341" srcset="https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-1024x269.png 1024w, https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-300x79.png 300w, https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-768x202.png 768w, https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1.png 1128w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p>More specifically, I&#8217;ll tell you how to install Apple&#8217;s new and first alpha version of its desktop operating system software, macOS Ventura 13.0, from a Mac that is most likely still on macOS Monterey &#8212; especially if you keep up with the Apple world. I&#8217;ll also tell you how to download installers for approximately every public macOS build number within the last two years.</p>
<div style="background-color:blue; color:white; padding:10px 10px 10px 10px;"><strong>In today&#8217;s tutorial, we&#8217;ll be using the dreaded <em>command line</em>, but don&#8217;t worry. All that pretty user interface can just make code more buggy, and Apple always seems to have problems with getting new macOS versions downloaded and/or installed. Today, we&#8217;ll be cutting out some fluff and talking (almost) directly to macOS using a <code>Terminal</code> command called <code>softwareupdate</code>. It&#8217;s very reliable. I know everything I show you here today works on Monterey and Ventura and I know the command goes all the way back to macOS El Capitan 10.11. If you&#8217;re using <code>softwareupdate</code> on an older macOS version, just do a <code>man softwareupdate</code> at the command line and study the help. Here we go&#8230;</strong></div>
<p></p>
<p><span id="more-3332"></span></p>
<h2>We&#8217;ll be using the command line (<code>Terminal</code>)</h2>
<p>I&#8217;m assuming that readers are familiar with <code>Terminal.app</code>, which allows people like you and me to execute commands and run utilities directly through the operating system &#8220;shell.&#8221; If you&#8217;re not, please look at one of the many, many great <code>Terminal</code> tutorials available on the web. You&#8217;ll figure it out in no time.</p>
<p>Before you do anything like upgrade your Mac&#8217;s operating system version, you should know what operating system version you&#8217;re <strong>currently</strong> running. It takes me <strong>more time</strong> to use my Mac&#8217;s user interface to find macOS details. I can get my macOS details much faster by entering this short <code>Terminal</code> command:</p>
<p></p><pre class="crayon-plain-tag">% sw_vers                
ProductName:	macOS
ProductVersion:	12.3.1
BuildVersion:	21E258</pre><p></p>
<p>Note that the output from the shell command, <code>sw_vers</code>, is shown immediately after the command. This is the format I&#8217;ll use when displaying events in <code>Terminal</code>.</p>
<p>If I go to <em>Apple</em> > <em>About This Mac</em>, I have to click into the macOS version number to make the build number appear, and it&#8217;s just awkward, like so:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/11/whatMacOSRun-1-1024x578.png" alt="" width="840" height="474" class="aligncenter size-large wp-image-3362" srcset="https://iosbrain.com/wp-content/uploads/2022/11/whatMacOSRun-1-1024x578.png 1024w, https://iosbrain.com/wp-content/uploads/2022/11/whatMacOSRun-1-300x169.png 300w, https://iosbrain.com/wp-content/uploads/2022/11/whatMacOSRun-1-768x434.png 768w, https://iosbrain.com/wp-content/uploads/2022/11/whatMacOSRun-1.png 1172w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<h2>Finding out what macOS installers are available from Apple</h2>
<p>Suppose I want to find out if I can <strong>1)</strong> upgrade my current Monterey partition to Ventura or <strong>2)</strong> install an older version of macOS, namely macOS Big Sur 11.6.6, on another partition from Ventura? To find out what macOS installers are currently available from Apple, enter the following command in <code>Terminal</code>:</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --list-full-installers

Finding available software
Software Update found the following full installers:
* Title: macOS Ventura beta, Version: 13.1, Size: 11548070KiB, Build: 22C5033e
* Title: macOS Ventura, Version: 13.0, Size: 11866804KiB, Build: 22A380
* Title: macOS Monterey, Version: 12.6.1, Size: 12108491KiB, Build: 21G217
* Title: macOS Monterey, Version: 12.6.1, Size: 12110530KiB, Build: 21G215
* Title: macOS Monterey, Version: 12.6, Size: 12104042KiB, Build: 21G115
* Title: macOS Monterey, Version: 12.5.1, Size: 12114929KiB, Build: 21G83
* Title: macOS Monterey, Version: 12.5, Size: 12112497KiB, Build: 21G72
* Title: macOS Big Sur, Version: 11.7.1, Size: 12119247KiB, Build: 20G918
* Title: macOS Big Sur, Version: 11.7, Size: 12118755KiB, Build: 20G817
* Title: macOS Big Sur, Version: 11.6.8, Size: 12118851KiB, Build: 20G730
* Title: macOS Big Sur, Version: 11.6.6, Size: 12121263KiB, Build: 20G624
* Title: macOS Big Sur, Version: 11.6.5, Size: 12121404KiB, Build: 20G527
* Title: macOS Big Sur, Version: 11.6.4, Size: 12147782KiB, Build: 20G417
* Title: macOS Big Sur, Version: 11.6.3, Size: 12143674KiB, Build: 20G415
* Title: macOS Big Sur, Version: 11.6.2, Size: 12141944KiB, Build: 20G314
* Title: macOS Big Sur, Version: 11.6.1, Size: 12137180KiB, Build: 20G224
* Title: macOS Big Sur, Version: 11.5.2, Size: 12149332KiB, Build: 20G95
* Title: macOS Ventura 13.1 Beta 2, Version: 13.1, Size: 10725858KiB, Build: (null)</pre><p> </p>
<p>Notice that I highlighted two lines of output from the <code>softwareupdate</code> command I just ran? These are the two installers I was looking for. Let&#8217;s find out how to download them, where they download to, and how to run the downloaded installers.</p>

<h2>Downloading a macOS installer from Apple</h2>
<p>First, let&#8217;s download the installer app for macOS Ventura 13.0 (22A380) from Monterey. The installer was listed as available in the last <code>Terminal</code> code snippet I just showed you. When using this tool in the future, you always want to make sure that you&#8217;re downloading the installer with the right build number. I won&#8217;t go into details today but, trust me, I&#8217;ve verified that we want macOS build 22A380 to install the one and only publicly-released alpha build of Ventura. Let&#8217;s start downloading the installer app:</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --fetch-full-installer --full-installer-version 13.0</pre><p> </p>
<p>This commands requires you to enter the Mac&#8217;s administrator password, and it&#8217;ll prompt you for that password:</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --fetch-full-installer --full-installer-version 13.0
Password:</pre><p></p>
<p>After talking with the Apple server for a few seconds, the command will tell you what it&#8217;s doing:</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --fetch-full-installer --full-installer-version 13.0
Password:
Scanning for 13.0 installer</pre><p> </p>
<p>Once the <code>softwareupdate</code> command starts downloading the installer app to your <code>/Applications</code> folder, it shows you progress in the command line:</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --fetch-full-installer --full-installer-version 13.0
Password:
Scanning for 13.0 installer
Installing: 12.0%</pre><p></p>
<p><strong>IMPORTANT: Even though <code>softwareupdate</code> says it&#8217;s &#8220;Installing,&#8221; it&#8217;s <u>NOT installing an operating system</u>. It is only downloading a <u>macOS installer app</u> that has to be specifically run to install anything.</strong></p>
<p>When the <code>softwareupdate</code> command finishes downloading the installer app to your <code>/Applications</code> folder, it tells you everything went well in the command line:</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --fetch-full-installer --full-installer-version 13.0
Password:
Scanning for 13.0 installer
Install finished successfully</pre><p></p>
<p>Use <code>Finder</code> to look in the <code>/Applications</code> folder and you&#8217;ll see that the macOS Ventura 13.0 <strong>installer app</strong> is waiting for you to use.</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-1024x269.png" alt="" width="840" height="221" class="aligncenter size-large wp-image-3341" srcset="https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-1024x269.png 1024w, https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-300x79.png 300w, https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1-768x202.png 768w, https://iosbrain.com/wp-content/uploads/2022/11/InstallerForVentura-1.png 1128w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p>When you&#8217;re ready to install or upgrade to Ventura, grab a <code>Finder</code> window, go to the <code>/Applications</code> folder, and run <code>Install macOS Ventura.app</code>. The normal Apple installer will run for Ventura:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/11/InstallVentura-1024x835.png" alt="" width="840" height="685" class="aligncenter size-large wp-image-3372" srcset="https://iosbrain.com/wp-content/uploads/2022/11/InstallVentura-1024x835.png 1024w, https://iosbrain.com/wp-content/uploads/2022/11/InstallVentura-300x245.png 300w, https://iosbrain.com/wp-content/uploads/2022/11/InstallVentura-768x626.png 768w, https://iosbrain.com/wp-content/uploads/2022/11/InstallVentura-1200x979.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<h2>Downloading other macOS installers</h2>
<p>Remember that I also wanted to download macOS Big Sur 11.6.6 (20G624). Let&#8217;s do that on Ventura. I&#8217;m dealing with a service ticket wherein a specific app always crashes when certain features are used in Big Sur 11.6.6. I&#8217;ve got a partition ready. I just need the installer so I can recreate my customer&#8217;s environment. As you&#8217;ll see, the process for getting a Big Sur 11.6.6 <strong>installer <u>app</u></strong> is the same as it was for getting the Ventura installer app. I can download as many macOS installers as I want.</p>
<p>I look up the macOS version I need, then download its installer app if available&#8230;</p>
<p></p><pre class="crayon-plain-tag">% softwareupdate --fetch-full-installer --full-installer-version 11.6.6
Password:
Scanning for 11.6.6 installer
Install finished successfully</pre><p> </p>
<p>&#8230; Then I look in <code>/Applications</code> a find my installer app. I can run this anytime I want:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/11/InstallBigSur-1-1024x182.png" alt="" width="840" height="149" class="aligncenter size-large wp-image-3375" srcset="https://iosbrain.com/wp-content/uploads/2022/11/InstallBigSur-1-1024x182.png 1024w, https://iosbrain.com/wp-content/uploads/2022/11/InstallBigSur-1-300x53.png 300w, https://iosbrain.com/wp-content/uploads/2022/11/InstallBigSur-1-768x136.png 768w, https://iosbrain.com/wp-content/uploads/2022/11/InstallBigSur-1.png 1126w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /> </p>

<h2>Conclusion</h2>
<p>A great reason to use the <code>softwareupdate</code> command in <code>Terminal</code> is, obviously, that you can upgrade to Ventura using a safe and reliable tool. Another great reason to use <code>softwareupdate</code> is to always have access to as many of Apple&#8217;s older macOS versions as possible.</p>
<p>I have customers whose commitment to quality is par excellence. They&#8217;re willing to reproduce bug&#8217;s in their software that are specific to a particular macOS build, like macOS Big Sur 11.6.6. All&#8217;s they need is to look through their list of installers and run the one found, targeting some freshly-formatted partition. One customer I have has installers going back to macOS 10.6. Another keeps active macOS partitions installed and ready to be booted.</p>
<p>You may just find yourself one day with a piece of software that stopped being supported after a certain macOS build was forgotten by Apple&#8217;s memory, but you REALLY like the way your software worked. You can now get that app version back up and running.</p>
<p>You&#8217;ll have to do some regular book-keeping and check for and download macOS installer builds as they come and go. Apple is always on the move and you&#8217;ll only have a certain window of time to download and archive those macOS installers if you want good version coverage. Check often, download, and make backups.</p>
<p>I hope you enjoyed today&#8217;s session. Check back soon as this site is soon to be a hub of activity. We&#8217;ll be publishing more tutorials &#8212; <strong>but we&#8217;ll be adding videos and a new line of books that you can purchase to make you into the best of the best Apple developers</strong>.</p>

]]></content:encoded>
			</item>
		<item>
		<title>Beyond the sandbox: using app groups to communicate between iOS or macOS apps</title>
		<link>https://iosbrain.com/blog/2022/05/24/beyond-the-sandbox-using-app-groups-to-communicate-between-ios-or-macos-apps/</link>
		<pubDate>Tue, 24 May 2022 10:21:35 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[App Groups]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[Swift]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3296</guid>
		<description><![CDATA[Apple&#8217;s &#8220;app group&#8221; technology allows a collection of sandboxed macOS or iOS apps from the same development team to all communicate with each other, coordinate functionality, share resources, and/or minimize redundancies. Notice that I said that I can get sandboxed apps to communicate with each other. But isn&#8217;t sandboxing a security mechanism meant to keep &#8230; <a href="https://iosbrain.com/blog/2022/05/24/beyond-the-sandbox-using-app-groups-to-communicate-between-ios-or-macos-apps/" class="more-link">Continue reading<span class="screen-reader-text"> "Beyond the sandbox: using app groups to communicate between iOS or macOS apps"</span></a>]]></description>
				<content:encoded><![CDATA[<p>Apple&#8217;s &#8220;app group&#8221; technology allows a collection of <strong>sandboxed</strong> macOS or iOS apps from the same development team to all communicate with each other, coordinate functionality, share resources, and/or minimize redundancies. <strong>Notice that I said that I can get <a href="https://iosbrain.com/blog/2018/04/22/ios-file-management-with-filemanager-in-protocol-oriented-swift-4/#sandboxing">sandboxed</a> apps to communicate with each other. But isn&#8217;t sandboxing a security mechanism meant to keep apps isolated from each other?</strong> Yes and no. Apple realized at some point that it would allow apps developed by the same team, with the same Team ID &#8212; built by the same people and thus hopefully less risky &#8212; to intercommunicate. I&#8217;m glad they did as the usefulness of app groups outweighs the dangers.</p>
<p>As long as all developers involved in creating apps meant to be part of an app group can securely share a Team ID from an Apple Developer portal account, they can write apps that can transcend sandboxing. A company may carefully decide to share its Team ID with a trusted partner company, not just with different teams within its own organizational structure. </p>
<p>Member apps of an app group share access to a special group container, a shared folder structure, whose root folder has the same name as the app group ID. In the <a href="https://github.com/iosbrain/Beyond-the-Sandbox-App-Groups-in-Swift">macOS sample app that accompanies this tutorial</a>, several apps share a preference stored in a <code>.plist</code> file that lives in the special group container. The preference is the background color to be used by app group apps&#8217; <code>UIView</code> instances. If one app sets (writes) this shared background color preference to, say, the color green, other app group members read this preference and can change their view layer <code>backgroundColor</code> property to <code>NSColor.green.cgColor</code>. By starting an app group, I&#8217;ve created the beginnings of a group of related apps sharing &#8212; centralizing &#8212; settings like view color scheme, even if all the apps are sandboxed.</p>
<p><span id="more-3296"></span></p>

<p>You can already imagine the possibilities: shared preferences, shared licensing, shared caches, and/or shared databases. Apple says this capability <a href="https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19">&#8220;allows the apps within the group to share Mach and POSIX semaphores and to use certain other IPC [interprocess communication] mechanisms among the group&#8217;s members.&#8221;</a> So, for example, you can have member apps performing thread-safe operations on shared resources.</p>
<p>Today, I&#8217;ll walk you through the configuration and encoding of a macOS app group whose members communicate through a shared instance of <a href="https://developer.apple.com/documentation/foundation/userdefaults"><code>UserDefaults</code></a>, more commonly known as user preferences. One app allows me (and my users) to pick a view background color &#8212; like a theme color &#8212; and write it to my shared <code>UserDefaults</code>. The other app can read that same shared preference and update its view&#8217;s background color to the currently saved value. This process is dynamic. As I change the theme color in one app, the other app can update its view&#8217;s background color immediately. We&#8217;ll build these apps and app group together in this tutorial. You can download the sample apps <a href="https://github.com/iosbrain/Beyond-the-Sandbox-App-Groups-in-Swift">here</a>. Here&#8217;s a video of my two sample apps coordinating together:</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2022/05/AppGroupDemo.gif" title="My sample apps working" /></center></p>
<div style="background-color:blue; color:white; padding:10px 10px 10px 10px;"><strong>Keep this in mind for testing my two sample apps later:</strong> USE THIS ORDER OF OPERATIONS: Run the FirstApp and pick a color, Red, Green, or Blue, from the dropdown box. Click the &#8220;Set shared value&#8221; button. Then click the &#8220;Check for .plist&#8221; button and make sure the textbox to the right says &#8220;.plist exists&#8221;. Only then can SecondApp read preferences.</div>
<p></p>
<p>Probably one of the most intriguing aspects of app groups is that their commonly shared container, a mini folder and file system, transcends <a href="https://iosbrain.com/blog/2018/04/22/ios-file-management-with-filemanager-in-protocol-oriented-swift-4/#sandboxing">sandboxing</a>. To highlight the flexibility of app groups on macOS, one of my sample apps <strong>is</strong> sandboxed while the other <strong>is not</strong>. On iOS, remember that <strong>all your apps are sandboxed</strong>.</p>
<p>App groups are a great feature, but unfortunately they&#8217;re not well-documented and therefore generally not well understood. For example, Apple has a section in it&#8217;s macOS developer documentation called <a href="https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19">&#8220;Adding an App to an App Group&#8221;</a> which strongly implies that all you have to do is add an entitlement to your app&#8217;s project. In another developer document, Apple states <a href="https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps">&#8220;You control the groups that your app belongs to by manipulating its entitlements.&#8221;</a> No mention is made of a very crucial step: registering your app group ID under your account on the Apple Developer portal.</p>
<p>For awhile, adding an app group identifier to an Xcode project&#8217;s entitlements was sufficient <strong>in macOS</strong> to create and join an app group. Only iOS required that developers have an account with Apple and that they register the app group ID on the Apple Developer portal. That requirement now applies to macOS app groups, too.</p>
<p>If you have a number of related apps, especially ones you sell as part of an App Store <a href="https://developer.apple.com/app-store/app-bundles/">bundle</a>, then app groups might be for you. Keep in mind that apps can be members of more than one app group, too.</p>
<p>Let&#8217;s walk though all the required steps to create two macOS apps that demonstrate app groups &#8212; and note that almost all the content herein applies to iOS app groups.</p>
<div style="background-color:blue; color:white; padding:10px 10px 10px 10px;">Remember that you&#8217;ll have to provide your own Apple Developer account&#8217;s <em>Team ID</em> for creating your own app group ID and for using, especially signing, both of my sample apps.</div>
<p></p>
<h2>Registering your app group&#8217;s ID</h2>
<p>The first thing to do when creating an app group is to register an app group ID. Have a copy of your Apple Developer account&#8217;s <em>Team ID</em> ready, like copied into your clipboard. In the screenshots shown below, you&#8217;ll substitute your own <em>Team ID</em> where I&#8217;ve redacted my own. Let&#8217;s get started:</p>
<p><strong>1.</strong> Login to your <a href="https://developer.apple.com/account/">Apple Developer</a> account;<br />
<strong>2.</strong> Select <em>Certificates, IDs &#038; Profiles</em> from the left sidebar or the center of the screen;<br />
<strong>3.</strong> You&#8217;ll land on the <em>Certificates</em> screen by default, but select <em>Identifiers</em> from the left sidebar;<br />
<strong>4.</strong> Click the dropdown labelled <em>App IDs</em>, like so:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/SelectTheDropdownLabelledAppIDs-1024x531.png" alt="" width="840" height="436" class="aligncenter size-large wp-image-3303" srcset="https://iosbrain.com/wp-content/uploads/2022/05/SelectTheDropdownLabelledAppIDs-1024x531.png 1024w, https://iosbrain.com/wp-content/uploads/2022/05/SelectTheDropdownLabelledAppIDs-300x156.png 300w, https://iosbrain.com/wp-content/uploads/2022/05/SelectTheDropdownLabelledAppIDs-768x398.png 768w, https://iosbrain.com/wp-content/uploads/2022/05/SelectTheDropdownLabelledAppIDs-1200x622.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p><strong>5.</strong> Select the <em>App Groups</em> option from the dropdown;<br />
<strong>6.</strong> Now that you&#8217;re on the <em>Identifiers</em> for <em>App Groups</em> page, click the plus-sign-inside-the-circle button;<br />
<strong>7.</strong> On the <em>Register a New Identifier</em> page that comes up, select the <em>App Groups</em> radio button, like this:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/AppGroupsPre-selected-1024x161.png" alt="" width="840" height="132" class="aligncenter size-large wp-image-3304" srcset="https://iosbrain.com/wp-content/uploads/2022/05/AppGroupsPre-selected-1024x161.png 1024w, https://iosbrain.com/wp-content/uploads/2022/05/AppGroupsPre-selected-300x47.png 300w, https://iosbrain.com/wp-content/uploads/2022/05/AppGroupsPre-selected-768x121.png 768w, https://iosbrain.com/wp-content/uploads/2022/05/AppGroupsPre-selected.png 1182w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p><strong>8.</strong> Click the big, blue <em>Continue</em> button on the upper right-hand side of the same page;<br />
<strong>9.</strong> You&#8217;ll land on the <em>Register an App Group</em> page where you&#8217;ll get ready to fill in the <em>Description</em> and <em>Identifier</em> fields;<br />
<strong>10.</strong> Type in a meaningful <em>Description</em> and type/paste your <em>Team ID</em> into the <em>Identifier</em> field;<br />
<strong>11.</strong> Notice that &#8220;group.&#8221; is prepended to the <em>Identifier</em>, and that I added some meaningful text, following Apple&#8217;s suggestion, like this:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/EnterDescriptionAndIdentifier-1024x355.png" alt="" width="840" height="291" class="aligncenter size-large wp-image-3308" srcset="https://iosbrain.com/wp-content/uploads/2022/05/EnterDescriptionAndIdentifier-1024x355.png 1024w, https://iosbrain.com/wp-content/uploads/2022/05/EnterDescriptionAndIdentifier-300x104.png 300w, https://iosbrain.com/wp-content/uploads/2022/05/EnterDescriptionAndIdentifier-768x266.png 768w, https://iosbrain.com/wp-content/uploads/2022/05/EnterDescriptionAndIdentifier-1200x416.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p><strong>12.</strong> Click the big, blue <em>Continue</em> button;<br />
<strong>13.</strong> You can review your new app group ID, are given the chance to click <em>Back</em> to make changes, but we&#8217;ll select the <em>Register</em> button; and,<br />
<strong>14.</strong> Now back on the <em>Identifiers</em> for <em>App Groups</em> page, you&#8217;ll see that you&#8217;ve created a new app group.</p>
<h2>The app group&#8217;s shared container</h2>
<p>By definition, an app <strong>group</strong> is a collection of two or more apps. Whichever app that is a member of the app group, and runs before any of the other member apps run, creates what&#8217;s called the group&#8217;s &#8220;shared container.&#8221; It does this once unless someone deletes the container, in which case macOS recreates the container when it is next referenced by one of the group&#8217;s member apps. That container is a mini folder/file system like those that macOS provides for sandboxed apps. It&#8217;s a bit like the folder system that macOS builds for each user on a Mac or MacBook. Every shared container is stored in the macOS file system in a folder that has the same name as the app group ID, like <code>group.TEAM_ID.com.domain.MyAppSuite</code>. That folder is always stored in the macOS file system in <code>~/Library/Group Containers/</code>. So the full container path is <code>~/Library/Group Containers/group.TEAM_ID.com.domain.MyAppSuite</code>. Here&#8217;s what the shared container looks like right after it&#8217;s created, including the preferences <code>.plist</code>:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/specialGroupContainer-1024x394.png" alt="" width="840" height="323" class="aligncenter size-large wp-image-3309" srcset="https://iosbrain.com/wp-content/uploads/2022/05/specialGroupContainer-1024x394.png 1024w, https://iosbrain.com/wp-content/uploads/2022/05/specialGroupContainer-300x116.png 300w, https://iosbrain.com/wp-content/uploads/2022/05/specialGroupContainer-768x296.png 768w, https://iosbrain.com/wp-content/uploads/2022/05/specialGroupContainer-1200x462.png 1200w, https://iosbrain.com/wp-content/uploads/2022/05/specialGroupContainer.png 1454w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p>The app group has its own user preferences data store, accessible via a special instance of <code>UserDefaults</code>. These preferences are stored in a <code>.plist</code> file just like they are for all macOS apps. In this tutorial, those preferences are stored in the file at this path:</p>
<p></p><pre class="crayon-plain-tag">~/Library/Group Containers/group.YOUR_TEAM_ID.com.domain.MyAppSuite/Library/Preferences/group.YOUR_TEAM_ID.com.domain.MyAppSuite.plist</pre><p></p>
<p>All apps in the app group have read and write access to the shared container, including access to the shared preferences.</p>

<h2>A word about my sample code</h2>
<p>My code is semantically clear and well commented &#8212; <strong>but simple</strong>. You shouldn&#8217;t have any trouble reading it and understanding it. Remember that my code and this accompanying article are pedantic in nature. We&#8217;re talking about app groups, <strong>not</strong> about using MVC, robust error handling, testing, etc.</p>
<p>Let talk about the numbering of my comments, mainly the fact that I&#8217;ve shown them out of sequence, starting at &#8220;3a)&#8221; and not with &#8220;1)&#8221;. Let me explain: I&#8217;m introducing the code in the order I feel best for my tutorial&#8217;s flow, especially regarding what code I want to explain first, what to explain second, all the way to what to explain last. </p>
<p>So initially, please <strong>read the code</strong>, ignoring the comment numbers until you&#8217;ve read the whole article. Once you&#8217;ve got your Team ID, your app group ID, and you&#8217;ve got both apps configured with the app group ID, you can build and run them. </p>
<p>Then read the code with comments in numeric sequence starting with &#8220;1)&#8221; all the way through &#8220;4g)&#8221;. You’ll see that the sequencing of the comment numbers makes sense in terms of the overall flow of the way my two apps work together.</p>
<h2>&#8220;FirstApp&#8221; &#8211; Creating an app that is part of an app group</h2>
<p>Let&#8217;s walk through building my app group&#8217;s first app, ingeniously named &#8220;FirstApp.&#8221; It reads from and writes to the shared container. My FirstApp writes a color to the shared container&#8217;s preferences so that my &#8220;SecondApp&#8221; can read that preference, and thus we have interprocess communication.</p>
<p>Open up Xcode (I&#8217;m using 13.2.1) and create a new application based on the macOS <code>App</code> template.</p>
<p>Follow these steps in <em>TARGETS</em> -> <em>Signing &#038; Capabilities</em>:</p>
<p><strong>1.</strong> Tick the <em>Automatically manage signing</em> checkbox and then set the <em>Team</em> and <em>Bundle Identifier</em> appropriately;<br />
<strong>2.</strong> Make sure to that you have the <em>App Sandbox</em> and <em>Hardened Runtime</em> capabilities;<br />
<strong>3.</strong> Click the <em>+</em> button next to <em>Capability</em> and add the <em>App Groups</em> capability by dragging it in from the <em>Library</em>, like this:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/DragToAddAppGroupCapability.gif" alt="" width="840" /></p>
<p><strong>4.</strong> Add your app group ID to the <em>App Groups</em> slot. Where it says <em>Add containers here</em>, press the <em>+</em> button and add your app group ID:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-1024x506.png" alt="" width="840" height="415" class="aligncenter size-large wp-image-3311" srcset="https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-1024x506.png 1024w, https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-300x148.png 300w, https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-768x380.png 768w, https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup.png 1048w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p>Remember that your app group ID should look like this:</p>
<p></p><pre class="crayon-plain-tag">group.YOUR_TEAM_ID.com.domain.MyAppSuite</pre><p></p>
<p>Your app group ID is actually an array element in the <code>.entitlements</code> file.</p>
<p>Note that I specifically sandboxed this app to show you that an <strong>app group app can read the shared container, which is outside of this app&#8217;s sandbox.</strong></p>
<p>Everything you need to see is in the <code>ViewController.swift</code> file. Let&#8217;s briefly walk through the most important code in FirstApp &#8212; a few selected snippets.</p>
<p>Let&#8217;s examine how I write user-selected color values from my app&#8217;s <code>NSComboBox</code> to the app group&#8217;s shared preferences. The interprocess communication comes into play when my SecondApp, described below, reads that color preference. Notice that I&#8217;m getting a special type of reference to <code>UserDefaults</code> by calling its <a href="https://developer.apple.com/documentation/foundation/userdefaults/1409957-init"><code>init(suiteName:)</code></a> initializer, where the full definition is <code>init?(suiteName suitename: String?)</code>, and note the optional return value. I pass my app group ID to the argument labelled <code>suiteName</code>. I access the user preferences associated with my app group by initializing <code>UserDefaults</code> specific to my app group&#8217;s ID, stored in the shared container. Then I can set a key/value specific to that app group:</p>
<p></p><pre class="crayon-plain-tag">...
/** 3a) Write user preference to shared container. */
func setPreferenceValue(_ value: Any?, forKey key: String, in appGroup: String) {

    // 3b) If we can access preferences to our app group...
    if let groupUserDefaults = UserDefaults(suiteName: appGroup) {

        // 3c) Write the value for the given key
        // to our shared container.
        groupUserDefaults.set(value, forKey: key)
        print(&quot;Wrote to shared user defaults.&quot;)

    }

} // end func setPreferenceValue
...</pre><p></p>
<p>If you&#8217;re going to do something with your app group like store common files or maintain a shared cache, you&#8217;ll need to be able to get a valid macOS file system path to read from, and possibly write to, files/folders in the shared container. To get a URL to the root folder of your shared container, you use the <a href="https://developer.apple.com/documentation/foundation/filemanager/1412643-containerurl"><code>containerURL(forSecurityApplicationGroupIdentifier:)</code></a> instance method of <code>FileManager</code>, passing it your app group ID. Notice that <a href="https://developer.apple.com/documentation/foundation/filemanager/1416680-iswritablefile">instead of testing to see if a file exists first before reading from it</a>, I proactively read from it using <code>NSData</code> and then check for a return value:</p>
<p></p><pre class="crayon-plain-tag">...
/** 4a) If you're going to manage and access common resources
 or assets in the shared container, remember that &quot;It&rsquo;s far better to
 attempt an operation (such as loading a file or creating a directory),
 check for errors, and handle those errors gracefully than it is to try
 to figure out ahead of time whether the operation will succeed.&quot;

 - returns: True if plist exists; false if it doesn't exist
*/
func sharedPreferencesPlistExists() -&gt; Bool {

    var containerExists = false

    let sharedFileManager = FileManager.default

    /* 4b) &quot;In macOS, a URL of the expected form is always returned, even if the app group is invalid, so be sure to test that you can access the underlying directory before attempting to use it.&quot; */
    let sharedContainerFolderURL = sharedFileManager.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)
    // 4c) Now we build a standard path (&quot;Library/Preferences/&quot;)
    // to the preferences data store file (plist). Note
    // the format of the plist's name.
    let sharedContainerPrefsPlistURL = (sharedContainerFolderURL?.appendingPathComponent(&quot;Library/Preferences/group.YOUR_TEAM_ID.com.domain.MyAppSuite.plist&quot;))!
    // 4d) Try to read data from the preferences
    // plist file.
    let sharedContainerPrefsPlistData = NSData(contentsOf: sharedContainerPrefsPlistURL)
    // 4e) If the file exists...
    if let fileData = sharedContainerPrefsPlistData {

        // 4f) if the plist file has contents (bytes)...
        if fileData.length &gt; 0 {

            // 4g) We know that the plist is valid.
            print(&quot;.plist file size: \(fileData.length)&quot;)
            containerExists = true

        }

    }

    return containerExists

} // func sharedContainerExists()
...</pre><p></p>
<p>Upon clicking the &#8220;Check for .plist&#8221; button in FirstApp, the console shows:</p>
<p></p><pre class="crayon-plain-tag">.plist file size: 90
Shared plist created.</pre><p></p>

<h2>&#8220;SecondApp&#8221; &#8211; Creating another app so we have an app group</h2>
<p>To restate what I would hope is now the obvious, &#8220;an app <strong>group</strong> is a collection of two or more apps.&#8221; SecondApp is, well, the other app that makes up my little app group. SecondApp reads a preference from the shared container. That preference for color is written by FirstApp. SecondApp sets its view controller&#8217;s <code>NSView</code> background color to the shared container&#8217;s preference and thus we have interprocess communication.</p>
<p>Open up Xcode (I&#8217;m using 13.2.1) and create a new application based on the macOS <code>App</code> template.</p>
<p>Follow these steps in <em>TARGETS</em> -> <em>Signing &#038; Capabilities</em>:</p>
<p><strong>1.</strong> Tick the <em>Automatically manage signing</em> checkbox and then set the <em>Team</em> and <em>Bundle Identifier</em> appropriately;<br />
<strong>2.</strong> In this case, make sure to <strong>remove</strong> the <em>App Sandbox</em> capability;<br />
<strong>3.</strong> Make sure the app has the <em>Hardened Runtime</em> capability;<br />
<strong>4.</strong> Click the <em>+</em> button next to <em>Capability</em> and add the <em>App Groups</em> capability by dragging it in from the <em>Library</em>, like this:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/DragToAddAppGroupCapability.gif" alt="" width="840" /></p>
<p><strong>5.</strong> Add your app group ID to the <em>App Groups</em> slot. Where it says <em>Add containers here</em>, press the <em>+</em> button and add your app group ID:</p>
<p><img src="https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-1024x506.png" alt="" width="840" height="415" class="aligncenter size-large wp-image-3311" srcset="https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-1024x506.png 1024w, https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-300x148.png 300w, https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup-768x380.png 768w, https://iosbrain.com/wp-content/uploads/2022/05/InsertAppGroup.png 1048w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></p>
<p>Remember that your app group ID should look like this:</p>
<p></p><pre class="crayon-plain-tag">group.YOUR_TEAM_ID.com.domain.MyAppSuite</pre><p></p>
<p>The app group ID is actually an array element in the <code>.entitlements</code> file.</p>
<p>Everything you need to see is in the <code>ViewController.swift</code> file. Let&#8217;s briefly walk through the most important code in SecondApp &#8212; just one selected snippet. Again, I&#8217;m getting a special type of reference to <code>UserDefaults</code> by calling its <a href="https://developer.apple.com/documentation/foundation/userdefaults/1409957-init"><code>init(suiteName:)</code></a> initializer with my app group&#8217;s ID as an argument. This is how I read the user preference for the color that was set in FirstApp. I then change my main window&#8217;s view background color to the preferred color. Here&#8217;s the code:</p>
<p></p><pre class="crayon-plain-tag">...
func setViewBackgroundColor() {

    // 1) Get a reference to the shared user defaults for the
    // app group we created.
    if let groupUserDefaults = UserDefaults(suiteName: appGroupID) {

        // 2) Read the value for the &quot;BackgroundColor&quot; key stored
        // in our app group shared container's preferences
        // (user defaults).
        if let backgroundColor = (groupUserDefaults.object(forKey: &quot;BackgroundColor&quot;)) as? String {

            // 3) Set the background color of our NSView to
            // the value we read from the our shared container's
            // preferences.
            self.view.wantsLayer = true

            self.view.needsDisplay = true

            if backgroundColor == &quot;Red&quot; {
                self.view.layer?.backgroundColor = NSColor.red.cgColor
            }
            else if backgroundColor == &quot;Green&quot; {
                self.view.layer?.backgroundColor = NSColor.green.cgColor
            }
            else if backgroundColor == &quot;Blue&quot; {
                self.view.layer?.backgroundColor = NSColor.blue.cgColor
            }
            else {
                self.view.layer?.backgroundColor = NSColor.gray.cgColor
            }

            print(&quot;Read background color, \(backgroundColor), from shared user defaults.&quot;)

        } // end if let backgroundColor =...

    } // end if let groupUserDefaults =...

} // end func setViewBackgroundColor()
...</pre><p></p>
<p>Note that I specifically didn&#8217;t sandbox this app to show you that <strong>macOS apps don&#8217;t necessarily need to be sandboxed (especially those distributed via 3rd party signing) and that non-sandboxed apps can access their app group&#8217;s shared container.</strong></p>
<div style="background-color:green; color:white; padding:10px 10px 10px 10px;"><strong>CODING TIP:</strong> When I develop apps involving app groups, I always write a default value to shared preferences so that I know that the app group&#8217;s user preferences <code>.plist</code> will be there from the start. Since I wanted to keep this project simple, I left that step out, and I also wanted to show you how an app group can go wrong if that initial <code>.plist</code> file is not there from the beginning.</div>
<p></p>
<h2>Installing and distributing your macOS apps</h2>
<p>Remember that if you want to install and/or distribute macOS apps like the ones I discussed here, you have two choices. You can go the 3rd party route and sign and notarize your apps outside of the Mac App Store or you can submit your apps for review by staying within the Mac App Store. macOS apps are more flexible in terms of distribution than iOS apps. <strong>I&#8217;ll be publishing a book on Amazon Kindle on how to distribute macOS apps outside of the Mac App Store. I&#8217;ll also be offering iOS courses on Udemy. Come back to look for it soon!</strong></p>
<h2>Conclusion</h2>
<p>I hope you see the benefits that can be gained by use of app groups, whether it be in iOS or macOS. You can control and update your apps more easily by centralizing shared resources. You can eliminate redundancies. And you can get really advanced by using technologies like shared memory (as long as you remember to keep things thread safe). I could go on and on about the benefits of app groups, but I hope you&#8217;ll see that, for a relatively small price, you can get a high return on investment.</p>

]]></content:encoded>
			</item>
		<item>
		<title>Using SwiftUI and WidgetKit to make your app content indispensable</title>
		<link>https://iosbrain.com/blog/2021/12/12/using-swiftui-and-widgetkit-to-make-your-app-content-indispensable/</link>
		<pubDate>Mon, 13 Dec 2021 00:48:57 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[Code Reuse]]></category>
		<category><![CDATA[SwiftUI]]></category>
		<category><![CDATA[User Interface]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3279</guid>
		<description><![CDATA[By using a combination of SwiftUI and WidgetKit, you can increase the visibility of your app&#8217;s content and enhance the user experience by placing one or more &#8220;widgets&#8221; on the user&#8217;s iOS Home screen, macOS Notification Center, and/or iOS Today View. Widgets should display your app&#8217;s most relevant content, allowing users to get important information &#8230; <a href="https://iosbrain.com/blog/2021/12/12/using-swiftui-and-widgetkit-to-make-your-app-content-indispensable/" class="more-link">Continue reading<span class="screen-reader-text"> "Using SwiftUI and WidgetKit to make your app content indispensable"</span></a>]]></description>
				<content:encoded><![CDATA[<p>By using a combination of <a href="https://developer.apple.com/documentation/swiftui/">SwiftUI</a> and <a href="https://developer.apple.com/documentation/widgetkit">WidgetKit</a>, you can increase the visibility of your app&#8217;s content and enhance the user experience by placing one or more &#8220;widgets&#8221; on the user&#8217;s iOS Home screen, macOS Notification Center, and/or iOS Today View. Widgets should display your app&#8217;s most relevant content, allowing users to get important information with a glance. When a user taps/clicks a widget, they go straight to your app and should land on a page that gives them more details about what they just glanced at. Take a look at your iPhone&#8217;s Today View right now. There are widgets for weather, battery power, maps, stock exchanges &#8212; with many more available. For example, you can get an almost-instant read on the current atmospheric conditions by glancing at one of several available weather widgets. This time of year, before I leave the house, I glance at the weather widget to determine if I need a coat and hat before going outside. If I want to get the forecast for later in the day, I just tap on that weather widget to open the respective weather app.</p>
<p><span id="more-3279"></span></p>

<p>Since widgets display content with SwiftUI views, they are generally easy to create and portable across Apple&#8217;s devices, like iPhones and Macs. Each of your apps can provide multiple widgets, multiple instances of the same or different widgets, and three different sizes of the same widgets.</p>
<p>Let&#8217;s talk about at an example of design considerations for building a widget, from my <a href="https://iosbrain.com/wp-content/uploads/2021/11/Xcode_13.1_Project.zip">sample project</a>. You should click that link and download my project to follow along with this article. I used Xcode 13.1 to write this sample app and iOS 15.0 on the Simulator and on an iPhone 12 to test.</p>
<p>My &#8220;Events&#8221; app has a widget that shows the important events that occur during a workday along with the times at which they occur. Look at the following two images. The first highlights my widget showing the events of the day in fast motion, because we wouldn&#8217;t want to wait to watch the widget over a 15-hour period. The widget simply shows the nearest-occurring event and its time; information that can be seen at a glance. The second image shows what happens when you tap on the widget: the app opens showing all the events of the day including the one that was being shown in the widget at the time of the tap. Remember that this app is a proof of concept highlighting WidgetKit and SwiftUI, and is not fully-functional.</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/WidgetOnHomeScreen.gif" title="Widget on the home screen" width="50%" /></center></p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/ClickOnWidget.gif" title="Click on widget" width="50%" /></center></p>
<p>It should be apparent to you by now that, because of a widget&#8217;s limited amount of space, it should only display information that users see as most valuable in your app. Don&#8217;t clutter things up. Design for simplicity, ease of use, and elegance.</p>
<p>Because widgets are portable between iOS and macOS, are pretty small, and should convey concise, glanceable information, SwiftUI is the perfect tool to use for building their user interfaces. Indeed, WidgetKit requires that you use SwiftUI views to design and render widgets&#8217; content.</p>
<h1> A word about my sample app </h1>
<p>The sample app that we&#8217;ll walk through in this article is very simple and not fully functional on purpose. I want you to get a basic understanding of SwiftUI and WidgetKit without getting bogged down in a bunch of implementation details about how a daily to-do list app would be written. My app implements just enough of a to-do list to introduce you to SwiftUI and WidgetKit; the rest is a facade.</p>
<p>So, if fully functional, my app would allow a user to define 5 to 6 essential life events in a day, assign times to those events, and, at any time, glance at the widget to see the nearest approaching event, based on some type of timing algorithm. If the app was completed, tapping on the widget would take a user to a detail screen for the nearest event where one could, say, make some notes, set a reminder or alarm, add contacts, add directions, then go back to the main summary screen showing a list of all the day&#8217;s events and times, and edit another event. Since my app is still a prototype, when the user taps on the widget (or opens the app itself), he or she is sent directly to a screen to see a read-only list of events and times.</p>
<h1> Creating the base app </h1>
<p>Let&#8217;s walk through the steps I went through to develop my sample &#8220;Events&#8221; app. I made it a SwiftUI-based app. Open Xcode 13.x and go to:</p>
<p>&#8211; <em>New</em> > <em>Project&#8230;</em><br />
&#8211; On the <em>Choose a template for your new project:</em> screen, select <em>iOS</em> and <em>App</em>, then click <em>_Next</em></p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/ChooseiOSApp.png" title="Choose project template" /></center></p>
<p>&#8211; On the <em>Choose options for your new project:</em> screen, fill in <em>Product Name:</em> with &#8220;Events,&#8221; select your own <em>Team:</em>, set your own <em>Organization Identifier:</em>, set the <em>Interface:</em> to &#8220;SwiftUI,&#8221; set the &#8220;Language:&#8221; to &#8220;Swift,&#8221; then click <em>Next</em></p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/ChooseSwiftUI.png" title="Choose SwiftUI interface" /></center></p>
<p>&#8211; Select the new project location and click <em>Create</em></p>
<p>The new app will have two code files, &#8220;EventsApp.swift&#8221; and &#8220;ContentView.swift.&#8221; We&#8217;ll leave &#8220;EventsApp.swift&#8221; alone. It&#8217;s custom <code>App</code> protocol conformer, <code>EventsApp</code>, provides the entry point into the app and will render the simple user interface defined in &#8220;ContentView.swift.&#8221; <strong>From herein to the end of this article, I&#8217;ll show you a piece of code and then explain it immediately afterwards.</strong></p>
<p>Take a look at &#8220;ContentView.swift.&#8221; I wrote a simple declarative SwiftUI user interface (UI) using the <code>struct</code> named <code>ContentView</code>. The app&#8217;s entire UI is in the <code>body</code> member of the <code>ContentView</code>:</p>
<p></p><pre class="crayon-plain-tag">...
import SwiftUI

let events = ["Wake up", "Breakfast", "Go to work", "Lunch", "Come home", "Go to sleep"]
let eventTimes = ["7:00 AM", "8:00 AM", "8:30 AM", "12:00 PM", "5:00 PM", "11:00 PM"]

struct ContentView: View {

    var body: some View {

        // Screen title
        Text("Daily Events").bold().italic().padding()

        // List of daily events with times
        Form {
            ForEach(0..&lt;events.count) { event in
                Text("- \(events[event]) [ \(eventTimes[event]) ]")
            }
        }.padding().border(Color.blue)

    } // end body

} // end ContentView
...</pre><p> </p>
<p>First, I used a <code>Text</code> view to give my list of events a title, using some view modifiers to highlight that title (<code>.bold().italic().padding()</code>). Then I used a <code>Form</code> view as the main container for the app&#8217;s list of events because, in real life, I&#8217;d allow editing of my events here. Right now, the app only displays the events and their times read-only, but always think ahead. The <code>ForEach</code> writes out the events and their respective times as <code>Text</code> views, one per line, for all to-do list items that I&#8217;ve stored in arrays. The <code>Form</code> has a colored border and some padding around it. There&#8217;s a reason I used 2 arrays and it has to do with widgets auto-updating, but that&#8217;s beyond the scope of this article.</p>

<p>Running the &#8220;Events&#8221; app now shows this screen:</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/EventsMainScreen.png" title="Containing app main screen" width="50%" /></center></p>
<p>For those of you following along, test your &#8220;Events&#8221; app and make sure it looks like the previous picture.</p>
<h1> Adding the WidgetKit extension </h1>
<p>Widget functionality can be added to the SwiftUI &#8220;Events&#8221; app I started up above. All&#8217;s I have to do is to add a new target &#8212; a WidgetKit extension &#8212; to my existing app. Head back to Xcode 13.x and go to:</p>
<p>&#8211; <em>File</em> > <em>New</em> > <em>Target&#8230;</em><br />
&#8211; On the <em>Choose a template for your new target:</em> screen, select <em>iOS</em> and <em>Widget Extension</em>, then click <em>Next</em></p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/AddWidgetExtension.png" title="Add WidgetKit extension to project" /></center></p>
<p>&#8211; On the <em>Choose options for your new target:</em> screen, fill in <em>Product Name:</em> with &#8220;EventTimes,&#8221; select your own <em>Team:</em>, set your own <em>Organization Identifier:</em> (same as &#8220;Events&#8221; app), <strong>do not</strong> set the <em>Include Configuration Intent</em>, make sure that &#8220;Project:&#8221; and &#8220;Embed in Application:&#8221; are both set to &#8220;Events,&#8221; and then click <em>Finish</em></p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/ConfigExtensionTargetOptions.png" title="Configure WidgetKit extension options" /></center></p>
<p>&#8211; You&#8217;ll be prompted to activate your new &#8220;EventTimesExtension&#8221; scheme; make sure you press the &#8220;Activate&#8221; button now:</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/ActivateExtension.png" title="Activate WidgetKit extension" width="50%" /></center></p>
<p>A few items have been added to your &#8220;Events&#8221; app project, most notably, the &#8220;EventTimes.swift&#8221; WidgetKit code and the <code>WidgetKit.framework</code>. We&#8217;ll spend most of the rest of the article discussing &#8220;EventTimes.swift.&#8221;</p>
<h1> Data sharing between the app and widget? </h1>
<p>Notice that I&#8217;ve defined the same data model (2 arrays) at the top of the extension&#8217;s &#8220;EventTimes.swift&#8221; that I already defined in the containing app&#8217;s &#8220;ContentView.swift&#8221;:</p>
<p></p><pre class="crayon-plain-tag">...
let events = ["Wake up", "Breakfast", "Go to work", "Lunch", "Come home", "Go to sleep"]
let eventTimes = ["7:00 AM", "8:00 AM", "8:30 AM", "12:00 PM", "5:00 PM", "11:00 PM"]
...</pre><p></p>
<p>Remember that <a href="https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html">&#8220;Even though an app extension bundle is nested within its containing app&#8217;s bundle, the running app extension and containing app have no direct access to each other&#8217;s containers.&#8221;</a> In other words, the 2 arrays defined in just the containing app are not accessible to the extension and vice versa. One solution would be to define an app group to which both the &#8220;Events&#8221; app and &#8220;EventTimesExtension&#8221; extension belong. The app group would let the extension and containing app intercommunicate. They could then share the same data model. But that is way beyond the scope of this article &#8212; and I already wrote a tutorial on app groups which I urge you to read: <a href="https://www.appcoda.com/app-group-macos-ios-communication/">&#8220;Using App Groups for communication between macOS/iOS apps from the Same Vendor&#8221;</a>.</p>
<h1> How WidgetKit works </h1>
<p>Widgets are driven by, like many other aspects of our reality, <strong>time</strong>. With my &#8220;Events&#8221; app and widget, we have a relatively fixed list of events that occur throughout the day. What drives the updating of the widget to show the next nearest coming-up event is that event&#8217;s time. Think of the iPhone weather widget. It also is driven by time, probably polling a server every 30 seconds so it can update the current conditions, the current temperature, and the day&#8217;s current high and low.</p>
<p>Let&#8217;s go through the code in the WidgetKit extension&#8217;s &#8220;EventTimes.swift&#8221; file from top to bottom, even though that might not may be the most logical order. But if I jump around, you&#8217;re likely to get confused &#8212; plus I urge you to compare my version of the file to the template version as first generated when you created the WidgetKit extension.</p>
<p>Let&#8217;s start at the top of the file:</p>
<p></p><pre class="crayon-plain-tag">...
import WidgetKit
import SwiftUI

let events = ["Wake up", "Breakfast", "Go to work", "Lunch", "Come home", "Go to sleep"]
let eventTimes = ["7:00 AM", "8:00 AM", "8:30 AM", "12:00 PM", "5:00 PM", "11:00 PM"]
var currentEvent = 0

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), eventName: "Daily event", eventTime: "N/A")
    }
...</pre><p></p>
<p>From the first <code>struct</code> we encounter, of type <code>TimelineProvider</code>, you can see why I said that widgets are driven by time. The <code>placeholder</code> function <a href="https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension">&#8220;displays a generic representation of your widget, giving the user a general idea of what the widget shows&#8221;</a>. It is called if your widget is displayed but no real data is ready to be displayed, perhaps because the containing app hasn&#8217;t been configured or established network connections yet. <code>SimpleEntry</code> is the <code>struct</code> that holds instances of data that are shown one at a time in your widget. To be specific, this <code>SimpleEntry</code> reference is the <code>struct</code> constructor that returns an instance.</p>
<p></p><pre class="crayon-plain-tag">...
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), eventName: events[currentEvent], eventTime: eventTimes[currentEvent])
        completion(entry)
    }
...</pre><p></p>

<p>The <code>getSnapshot</code> function provides an app timeline entry for the current time (and perhaps state) of the widget. For my &#8220;Events&#8221; app, this would be the nearest event in time in your daily schedule about to occur.</p>
<p></p><pre class="crayon-plain-tag">...
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        // Generate a timeline consisting of six entries an second apart, starting from the current time.
        let currentDate = Date()

        for timeOffset in 0 ..< events.count {
            let entryDate = Calendar.current.date(byAdding: .second, value: timeOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate, eventName: events[timeOffset], eventTime: eventTimes[timeOffset])
            entries.append(entry)
        }
        currentEvent = 0

        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    } // end getTimeline
...</pre><p></p>
<p>For a static prototype like my sample &#8220;Events&#8221; app, the <code>getTimeline</code> function can build the entire timeline to be displayed in my widget. Because of the <code>policy: .atEnd</code>, the timeline is created over and over, so I create an event (<code>entry</code>) every second so you can see my to-do list in fast motion. I already explained why a **real** version of my &#8220;Events&#8221; app would need a more sophisticated algorithm to calculate a timeline of the &#8220;next, nearest&#8221; event relative to the current point in time. If you were building a weather app, some type of polling algorithm could be used to make network requests to get the current conditions for the current times throughout the day. At least you could pull the current weather conditions whenever the user looks at the app and <i>then</i> start polling.</p>
<p></p><pre class="crayon-plain-tag">...
    struct SimpleEntry: TimelineEntry {
        let date: Date
        let eventName: String
        let eventTime: String
    }
...</pre><p></p>
<p>As I mentioned above, the <code>SimpleEntry</code> is the <code>struct</code> that holds instances of data that are shown one at a time in your widget. Note that the <code>date</code> is essential to a timeline.</p>
<p></p><pre class="crayon-plain-tag">...
struct EventTimesEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        VStack {
            Text(entry.eventTime)
            Text(entry.eventName)
        }
    }
} // end EventTimesEntryView
...</pre><p></p>
<p>This is the SwiftUI I used to display the widget. Do I even need to explain what I&#8217;m drawing here? Just look at my widget. I show the event&#8217;s time on the top line and the event&#8217;s name right below. It just amazes me how I can write such short, simple, and elegant code to get a UI. The declarative UI is here!</p>
<p></p><pre class="crayon-plain-tag">...
@main
struct EventTimes: Widget {
    let kind: String = "EventTimes"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            EventTimesEntryView(entry: entry)
        }
        .configurationDisplayName("My Daily Events")
        .description("Shows my typical workday schedule.")
    }
} // end EventTimes
...</pre><p></p>
<p>The <code>@main</code> attribute specifies the single entry point to my <code>Widget</code> extension. My widget is given a string tag for system identification purposes. I&#8217;m specifying the SwiftUI that my widget uses and I provide template text that people will see when they look up my widget so they can add it to my iPhone Home or Today View screens, as described in the next section.</p>
<h1> Adding widgets after the app is installed </h1>
<p>Once you install my sample app on an iPhone, you want to install one or more instances of its widget in one or more of the three available sizes. This ani-GIF shows you how to install a widget on the Home screen:</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/AddNewWidget.gif" title="Add widget to Home Screen" /></center></p>
<p>Note that I started the process by long-pressing on empty Home screen space. You can follow the same process on the Today View or, instead of starting by long-pressing, you can scroll down to the bottom of the page and tap the &#8220;Edit&#8221; button.</p>
<h1> Static versus user-configurable widgets </h1>
<p>Mainly because my &#8220;Events&#8221; app and widget are proofs of concept, they are static. While I&#8217;ve mentioned possibilities for editing the events and times, those values are currently fixed. But you can make your widget user-configurable. When the good folks who were writing the iPhone weather app added their widget extension, they ticked the <code>Include Configuration Intent</code> checkbox &#8212; that&#8217;s the checkbox we <strong>didn&#8217;t</strong> tick.</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/11/ConfigExtensionTargetOptions.png" title="Configure widget extension options" /></center></p>
<p>To make a long story short, you can configure the weather widget by long-tapping it until the context menu appears and selecting the &#8220;Edit Widget&#8221; item. The widget &#8220;flips over&#8221; to present an interface that allows you select from a list of nationwide locations that the widget will then show weather snapshots for.</p>
<h1> Conclusion </h1>
<p>Adding a widget to your app can add a whole lot of value to your app. You can make it so much more useful by allowing one glance to give users the gist of the main purpose of your app. Think of ways to make your apps **indispensable** to users &#8212; an essential part of their lives. Widgets are one of the best ways I&#8217;ve seen in recent years to accomplish this lofty goal.</p>
<p><!--Ads11--></p>
]]></content:encoded>
			</item>
		<item>
		<title>async/await &#8211; A core construct of Swift 5.5&#8217;s new concurrency model</title>
		<link>https://iosbrain.com/blog/2021/07/11/asyncawait-a-core-construct-of-swift-5-5s-new-concurrency-model/</link>
		<pubDate>Mon, 12 Jul 2021 03:00:03 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[Closures]]></category>
		<category><![CDATA[Concurrency]]></category>
		<category><![CDATA[Grand Central Dispatch (GCD)]]></category>
		<category><![CDATA[Swift]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3266</guid>
		<description><![CDATA[I first published this article on appcoda.com The goal: readable asynchronous/parallel code In designing the async/await construct, Apple is hoping to increase the readability, and thus maintainability, of implementing concurrency/parallelism in Swift. What I see in it are attempts: to make asynchronous/parallel code almost look like synchronous/sequential code; and, to make asynchronous/parallel code much more &#8230; <a href="https://iosbrain.com/blog/2021/07/11/asyncawait-a-core-construct-of-swift-5-5s-new-concurrency-model/" class="more-link">Continue reading<span class="screen-reader-text"> "async/await &#8211; A core construct of Swift 5.5&#8217;s new concurrency model"</span></a>]]></description>
				<content:encoded><![CDATA[<p><em><small>I first <a href="https://www.appcoda.com/async-await-concurrency/">published</a> this article on appcoda.com</small></em></p>
<h1>The goal: readable asynchronous/parallel code</h1>
<p>In designing the <code>async</code>/<code>await</code> construct, Apple is hoping to increase the readability, and thus maintainability, of implementing <a href="https://iosbrain.com/blog/2017/02/06/concurrency-in-ios-queues-and-other-definitions-in-grand-central-dispatch-gcd-with-swift-3/#concurrency">concurrency/parallelism</a> in Swift. What I see in it are attempts:</p>
<ul>
<li>to make asynchronous/parallel code <em>almost</em> look like synchronous/sequential code; and,</li>
<li>to make asynchronous/parallel code much more semantically clear (more readable, less verbose, compact, doing what it says).</li>
</ul>
<p>These are laudable and ambitious goals, but I&#8217;d say Apple&#8217;s heading in the right direction. I&#8217;m glad because I write a lot of asynchronous code to keep my apps responsive &#8212; to create the best possible user experience for my customers. I have a feeling that most of you write a lot of concurrent code, too.</p>
<p>We&#8217;ll walk through how to use <code>async</code>/<code>await</code> in detail, but I will limit my discussion to it. You need to understand <code>async</code>/<code>await</code> before trying to use Swift&#8217;s other new concurrency features, like actors, continuations, the <code>AsyncSequence</code> protocol, the <code>TaskGroup</code> generic structure, task cancellation, and a few other concepts.</p>
<p><span id="more-3266"></span></p>

<p>The Swift team has added hundreds of <code>async</code> (or &#8220;awaitable&#8221;) methods to the language, but I&#8217;d like you to focus on the <em>pattern</em> I use to implement most any call involving <code>async</code>/<code>await</code>, not on specific functions. To take an even broader view, I&#8217;ll compare using Swift&#8217;s <code>async</code>/<code>await</code> to using Swift&#8217;s <a href="https://iosbrain.com/blog/2018/03/07/concurrency-in-ios-serial-and-concurrent-queues-in-grand-central-dispatch-gcd-with-swift-4/">Grand Central Dispatch (GCD)</a> implementation. Both technologies offer &#8220;generic&#8221; support for parallelism. In other words, they both can support asynchronous/parallel code in a wide variety of applications, from long-running multi-step mathematical computations to large file downloads that all need to be run in the background. We&#8217;ll go over a common <code>async</code>/<code>await</code> beginner&#8217;s pitfall and finally end with some advice about where to go next with Swift concurrency.</p>
<p>Please note that <code>async</code>/<code>await</code> is <strong>not unique to Swift</strong>. Javascript, C++, Python, and C# are some examples of languages which support this construct. Also note that while <code>async</code>/<code>await</code> is nice to have, I wouldn&#8217;t want to give up access to GCD. It&#8217;s too powerful, despite its use of closures.</p>
<p>Please download my <a href="https://github.com/iosbrain/async-await---Core-construct-of-Swift-5.5-new-concurrency-model">sample Xcode 13 beta project</a>, written in Swift 5.5, essential for getting the most out of this tutorial. The Base SDK is iOS 15 beta and I used an iPhone 12 Pro Max for the base UI layout in my storyboard.</p>
<h1> The heart of the problem </h1>
<p>When faced with writing concurrent/asynchronous code, Swift developers are used to submitting a specific task, like downloading a big file, and then waiting for the download to finish in a completion handler or delegate callback. If you review an example of using Apple&#8217;s <a href="https://developer.apple.com/documentation/foundation/urlsession/1411511-downloadtask"><code>downloadTask(with:completionHandler:)</code></a> SDK call that <a href="https://iosbrain.com/blog/2018/05/26/introduction-to-mvvm-refactoring-an-mvc-app-using-the-mvvm-design-pattern/">I used in another article right here on iosbrain.com</a>, you&#8217;ll see that the code is a bit awkward, verbose, complex, hard to read, and spread out. Look at where I have to call <code>task.resume()</code> to start the download. Note that I defined the <code>ImageDownloadCompletionClosure</code> elsewhere in the code. It&#8217;s not super intuitive.</p>
<p></p><pre class="crayon-plain-tag">...
func download(completionHanlder: @escaping ImageDownloadCompletionClosure)
{

    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig)
    let request = URLRequest(url:imageURL)

    let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in

        if let tempLocalUrl = tempLocalUrl, error == nil {
            if let statusCode = (response as? HTTPURLResponse)?.statusCode {
                let rawImageData = NSData(contentsOf: tempLocalUrl)
                completionHanlder(rawImageData!)
                print("Successfully downloaded. Status code: \(statusCode)")
            }
        } else {
            print("Error took place while downloading a file. Error description: \(String(describing: error?.localizedDescription))")
        }
    } // end let task

    task.resume()

} // end func download
...</pre><p> </p>
<p>Apple, language architects, and many developers feel that the <code>block</code>&#8211;<code>completion handler</code> model is hard to read, especially when you&#8217;re nesting calls of this type. As <a href="https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html">Apple puts it</a>:</p>
<blockquote><p>&#8230;Even in [the] simple[st] case, because the code has to be written as a series of completion handlers, you end up writing nested closures. In this style, more complex code with deep nesting can quickly become unwieldy.</p></blockquote>
<p>So, to nested completion handlers, add error checking, like <a href="https://iosbrain.com/blog/2018/08/04/controlling-chaos-error-checking-in-swift-4-with-if-let-guard-and-failable-initializers/"><code>guard</code>, <code>if let</code></a>, <a href="https://iosbrain.com/blog/2018/05/01/controlling-chaos-error-handling-in-swift-4-with-do-try-catch-defer-throw-throws-error-and-nserror/"><code>do</code>, <code>try</code>, <code>catch</code>, <code>defer</code>, <code>throw</code>, <code>Error</code> &#8212; even <code>NSError</code></a>, which also can be nastily nested, you truly get yourself into a major pyramid of doom. Note that my sample project has very little in the way of error checking, not to be sloppy, but so you can concentrate on the subject of this article without distraction.</p>
<p>Enter the Swift 5.5 <code>async</code>/<code>await</code> keywords, which by no means constitute <strong>all</strong> the new Swift concurrency features. I believe you should first learn about <code>async</code>/<code>await</code> before exploring the rest of Swift&#8217;s new concurrency model.</p>
<h1> Good old GCD </h1>
<p>Let&#8217;s start out talking about a tool that many of us have used in the past to perform long-running operations in the background, thus freeing our apps to do other things, and allowing the user interface (UI) to remain responsive. One common scenario is downloading a background image for an app&#8217;s login screen while not preventing user interaction (like typing their username and password). Most of you should know about GCD, but if you don&#8217;t, I&#8217;ve written an extremely in-depth article on using it with Swift. In fact, the <a href="https://iosbrain.com/blog/2018/03/07/concurrency-in-ios-serial-and-concurrent-queues-in-grand-central-dispatch-gcd-with-swift-4/">sample code</a> I discussed in that article is used right here.</p>
<p>Let&#8217;s first read through my <code>downloadImageGCD</code> method, part of <a href="https://github.com/iosbrain/async-await---Core-construct-of-Swift-5.5-new-concurrency-model">this article&#8217;s companion project</a>. We&#8217;ll talk about that function in just a minute:</p>
<p></p><pre class="crayon-plain-tag">...
// example of GCD asynchronous code; as
// soon as an image download is queued, control
// flows immediately onwards
func downloadImageGCD(for url: String, with index:Int) -&gt; Void {

    DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {

        _ = self.isCodeOnMainThread(named: "start GCD image \(index) downloading...")
        let imageURL = URL(string: url)
        // this call blocks until the image data is downloaded,
        // BUT we're running in the background
        let imageData = NSData(contentsOf: imageURL!)
        // convert the data into an image
        let image = UIImage(data: imageData! as Data)

        DispatchQueue.main.async {
            self.imageViewStellar.image = image
            self.imageViewStellar.setNeedsDisplay()
            print("GCD image \(index) downloaded/displayed")
        }

    } // end DispatchQueue.global(qos: ...

} // end func downloadImageGCD
...</pre><p> </p>
<p>By wrapping my GCD code in a <code>for</code> loop, the downloading of 22 big image files are queued up, but the downloads occur in the background, so the UI remains responsive, and I can click any of my sample app&#8217;s buttons at any time and they do some concurrent work. The following <code>for</code> loop is called when you click the &#8220;Start GCD Downloading&#8221; button on the app&#8217;s main screen:</p>
<p></p><pre class="crayon-plain-tag">...
func startGCDAsyncImageDownload()
{
    for index in 0..&lt;imageURLs.count
    {
        downloadImageGCD(for: imageURLs[index], with: index)
    }
} // end func startAsyncImageDownload()
...</pre><p> </p>
<p>Watch the video of my app working and check out my <code>print</code> statements to the console. Notice there&#8217;s a bit of stuttering when I click the &#8220;Increment&#8221; button, but that&#8217;s mainly due to updating the <code>UIImageView</code> on the main thread:</p>
<p><center><img src="https://iosbrain.com/wp-content/uploads/2021/06/GCD_download.gif" /></center></p>
<p>My <code>downloadImageGCD</code> function is intrinsically asynchronous. Given a URL, you schedule a task to download the data at that URL on a background thread. Then you specify a completion handler to display the downloaded data in a <code>UIImageView</code> and move on. Code flow whips right through this function. By the time the images start displaying in the UI, you can be off somewhere else in the app&#8217;s code. <strong>REMEMBER: As shown above, <em>always</em> update your UI on the main thread.</strong> See my <code>updateImageView(with:)</code> used throughout the sample project.</p>

<p>Since I&#8217;m running my code on a multi-core processor, calling <code>downloadImageGCD</code> demonstrates true parallelism. Concurrency/asynchrony involves a stochastic (random) element. Look at my console output to see the random queuing and completion of tasks &#8212; and <a href="https://iosbrain.com/blog/2018/03/07/concurrency-in-ios-serial-and-concurrent-queues-in-grand-central-dispatch-gcd-with-swift-4/#cpuTool">go to Xcode&#8217;s <em>Debug navigator</em> -> <em>CPU</em> to see worker threads being created and eventually cleaned up</a>:</p>
<p></p><pre class="crayon-plain-tag">start GCD image 0 downloading... ON BACKGROUND THREAD
start GCD image 1 downloading... ON BACKGROUND THREAD
start GCD image 2 downloading... ON BACKGROUND THREAD
start GCD image 4 downloading... ON BACKGROUND THREAD
start GCD image 3 downloading... ON BACKGROUND THREAD
start GCD image 5 downloading... ON BACKGROUND THREAD
...
GCD image 9 downloaded/displayed
GCD image 21 downloaded/displayed
GCD image 7 downloaded/displayed
GCD image 18 downloaded/displayed
GCD image 12 downloaded/displayed
GCD image 5 downloaded/displayed</pre><p> </p>
<p>I purposely used the <code>init(contentsOf:)</code> initializer of <code>NSData</code> to download image data because it is a synchronous, blocking call, a concept central to this article. Yes, it blocks until <strong>all</strong> data at the specified URL downloads, but I&#8217;m using that <code>NSData</code> initializer on a <strong>background</strong> thread. If you called that function on your main thread, your app would freeze until all URL data downloads. Remember that I submitted the synchronous download inside a block passed to the very <strong>asynchronous</strong> <code>DispatchQueue...async {...}</code>. Later, we&#8217;ll see that &#8220;blocking&#8221; or &#8220;suspending&#8221; have a different meaning in <code>async</code>/<code>await</code>.</p>
<p>The SDKs available to Swift have been populated with many, many calls that include completion handlers or delegate callbacks, not just <code>DisptachQueue</code>. I have a lot of good asynchronous code that&#8217;s already been written using the <code>block</code>&#8211;<code>completion handler</code> pattern. I&#8217;m certainly not going to go back and rewrite it all using the new Swift concurrency gimmicks. But looking forward, I will consider using constructs like <code>async</code>/<code>await</code>.</p>
<h1> The Swift 5.5 <code>async</code>/<code>await</code> construct </h1>
<p>Let&#8217;s define some terminology essential to understanding Swift&#8217;s new concurrency model.</p>
<p><code>async</code>:</p>
<ul>
<li>add this keyword to a function signature (declaration) to denote that that method is asynchronous, i.e., can potentially run code in parallel with other code, and can be subject to suspension and later resumption</li>
<li>suspension may occur, for example, to await the results of some long-running task</li>
<li>suspension may occur, for example, for short-term tasks like updating the UI</li>
<li>suspension may not occur at all</li>
<li>functions marked <code>async</code> must themselves call <code>await</code> to be suspended (see below)</li>
<li>when an async function suspends, it does not block its thread</li>
<li>when an async function suspends, the operating system can queue and execute other processes on it&#8217;s thread</li>
</ul>
<p><code>await</code>:</p>
<ul>
<li>obviously marks a potential suspension point in your code, making that suspension point clear to people reading the code</li>
<li>the code on the rest of the line following the <code>await</code> can be scheduled by the system for running a long task</li>
<li>that long task can be suspended once or many times so the system can execute other work</li>
<li>a shorter task might not be suspended at all and it can run to completion</li>
<li>once its task finishes, the <code>await</code> line finishes, and execution continues on the next line</li>
<li>when Swift suspends the current thread,  other code is allowed to execute on that same thread</li>
</ul>
<p><code>async-let</code>:</p>
<ul>
<li>lets you call asynchronous functions when you don&#8217;t need the return value immediately</li>
<li>you can start one or many tasks that can be run in parallel</li>
<li>other code can run while your asynchronous functions process</li>
</ul>
<p><code>async {...}</code>:</p>
<ul>
<li>enables you to kick off asynchronous work from within regular, synchronous code, like from within a function <strong>not</strong> labelled <code>async</code></li>
<li>you call your asynchronous code between the &#8220;{&#8221; and &#8220;}&#8221;</li>
</ul>
<h2> How to write code with <code>async</code>/<code>await</code> </h2>
<p>Now that we&#8217;ve defined the terms <code>async</code> and <code>await</code> at a theoretical level, let&#8217;s learn how to write code using these constructs. As an alternative to my <code>downloadImageGCD</code> method, which uses GCD with a completion handler, let&#8217;s write an <code>async</code> function that you call with an image URL and it <strong>returns</strong> the image data, kind of like a synchronous function would do so. But it doesn&#8217;t block, it possibly suspends for a relatively brief period while the image downloads, probably on a background thread, but that is not guaranteed as I understand the new Swift construct (see my definitions above).</p>
<p></p><pre class="crayon-plain-tag">...
func downloadImageAsync(for url: String, with index:Int) async throws -&gt; UIImage {

    _ = isCodeOnMainThread(named: "start awaitable image \(index) downloading...")
    let request = URLRequest(url: URL(string: url)!)
    let (data, response) = try await URLSession.shared.data(for: request)
    guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw HTTPError.withIdentifier((response as! HTTPURLResponse).statusCode) }
    let downloadedImage = UIImage(data: data)
    return downloadedImage!

} // end func downloadImageAsync
...</pre><p> </p>
<p>Notice that we place the <code>async</code> keyword just after the method signature&#8217;s parameter list but before the <code>throws</code> and the return type. Pause for a moment to review my <code>async</code> keyword definition up above.</p>
<p>The key to this method is this line:</p>
<p></p><pre class="crayon-plain-tag">let (data, response) = try await URLSession.shared.data(for: request)</pre><p> </p>
<p>Since <code>URLSession.shared.data</code> is <code>async</code> (&#8220;awaitable&#8221;), we <em>must</em> call it with <code>await</code>; it also <code>throws</code>. If an <code>async</code> function <code>throws</code>, you always put a <code>try</code> before the <code>await</code>, as we did here when calling the function. The lines of code both before and after <code>data(for:)</code> on the shared URLSession are synchronous. The code after this network download call is dependent on the <code>data</code> and <code>response</code> it returns, so it must suspend while the image data at <code>url</code> downloads. Here&#8217;s the magic: while this line (and its containing method) suspend, <strong>other work in the app can be done.</strong></p>
<p>A great benefit of writing code with <code>async</code>/<code>await</code> is the enhanced readability. You can obviously see asynchronous code and potential suspension points. There&#8217;s also less clutter without the closure syntax.</p>
<h2> Our first try at <code>async</code>/<code>await</code> </h2>
<p>To prove to you that <code>async</code>/<code>await</code> works efficiently and allows other app work to be done simultaneously, let&#8217;s do an experiment with my code. I&#8217;ve got some code commented out, but don&#8217;t make any changes yet. Let&#8217;s review what you&#8217;ll do first. Here&#8217;s the code that my app&#8217;s &#8220;Start Proper Awaitable Downloading&#8221; button calls:</p>
<p></p><pre class="crayon-plain-tag">...
@IBAction func startProperAwaitableDownloadingButtonClicked(_ sender: Any) {

    counter = 0;
    counterTextField.text = "0"
    imageViewStellar.image = nil

    async {

        let image = try! await downloadImageAsync(for: imageAltURLs[0], with: 0)
        updateImageView(with: image)
        print("GIANT FILE FINALLY DOWNLOADED")
        //await startRightNewSimpleSyncImageDownload()
        //await startRightNewSimpleAsyncImageDownload()
        //await startExperimentAsyncImageDownload()
        //await startTaskGroupAsyncImageDownload()
    }

} // end startProperAwaitableDownloadingButtonClicked
...</pre><p> </p>
<p>While this <code>@IBAction func</code> is synchronous, note that you can call <code>async</code> code by wrapping it in the <code>async{...}</code> construct as defined above. The image at the URL in <code>imageAltURLs[0]</code> is gigantic and takes awhile to download. You already saw earlier that my <code>downloadImageGCD</code> function downloads and displays 22 large image files. Ready? Run my app and press the &#8220;Start Proper Awaitable Downloading&#8221; button, then quickly press the &#8220;Start GCD Downloading&#8221; button.</p>

<p>Your console output should be similar to that shown next, though not exactly the same. You&#8217;ll see the <code>async</code> call to download the huge file start up and suspend. Then you&#8217;ll see the GCD function simultaneously queuing and downloading 22 images. Most of the time, the <code>async</code> file will download later to last when considering all total 23 downloads, not because there&#8217;s anything wrong with <code>async</code>, but because it&#8217;s downloading a very large file.</p>
<p></p><pre class="crayon-plain-tag">start awaitable image 0 downloading... ON MAIN THREAD
start GCD image 0 downloading... ON BACKGROUND THREAD
start GCD image 1 downloading... ON BACKGROUND THREAD
start GCD image 2 downloading... ON BACKGROUND THREAD
start GCD image 3 downloading... ON BACKGROUND THREAD
...
start GCD image 19 downloading... ON BACKGROUND THREAD
start GCD image 21 downloading... ON BACKGROUND THREAD
start GCD image 20 downloading... ON BACKGROUND THREAD
GCD image 0 downloaded/displayed
GCD image 4 downloaded/displayed
GCD image 2 downloaded/displayed
...
GCD image 20 downloaded/displayed
GCD image 21 downloaded/displayed
GCD image 16 downloaded/displayed
GIANT FILE FINALLY DOWNLOADED</pre><p> </p>
<h1> How NOT to use <code>async</code>/<code>await</code> </h1>
<p>Unless you&#8217;re enforcing some specific order of execution because of certain interdependencies, I would advise you to avoid using a bunch of <code>await</code> calls in sequence. Let&#8217;s look at two examples from my project. Here&#8217;s a &#8220;manual&#8221; example:</p>
<p></p><pre class="crayon-plain-tag">...
// these downloads occur SEQUENTIALLY because we
// start each download with the "await" keyword
func startRightNewSimpleSyncImageDownload() async -&gt; Void {

    let stellarImage0 = try! await downloadImageAsync(for: imageURLs[0], with: 0)
    let stellarImage1 = try! await downloadImageAsync(for: imageURLs[1], with: 1)
    let stellarImage2 = try! await downloadImageAsync(for: imageURLs[2], with: 2)

    _ = isCodeOnMainThread(named: "startRightNewAsyncImageDownload")

    // no await is needed
    updateImageView(with: stellarImage0)
    print("stellarImage0 with index 0 downloaded")
    updateImageView(with: stellarImage1)
    print("stellarImage1 with index 1 downloaded")
    updateImageView(with: stellarImage2)
    print("stellarImage2 with index 2 downloaded")

} // end func startRightNewSimpleSyncImageDownload
...</pre><p> </p>
<p>Here&#8217;s a &#8220;automated&#8221; example (I used a <code>for</code> loop):</p>
<p></p><pre class="crayon-plain-tag">...
// this method is a misguided attempt to
// call a bunch of blocking calls all at once
func startWrongNewAsyncImageDownload()
{

    async {

        for index in 0..&lt;imageURLs.count {
            let url = imageURLs[index]
            let downloadedImage = try! await self.downloadImageAsync(for: url, with: index)
            imageViewStellar.image = downloadedImage
            print("awaitable image \(index) downloaded/displayed")
        }

    } // end async

} // end func startWrongNewAsyncImageDownload()
...</pre><p> </p>
<p>Why would I impose such a sequential ordering, especially if I were preparing an image gallery and/or the thumbnails for a <code>UICollectionView</code>? Even with concurrency involved, think of what would happen if each of the image downloads was in the order of 170 MB, as opposed to the ~30 MB files I&#8217;m downloading from my URL array&#8217;s addresses. Or suppose I had a long list of mathematically intense calculations? I&#8217;d have a lot of uninterruptible tasks that would make my app run sluggishly at best. Even if I were required to enforce a sequence of tasks, each dependent on the previous one, this wouldn&#8217;t be the most optimal way to encode my work. See the console output:</p>
<p></p><pre class="crayon-plain-tag">start awaitable image 0 downloading... ON MAIN THREAD
awaitable image 0 downloaded/displayed
start awaitable image 1 downloading... ON MAIN THREAD
awaitable image 1 downloaded/displayed
start awaitable image 2 downloading... ON MAIN THREAD
awaitable image 2 downloaded/displayed
start awaitable image 3 downloading... ON MAIN THREAD
awaitable image 3 downloaded/displayed
start awaitable image 4 downloading... ON MAIN THREAD
awaitable image 4 downloaded/displayed
start awaitable image 5 downloading... ON MAIN THREAD
awaitable image 5 downloaded/displayed
start awaitable image 6 downloading... ON MAIN THREAD
awaitable image 6 downloaded/displayed
start awaitable image 7 downloading... ON MAIN THREAD
awaitable image 7 downloaded/displayed
start awaitable image 8 downloading... ON MAIN THREAD
awaitable image 8 downloaded/displayed
start awaitable image 9 downloading... ON MAIN THREAD
awaitable image 9 downloaded/displayed
start awaitable image 10 downloading... ON MAIN THREAD
awaitable image 10 downloaded/displayed
start awaitable image 11 downloading... ON MAIN THREAD
awaitable image 11 downloaded/displayed
start awaitable image 12 downloading... ON MAIN THREAD
awaitable image 12 downloaded/displayed
start awaitable image 13 downloading... ON MAIN THREAD
awaitable image 13 downloaded/displayed
start awaitable image 14 downloading... ON MAIN THREAD
awaitable image 14 downloaded/displayed
start awaitable image 15 downloading... ON MAIN THREAD
awaitable image 15 downloaded/displayed
start awaitable image 16 downloading... ON MAIN THREAD
awaitable image 16 downloaded/displayed
start awaitable image 17 downloading... ON MAIN THREAD
awaitable image 17 downloaded/displayed
start awaitable image 18 downloading... ON MAIN THREAD
awaitable image 18 downloaded/displayed
start awaitable image 19 downloading... ON MAIN THREAD
awaitable image 19 downloaded/displayed
start awaitable image 20 downloading... ON MAIN THREAD
awaitable image 20 downloaded/displayed
start awaitable image 21 downloading... ON MAIN THREAD
awaitable image 21 downloaded/displayed</pre><p> </p>
<p>As we&#8217;ll see below, I can use <code>async</code>/<code>await</code> to download a whole bunch of images in parallel/simultaneously.</p>
<h1> Running multiple parallel tasks with <code>async</code>/<code>await</code> </h1>
<p>I always try to learn a new technology myself instead of waiting for someone else to figure it out and then doing copy and paste programming. I like to actually work through a practice test before looking at the answers in the back of the book. I want to figure out <em>why</em> I got some answers wrong.</p>
<p>Such was the case with figuring out how to run multiple parallel tasks with <code>async</code>/<code>await</code>. I was able to figure out how to manually use <code>async-let</code>. When I say &#8220;manually,&#8221; I mean I could start a fixed number of tasks, but couldn&#8217;t figure out how generalize my code for some varying number of tasks. I think the problem with <code>async-let</code> is that the construct has a <code>let</code>, implying a constant, not a variable.</p>
<p>Here&#8217;s my successful attempt at spawning 3 image downloads in parallel &#8212; and displaying the images from the downloaded data:</p>
<p></p><pre class="crayon-plain-tag">...
// each download occurs asynchronously -- even simultaneously
func startRightNewSimpleAsyncImageDownload() async -&gt; Void {

    async let stellarImage0 = try! downloadImageAsync(for: imageURLs[0], with: 0)
    async let stellarImage1 = try! downloadImageAsync(for: imageURLs[1], with: 1)
    async let stellarImage2 = try! downloadImageAsync(for: imageURLs[2], with: 2)

    _ = isCodeOnMainThread(named: "startRightNewAsyncImageDownload")

    updateImageView(with: await stellarImage0)
    print("stellarImage0 with index 0 downloaded")
    updateImageView(with: await stellarImage1)
    print("stellarImage1 with index 1 downloaded")
    updateImageView(with: await stellarImage2)
    print("stellarImage2 with index 2 downloaded")

} // end func startRightNewSimpleAsyncImageDownload
...</pre><p> </p>
<p>OK, this works, but it is way too specific of a solution. What if I wanted to be able to download 2, 10, 30, or 60 images using some kind of repetitive language construct, like <code>for</code> or <code>while</code>? I tried to figure this repetitive thing out for awhile &#8212; without looking for somebody else&#8217;s solution. Look at my <code>startExperimentAsyncImageDownload()</code> function for evidence of my failed attempts.</p>
<h1> Using a <code>TaskGroup</code> with <code>async</code>/<code>await</code> </h1>
<p>In an effort to find a repetitive solution to downloading any number of images, I did some research. All&#8217;s I found was a <a href="https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html#ID642">brief section in some Swift documentation</a> with a theoretical and not really usable solution. But I did get something working. Look at my sample code for a method named <code>startTaskGroupAsyncImageDownload()</code>, study it, run it, look at the console output, and watch my sample app&#8217;s screen while the function is working. Here&#8217;s the code:</p>
<p></p><pre class="crayon-plain-tag">...
// new Swift structured concurrency using
// tasks and task groups
func startTaskGroupAsyncImageDownload() async -&gt; Void {

    _ = self.isCodeOnMainThread(named: "startRightNewAsyncImageDownload started")

    await withTaskGroup(of: UIImage.self) { taskGroup in

        for index in 0..&lt;imageURLs.count {
            taskGroup.async {
                //_ = await self.isCodeOnMainThread(named: "task for image \(index) downloading started...")
                let downloadedImage = try! await self.downloadImageAsync(for: self.imageURLs[index], with: index)
                return downloadedImage
            }
        }

        // "To collect the results of tasks that
        // were added to the group, you can use
        // the following pattern:"
        for await image in taskGroup {
            _ = self.isCodeOnMainThread(named: "task awaited image downloaded")
            // notice I didn't have to jump
            // on the main queue to update the UI
            self.imageViewStellar.image = image
            print("task awaited image displayed")
            // DispatchQueue.main.async {
            //      self.imageViewStellar.image = downloadedImage
            // }
        }

    } // end withTaskGroup

} // end func startTaskGroupAsyncImageDownload()
...</pre><p> </p>
<p>Now this code acts truly concurrent. Hey, wait a minute. We&#8217;re using a <em>closure</em>. Hmmm&#8230;</p>
<p>I&#8217;m not going into a detailed explanation of this method as the main purpose of this article is introducing readers to <code>async</code>/<code>await</code>. But let me share one insight. See my comment above this line of code?</p>
<p></p><pre class="crayon-plain-tag">for await image in taskGroup {</pre><p> </p>
<p>This was key to figuring out how to make my experimental code work. I found this <strong>not</strong> on the Swift website, but in the Xcode context sensitive help when I clicked on the <code>withTaskGroup</code> keyword:</p>
<blockquote><p>To collect the results of tasks that were added to the group, you can use the following pattern: &#8230;</p></blockquote>
<h1> Conclusion </h1>
<p>Understanding Swift 5.5&#8217;s new concurrency features starts with <code>async</code>/<code>await</code>. I hope you learned a lot here today. I encourage you to practice using <code>async</code>/<code>await</code> with my sample code, study the links I&#8217;ve included in this article, and then to push forward through all the WWDC 2021 presentations on Swift&#8217;s other new concurrency features, like on actors, continuations, the <code>AsyncSequence</code> protocol, the <code>TaskGroup</code> generic structure, task cancellation, and a few other concepts. I especially recommend the WWDC 2021 sessions on <a href="https://developer.apple.com/videos/play/wwdc2021/10134">&#8220;Explore structured concurrency in Swift&#8221;</a>, <a href="https://developer.apple.com/videos/play/wwdc2021/10133">&#8220;Protect mutable state with Swift actors&#8221;</a>, and <a href="https://developer.apple.com/videos/play/wwdc2021/10254">&#8220;Swift concurrency: Behind the scenes&#8221;</a>.</p>
<p><strong>One bit of homework:</strong> Look at my sample code&#8217;s <code>isCodeOnMainThread(named:)</code> function. Can you explain why the function prints &#8220;&#8230;ON MAIN THREAD&#8221; in some places while &#8220;&#8230;ON BACKGROUND THREAD&#8221; in others? I&#8217;m sure the <code>Thread.isMainThread</code> is working properly. I&#8217;ll respond to any comments left on my article regarding this question, or respond to any other comments you may have.</p>
<p>Enjoy!</p>

]]></content:encoded>
			</item>
		<item>
		<title>The real importance of WWDC 2021: raw computing power (CPU), raw graphics power (GPU), and big high resolution screens</title>
		<link>https://iosbrain.com/blog/2021/06/13/the-real-importance-of-wwdc-2021-raw-computing-power-cpu-raw-graphics-power-gpu-and-big-high-resolution-screens/</link>
		<pubDate>Mon, 14 Jun 2021 00:41:54 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[App Monetization]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[General Technology]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3237</guid>
		<description><![CDATA[Photographers can&#8217;t professionally fine-tune an image of a mountainous landscape&#8217;s foreground and background on a tiny little iPhone screen. A data scientist can&#8217;t layout graphs, matrices, vectors, and spreadsheets on a tiny little iPhone screen. A customer service representative can&#8217;t troubleshoot a technology problem without searching through several device schematics, handle several different calls at &#8230; <a href="https://iosbrain.com/blog/2021/06/13/the-real-importance-of-wwdc-2021-raw-computing-power-cpu-raw-graphics-power-gpu-and-big-high-resolution-screens/" class="more-link">Continue reading<span class="screen-reader-text"> "The real importance of WWDC 2021: raw computing power (CPU), raw graphics power (GPU), and big high resolution screens"</span></a>]]></description>
				<content:encoded><![CDATA[<p>Photographers can&#8217;t professionally fine-tune an image of a mountainous landscape&#8217;s foreground and background on a tiny little iPhone screen. A data scientist can&#8217;t layout graphs, matrices, vectors, and spreadsheets on a tiny little iPhone screen. A customer service representative can&#8217;t troubleshoot a technology problem without searching through several device schematics, handle several different calls at once, be on the phone with one customer, be texting with another customer, and looking at a user&#8217;s guide that shows which buttons and switches do what things on a tiny little phone screen. Can you imagine trying to design, read, write, and debug code, and layout your UI with Xcode on an iPhone? (I could on a large iPad or MacBook, but not a phone).</p>
<p><span id="more-3237"></span></p>
<p>Some people are yawning about <a href="https://developer.apple.com/wwdc21/">WWDC 2021</a> because of its incremental &#8212; as opposed to quantum &#8212; leap forwards. If you look around the web for summaries of this year&#8217;s WWDC, you&#8217;ll find lots and lots of simple lists of new features, the implication being that this year is just about tossing customers a few new gadgets. In this article, I&#8217;m positing that Apple&#8217;s making a big jump in terms of its strategic long-term planning and direction.</p>
<p>WWDC 2021 is one of the most significant developer conferences in Apple&#8217;s history. The company refocused on the Mac and macOS. Apple is reinforcing its focus on iPad and iPadOS. The company is making the desktop and tablet platforms into the center of a business&#8217;s, family&#8217;s, or individual&#8217;s technology life blood: information and tools for accessing searching, organizing, analyzing and storing that information. Cook&#8217;s yearly sermon espoused three predominant themes:</p>
<ol>
<li>having lots of high resolution screen space;</li>
<li>having the computing power to crunch large quantities of data in real time (CPU), and;</li>
<li>then taking that crunched CPU data, including changes made to it, and displaying it in real time on-screen (GPU).</li>
</ol>
<p>By strategically focusing on the products and services that require enough room to spread your work out neatly, organized, and all at one time, Apple has recognized a much-overlooked reality: the mobile device has matured. Even though Apple is leading more than <a href="https://developer.apple.com/wwdc21/sessions/">200 detailed developer sessions</a> to help coders create apps for the biggest app store in the world, at his initial keynote announcement, Tim Cook spent almost half of his time discussing his company&#8217;s great strides forwards on the three topics I listed above: raw computing horsepower, raw graphics horsepower, and enabling customers to work with their precious data on large crisp and clear screens driven by central and graphics processing units that show your data &#8212; especially changes made to that data &#8212; in real time. Apple didn&#8217;t just announce a new in-house CPU this year, they delivered it.</p>
<p>To emphasize the impact of the new M1 CPU, Cook noted that Xcode runs 85% faster than on Intel-based processors, while the GPU is 2 times faster, and machine learning is 3 times faster.</p>
<p>Yes, there are new versions of watchOS, iOS, and tvOS, and lots of new SDKs, respectively, but I still hold to this article&#8217;s core premise. I&#8217;m not diminishing Apple&#8217;s incremental changes to its various product lines; I&#8217;m trying to give you an idea of the strategic future direction of the company.</p>
<p>Over the next few days and weeks, please return to join me as I discuss WWDC 2021 development issues in detail. For now, I&#8217;ll show you how to prepare for learning about and implementing Apple&#8217;s cavalcade of new technologies. Take a look at the following list of links (below) that will enable you to download all the tools you need to try out the new technologies. I&#8217;ve also included links to resources that you can watch or read to help you with those tools. You can then start developing new apps using <a href="https://developer.apple.com/wwdc21/sessions/">Apple&#8217;s developer sessions</a>, new SDKs, and new tools.</p>
<p><strong>NOTE: You need to be a member of the <a href="https://developer.apple.com/programs/">Apple Developer Program</a> to access these resources (for an individual, like a single-member LLC, it&#8217;ll cost you $99/year). You&#8217;ll find all of this year&#8217;s beta downloads aggregated at <a href="https://developer.apple.com/download/">this link</a> (login required).</strong></p>
<p>You should watch the <a href="https://developer.apple.com/wwdc21/sessions/">200+ detailed developer sessions</a> in Apple&#8217;s new technologies to learn about implementing them. In the coming days and weeks, I&#8217;ll provide guidance into specific new/improved SDKs, which ones I feel are the most important, and provide tutorials to help you include new features in your apps.</p>
<p><strong><u>New Developer Tools</u></strong></p>
<ul>
<li><strong>Xcode 13 Beta</strong>
<ul>
<li><a href="https://developer.apple.com/documentation/Xcode-Release-Notes/xcode-13-beta-release-notes">Release notes</a></li>
<li><a href="https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_13_beta/Xcode_13_beta.xip">Download</a></li>
</ul>
</li>
<ul>
<li><strong>macOS Monterey 12 Beta</strong>
<ul>
<li><a href="https://developer.apple.com/documentation/macos-release-notes/macos-12-beta-release-notes">Release notes</a></li>
<li><a href="https://developer.apple.com/services-account/download?path=/WWDC_2021/macOS_12_Developer_Beta_Access_Utility/macOSDeveloperBetaAccessUtility.dmg">Install profile</a></li>
<li><a href="https://9to5mac.com/2021/06/10/how-to-install-macos-monterey-beta/">Installation tips</a></li>
</ul>
</li>
<ul>
<li><strong>iOS 15 Beta</strong>
<ul>
<li><a href="https://developer.apple.com/go/?id=ios-15-sdk-rn">Release notes</a></li>
<li><a href="https://developer.apple.com/services-account/download?path=/WWDC_2021/iOS_15_beta/iOS_15_Beta_Profile.mobileconfig">Install profile</a></li>
<li><a href="https://www.theverge.com/22524845/ios-15-how-to-install">Installation tips</a></li>
</ul>
</li>
</ul>
<ul>
<li><strong>iPadOS 15 Beta</strong>
<ul>
<li><a href="https://developer.apple.com/go/?id=ipados-15-sdk-rn">Release notes</a></li>
<li><a href="https://developer.apple.com/services-account/download?path=/WWDC_2021/iPadOS_15_beta/iOS_iPadOS_15_Beta_Profile.mobileconfig">Install profile</a></li>
</ul>
</li>
</ul>
<ul>
<li><strong>watchOS 8 Beta</strong>
<ul>
<li><a href="https://developer.apple.com/go/?id=watchos-8-sdk-rn">Release notes</a></li>
<li><a href="https://developer.apple.com/services-account/download?path=/WWDC_2021/watchOS_8_beta/watchOS_8_Beta_Profile.mobileconfig">Install profile</a></li>
</ul>
</li>
</ul>
<ul>
<li><strong>tvOS 15 Beta</strong>
<ul>
<li><a href="https://developer.apple.com/documentation/tvos-release-notes/tvos-15-beta-release-notes">Release notes</a></li>
<li><a href="https://developer.apple.com/services-account/download?path=/WWDC_2021/tvOS_15_beta/tvOS_15_Beta_Profile.mobileconfig">Install profile</a></li>
</ul>
</li>
</ul>

]]></content:encoded>
			</item>
		<item>
		<title>Using the &#8216;plutil&#8217; utility to fix improperly-formatted Xcode plist files</title>
		<link>https://iosbrain.com/blog/2020/02/09/using-the-plutil-utility-to-fix-improperly-formatted-xcode-plist-files/</link>
		<pubDate>Mon, 10 Feb 2020 05:13:41 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[Compiling]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[Troubleshooting]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3209</guid>
		<description><![CDATA[How do you find typos (syntax errors) in an improperly formatted plist (property list) file, especially when Xcode provides absolutely no detail about badly formed XML? I often see plist files with a thousand or more lines of text! In this article, I&#8217;ll show you how to fix plist bugs &#8212; and do a few &#8230; <a href="https://iosbrain.com/blog/2020/02/09/using-the-plutil-utility-to-fix-improperly-formatted-xcode-plist-files/" class="more-link">Continue reading<span class="screen-reader-text"> "Using the &#8216;plutil&#8217; utility to fix improperly-formatted Xcode plist files"</span></a>]]></description>
				<content:encoded><![CDATA[<p>How do you find typos (syntax errors) in an improperly formatted <code>plist</code> (property list) file, especially when Xcode provides absolutely no detail about badly formed XML? I often see <code>plist</code> files with a thousand or more lines of text<strong>!</strong> In this article, I&#8217;ll show you how to fix <code>plist</code> bugs &#8212; and do a few other things &#8212; by using the little-known <code>plutil</code> command line tool.</p>
<p>How many times have you seen the following error message, shown below in textual and graphical format, when doing a build?</p>
<p></p><pre class="crayon-plain-tag">: couldn't parse contents of '/path/to/project/projectName/projectName/Info.plist': The data couldn't be read because it isn't in the correct format.</pre><p> </p>
<p><img src="https://iosbrain.com/wp-content/uploads/2020/02/Info-plist-build-error.png" alt="Info.plist build error" width="764" height="242" class="size-full wp-image-3212" srcset="https://iosbrain.com/wp-content/uploads/2020/02/Info-plist-build-error.png 764w, https://iosbrain.com/wp-content/uploads/2020/02/Info-plist-build-error-300x95.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /><br />
<br />
<a href="https://iosbrain.com/blog/2020/02/09/using-the-plutil-utility-to-fix-improperly-formatted-xcode-plist-files/#solution">Jump straight to the fix</a> or take a minute to read a little background. </p>
<p><span id="more-3209"></span></p>

<h4>Background</h4>
<p>When performing complex development with Xcode, it&#8217;s hard to avoid working with the <code>plist</code> file. When creating a new project, Xcode automatically creates one named &#8220;Info.plist&#8221; and makes it part of your physical folder structure and includes it very obviously in the <code>Project Navigator</code>. You can rename it to your own liking, and sometimes use multiple plist files, especially when you have multiple targets. While some people recommend only editing the contents of OS X or iOS project <code>plist</code> files using the Xcode user interface, I find that advice to be unrealistic.</p>
<p>One common scenario for custom usage of the <code>plist</code> file comes to mind: </p>
<ul>
<li>What if your app supports its own file format and your files have a unique extension?</li>
<li>Say that your users want those files to automagically open in your app when they select one in the iOS <a href="https://iosbrain.com/blog/2018/06/18/ios-11-files-app-integration-and-the-uidocumentbrowserviewcontroller/" rel="noopener" target="_blank"><code>Files</code> app</a> or macOS&#8217;s <code>Finder</code>?</li>
<li>Say your users exchange your proprietary files using text messages or email.</li>
</ul>
<p>When someone receives one of those files and wants to open it with your app, you&#8217;ll have to&#8230; Guess what? Add and configure the  <code>Document Types</code>, <code>Imported UTIs</code>, and <code>Exported UTIs</code> sections of your app project&#8217;s <code>plist</code> file. Doing so is beyond the scope of this article, but I mention it to emphasize the importance of <code>plist</code> files. If you want to learn about associating files with your apps, I suggest you start by reading Apple&#8217;s <a href="https://developer.apple.com/library/archive/qa/qa1587/_index.html" rel="noopener" target="_blank">&#8220;Technical Q&#038;A QA1587 &#8211; Q:  How do I get my application to show up in the &#8220;Open in&#8230;&#8221; menu on iOS for a specific document type?&#8221;</a></p>
<p>I was once working on an app that supported over 40 file type associations, all with different file extensions (i.e., filename.<strong>ext</strong> where <strong>ext</strong> is the extension). Once I created my first <code>Document Types</code> and <code>Exported UTIs</code> elements, I opened my plist in <code>Source Code</code> view and used copy and paste to configure the remaining 40+. To make sure my XML was formatted properly, I switched from <code>Source Code</code> view back to <code>Property List</code> view. Guess what happened when Xcode parsed my XML so it could show my plist as a <code>Property List</code>? Bang &#8212; useless error message. Watch:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2020/02/Open-As-Property-List.gif" title="Open as Property List" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2020/02/Open-As-Property-List.gif" /></a></center></p>
<p>All&#8217;s I get is a dialog box that says &#8220;The data couldn&#8217;t be read because it isn&#8217;t in the correct format.&#8221; I get the same message when building. So with Xcode, <strong>I have to go through possibly a thousand lines of code to find the error?</strong> </p>

<p><a name="solution"></a></p>
<h4>The fix: plutil</h4>
<p>Before you start reading through a thousand lines of XML to find some minor syntax errors that are giving you major headaches, try the <code>plutil</code> command line utility, or as the OS X <a href="https://www.unix.com/man-page/osx/1/plutil/" rel="noopener" target="_blank"><code>man</code> page calls it</a>, the &#8220;property list utility.&#8221; Open <code>Terminal</code>, change directory (<code>cd</code>) to the folder that contains the offending <code>plist</code> file, and enter the following command:</p>
<p></p><pre class="crayon-plain-tag">% plutil Info.plist</pre><p> </p>
<p>Of course, enter the name of <em>your</em> <code>plist</code>. You&#8217;ll get some very helpful output. It will help you fix your error(s). Here&#8217;s what <code>plutil</code> told me was the problem with my plist:</p>
<p></p><pre class="crayon-plain-tag">% plutil Info.plist
Info.plist: Encountered unexpected character / on line 37 while looking for open tag</pre><p> </p>
<p>Let&#8217;s look at line 37 of my <code>plist</code> and see exactly what&#8217;s wrong, in textual and graphical format:</p>
<p></p><pre class="crayon-plain-tag">...
	&lt;true/&gt;
	&lt;key&gt;NSSupportsSuddenTermination&lt;/key&gt;
	&lt;true/&gt;
/dict&gt;
&lt;/plist&gt;</pre><p> </p>
<p><img src="https://iosbrain.com/wp-content/uploads/2020/02/plist-error.png" alt="" width="710" height="212" class="aligncenter size-full wp-image-3221" srcset="https://iosbrain.com/wp-content/uploads/2020/02/plist-error.png 710w, https://iosbrain.com/wp-content/uploads/2020/02/plist-error-300x90.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></p>
<p>This could be an instance of where I copied and pasted, but missed a single character when copying, or I was typing XML and forgot the open bracket (&#8220;<") for a tag.

Pretty simple, right?



<h4>Where to go next</h4>
<p>I urge you to take a look at the documentation on <code>plutil</code> by bringing up its <code>man</code> page at <code>Terminal's</code> command prompt:</p>
<p></p><pre class="crayon-plain-tag">% man plist</pre><p> </p>
<p>There are quite a few interesting things you can do with <code>plutil</code>. You can print the contents of your <code>plist</code> in a very readable <code>json</code> format. I find this option very useful when troubleshooting. If you type <code>plutil -help</code>, you can get very detailed assistance in using this utility for converting your <code>plist</code> into binary, setting or replacing individual values, inserting new values, and printing individual elements. This is deep down in the weeds but, trust me, when troubleshooting some apps, like the one I discussed above with file associations, you&#8217;ll be glad you learned about <code>plutil</code>.</p>

]]></content:encoded>
			</item>
		<item>
		<title>We&#8217;re still here&#8230;</title>
		<link>https://iosbrain.com/blog/2019/03/28/were-still-here/</link>
		<pubDate>Fri, 29 Mar 2019 01:07:33 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[General Technology]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3203</guid>
		<description><![CDATA[Some of you have been kind enough to ask why we haven&#8217;t been publishing for a few months. Thank you for your concern. We&#8217;ve been busy, but be patient as you&#8217;ll soon be seeing us post articles again&#8230; And we&#8217;ve got some big plans for the future, including books, online courses, and video tutorials, just &#8230; <a href="https://iosbrain.com/blog/2019/03/28/were-still-here/" class="more-link">Continue reading<span class="screen-reader-text"> "We&#8217;re still here&#8230;"</span></a>]]></description>
				<content:encoded><![CDATA[<p>Some of you have been kind enough to ask why we haven&#8217;t been publishing for a few months. Thank you for your concern.</p>
<p>We&#8217;ve been busy, but be patient as you&#8217;ll soon be seeing us post articles again&#8230;</p>
<p>And we&#8217;ve got some big plans for the future, including books, online courses, and video tutorials, just to name a few.</p>
<p>Stay tuned. Thanks!</p>
]]></content:encoded>
			</item>
		<item>
		<title>Using Xcode 10 Instrument&#8217;s Time Profiler template to optimize Swift 4.2 code</title>
		<link>https://iosbrain.com/blog/2018/11/24/using-xcode-instruments-time-profiler-template-to-optimize-swift-code/</link>
		<pubDate>Sat, 24 Nov 2018 14:46:38 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3179</guid>
		<description><![CDATA[My original article &#8212; &#8220;How to Use Xcode Instrument to Optimize Your Swift Code&#8221; &#8212; was published on appcoda.com. I still run across curmudgeons who flat out reject techniques like object-oriented programming (especially inheritance and polymorphism), protocols and protocol-oriented programming (especially composition), generics, and closures. On a conscious level, the curmudgeons usually reject these technique &#8230; <a href="https://iosbrain.com/blog/2018/11/24/using-xcode-instruments-time-profiler-template-to-optimize-swift-code/" class="more-link">Continue reading<span class="screen-reader-text"> "Using Xcode 10 Instrument&#8217;s Time Profiler template to optimize Swift 4.2 code"</span></a>]]></description>
				<content:encoded><![CDATA[<p><em>My original article &#8212; <a href="https://www.appcoda.com/xcode-instrument/">&#8220;How to Use Xcode Instrument to Optimize Your Swift Code&#8221;</a> &#8212; was published on appcoda.com.</em></p>
<p>I still run across curmudgeons who flat out reject techniques like object-oriented programming (especially inheritance and polymorphism), protocols and protocol-oriented programming (especially composition), generics, and closures. On a conscious level, the curmudgeons usually reject these technique because of their supposed &#8220;massive&#8221; performance cost. On a subconscious level, the curmudgeons don&#8217;t understand these technologies. So do we give up all hope or do we accept the fact that compiler designers have come up with brilliant optimizations that ameliorate the use of such high-level technologies? We believe in Swift&#8217;s compiler designers. Do we realize that there are great tools like Xcode Instruments that help us find awkward implementations of these techniques and give us the opportunity to come up with our own optimizations? Yes.</p>
<p><span id="more-3179"></span></p>

<p>There are costs to these high-level features, but I would argue that in most cases, language compiler optimizations, operating systems enhancements, and faster hardware (like solid state drives and multi-core processors), make up for the costs. Sure, once in a while you&#8217;ll have a use case where advanced code features don&#8217;t pay off, i.e., code is badly written or not used for the intended purpose.</p>
<p>Most of the time, these advanced features save software development boutiques enormous amounts of time and resources. Advanced language features usually let us do more by writing less and very expressive code. Time is saved because team members can easily read each other&#8217;s semantically clear code. Since the code is readable and logically organized, it can be extended, reused, debugged, and maintained easily.</p>
<p>But by goodness, nobody&#8217;s perfect, not even me ;-). Software keeps getting more and more complex. Users keep demanding more, better, and faster features. Problems will occur. Some apps are so slow that people just delete them.</p>
<p>Do we find out why our apps are so slow by using just <code>print</code> statements and breakpoints? I hope not, but I&#8217;ve seen more than a fair share of Stone Age &#8220;optimization&#8221; techniques. No. We turn to the darn good tools that <em>already</em> come bundled <em>free</em> with Xcode.</p>
<h4>Using Instruments to identify performance problems</h4>
<p>The Xcode Instruments&#8217; <em>Time Profiler</em> template is the best template to start with when looking for app performance problems and/or determining how to improve performance. According to Apple, the <em>Time Profiler</em> template &#8220;Performs low-overhead time-based sampling of processes running on the system&#8217;s CPUs.&#8221; </p>
<p>We&#8217;re going to use the <em>Time Profiler</em> to analyze the performance of my sample app&#8217;s code. Please download it from <a href="https://github.com/iosbrain/Optimizing-Swift-Code">GitHub</a>. In simplest of terms, <em>Time Profiler</em> collects information about your app while it&#8217;s running, determines you how long each of your functions takes to run, and also figures out the percentage of CPU cycles each of your functions is using. It gathers the same data about iOS SDK functions. The percentage of CPU cycles from 0% to 100% at each sample point is shown over time on a graph called the &#8220;timeline&#8221; or &#8220;track.&#8221; There are multiple tracks. The top track aggregates all the data from all individual thread and CPU core tracks. The <em>Time Profiler</em> is a very powerful tool as it shows your app&#8217;s performance in real time, thus reflecting surges or lulls in CPU usage. We&#8217;ll walk through an example.</p>
<h5>Your profiling environment</h5>
<p>Before we begin, realize that, when profiling your code, especially when comparing two different approaches to the same problem, <strong>it&#8217;s imperative that you compare apples and apples, not apples and bananas</strong>. In other words, if you&#8217;re profiling an algorithm and trying to optimize it, you want to <strong>use the same device (or simulated device) with the same configuration</strong>. </p>
<p>When I compared the performance of functions <code>showEmployee()</code> and <code>show()</code> from my sample app in the demo below, I ran and profiled each method on the <strong>same iPhone 8, with the same configuration</strong>. When preparing my iPhone 8 for profiling, I first shut down all running apps. Since the code I was studying didn&#8217;t involve any type of connectivity, I shut down WiFi, Bluetooth, and cellular. Of course, if you&#8217;re profiling networking code, like communications with a REST API, you&#8217;ll need to have WiFi or cellular.</p>
<p>The key takeaway here is that <strong>you want to minimize, preferably eliminate, the number of (random) variables that may skew <em>Time Profiler</em> analysis and results</strong>. Imagine if you&#8217;re profiling an algorithm and your iPhone starts up <a href="https://www.imore.com/how-to-manage-background-app-refresh-iphone-ipad"><em>Background App Refresh</em></a>&#8230; Your analysis may be tainted &#8212; artificially skewed so that you believe your algorithm is slower that it really should be. Imagine if you profile one algorithm when nothing is running in the background on your iPhone, profile a similar algorithm while your iPhone performs a background refresh, and then compare the two results (data sets). Is this a meaningful comparison?</p>
<h5>Using Instruments&#8217; <em>Time Profiler</em> template</h5>
<p>Let&#8217;s walk through the profiling of my &#8220;Optimizing Swift Code&#8221; <a href="https://github.com/iosbrain/Optimizing-Swift-Code">sample project</a>. Open the project in Xcode. Click and hold the <em>Build and then run the current scheme</em> button until you see the down arrow. Click the down arrow and then select the <em>Profile</em> option from the context menu, like so:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/1-Start-Profile.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/1-Start-Profile.gif" /></a></center></p>
<p>The <em>Choose a profiling template for:</em> dialog will open. Select the <em>Time Profiler</em> template and click the <em>Choose</em> button:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template.png" alt="" width="1548" height="878" class="aligncenter size-auto wp-image-3185" srcset="https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template.png 1548w, https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template-300x170.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template-768x436.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template-1024x581.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/2-Choose-Template-1200x681.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>The <em>Time Profiler</em> template window will open, ready to sample and render performance data of my &#8220;Optimizing Swift Code&#8221; app. I&#8217;ll refer to the following image as the &#8220;map:&#8221;</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview.png" alt="" width="1810" height="1186" class="aligncenter size-auto wp-image-3186" srcset="https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview.png 1810w, https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview-300x197.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview-768x503.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview-1024x671.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/3-Time-Profiler-Overview-1200x786.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>I&#8217;ve numbered my annotations to correspond with the general sequence of the workflow you use to analyze app performance. I&#8217;ll also refer to these annotations in the following discussion.</p>
<p>To begin profiling, press the record toggle button &#8212; what I call the &#8220;1 &#8211; Start/Stop&#8221; (map) button. Watch, and be patient: </p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/4-Start-Recording.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/4-Start-Recording.gif" /></a></center></p>
<p>When you feel you&#8217;ve sampled enough data, press the &#8220;2 &#8211; Pause&#8221; button or &#8220;1 &#8211; Start/Stop&#8221; toggle (see map). Now it&#8217;s time to examine the profile (sample data collected). Since I&#8217;m running code in the background via <a href="https://iosbrain.com/blog/2018/03/07/concurrency-in-ios-serial-and-concurrent-queues-in-grand-central-dispatch-gcd-with-swift-4/">GCD</a>, I can scroll down to see activity per thread and per core:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/5-Scroll-Profile.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/5-Scroll-Profile.gif" /></a></center></p>
<h5>Analyzing your profile</h5>
<p>Now it&#8217;s time to analyze the recorded profile data. You generally start by clicking into an area of activity on the track/timeline or by highlighting a &#8220;slice&#8221; of the timeline. Remember that you can look at not just the top/aggregate track, but can inspect each thread or core:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/6-Select-Track.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/6-Select-Track.gif" /></a></center></p>
<p>When you click on a single time/data sample or highlight a slice, the corresponding code executing at that time of that selection is shown in what I annotated on my map as the &#8220;4 &#8211; Heaviest Stack Trace,&#8221; &#8220;5.1 &#8211; Stack trace of method names (tree),&#8221; and &#8220;5.2 &#8211; Measures of CPU used.&#8221; You all should know that functions are pushed on and popped off the stack, that functions calling other functions builds a stack trace, and that &#8220;Heaviest Stack Trace&#8221; means high CPU usage (cycles).</p>
<div style="background-color:blue; color:white; padding:10px 10px 10px 10px;">If you&#8217;ve found that there&#8217;s some bottleneck in your app, but you don&#8217;t know where exactly it resides in your code, look for: 1) functions in the &#8220;Heaviest Stack Trace&#8221; pane, and/or, 2) thick, high, and blue activity on the top track, or possibly in thread and core tracks.</div>
<p></p>
<p>I&#8217;m interested in two regions on the timeline. Why? because they show non-trivial CPU activity:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest.png" alt="" width="610" height="230" class="aligncenter size-auto wp-image-3187" srcset="https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest.png 610w, https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest-300x113.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>After I&#8217;ve selected a slice of the timeline, here &#8220;Region 1,&#8221; I first look at the &#8220;4 &#8211; Heaviest Stack Trace&#8221; pane (see map) for method names I recognize with a person icon next to them. The person icon indicates my code; other icons represent iOS calls. The &#8220;4 &#8211; Heaviest Stack Trace&#8221; pane shows me code with high CPU usage. </p>
<p>In <em>this case</em>, I also expected to see certain functions at startup; code that I wrote. I know my own code. I clicked on one of my method names in &#8220;4 &#8211; Heaviest Stack Trace&#8221; so that its stack trace and symbols (function/class/struct names) would be shown in the &#8220;5.1 &#8211; Stack trace of method names (tree)&#8221; and &#8220;5.2 &#8211; Measures of CPU used&#8221; pane (see map):</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/createEmployees.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/createEmployees.png" alt="" width="2572" height="858" class="aligncenter size-auto wp-image-3188" srcset="https://iosbrain.com/wp-content/uploads/2018/11/createEmployees.png 2572w, https://iosbrain.com/wp-content/uploads/2018/11/createEmployees-300x100.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/createEmployees-768x256.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/createEmployees-1024x342.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/createEmployees-1200x400.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Notice all the detail. And notice that I can expand a symbol (function) name to see everything being called by it. If you go into my &#8220;Optimizing Swift Code&#8221; project, you can see how the <code>Organization.createEmployees()</code> method is called at app startup. Look in project file <code>Organization.swift</code> and you&#8217;ll find this code:</p>
<p></p><pre class="crayon-plain-tag">import Foundation

class Organization {
    
    var employees: [Employee] = []
    
    func createEmployees() {
        
        for count in 1...count {
            
            let employeeID = &quot;employee&quot; + String(count)
            let age = Int(arc4random_uniform(47)) + 18
            
            let employee = Employee(firstName: &quot;first&quot;+String(count), lastName: &quot;last&quot;+String(count), age: age, streetAddress: String(count)+&quot; Main St&quot;, zip: &quot;90210&quot;, employeeID: employeeID)
            
            employees.append(employee)
            
            print(&quot;Employee \(count) created.&quot;)
            
        } // end while
                
    } // end func createEmployees()
    
} // end class Organization</pre><p></p>
<p><em>But</em>&#8230; I don&#8217;t have to switch to Xcode to look at my code. </p>
<p>If I double-click on the symbol <code>Organization.createEmployees()</code> in the &#8220;5.1 &#8211; Stack trace of method names (tree)&#8221; and &#8220;5.2 &#8211; Measures of CPU used&#8221; pane, I jump right to source code:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/JumpToSource.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/JumpToSource.gif" /></a></center></p>
<p>You see that Instruments provides annotations (metrics) on performance (like the yellow arrow marked &#8220;47x&#8221;), but suppose you want <em>serious detail</em>, like assembly code. Click on the <em>Show side-by-side source/disassembly view</em> button:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/SideBySide.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/SideBySide.gif" /></a></center></p>
<p>Look at all that information. You can even see <a href="https://iosbrain.com/blog/2018/06/07/swift-4-memory-management-via-arc-for-reference-types-classes/">ARC memory management</a> in action, like retain and release statements. Note that ARC has overhead, so when using classes (reference types), you may have to carefully architect your code &#8212; and possibly optimize it. </p>
<p>Now that you have an idea of how the Instruments&#8217; <em>Time Profiler</em> template works, let&#8217;s look at optimizing some Swift code. </p>

<h4>Optimizing Swift code</h4>
<p>Those busy Swift compiler engineers have done a great job of making Swift fast and light-weight. Back in Swift 2.0, there were more opportunities for <em>developers using the language</em> to optimize their code. With the release of Swift 4.2, the compiler is pretty darn optimized &#8212; but that doesn&#8217;t prevent people from writing bad code. Still, developers need to legitimately optimize code, especially code in which there are complex relationships, mountains of data, and/or extensive calculations. </p>
<h5>Dynamic dispatch</h5>
<p>Let&#8217;s look at an example involving dynamic dispatch. I urge you to pause at some point while reading this article to take a look at an excellent Apple Developer blog post entitled <a href="https://developer.apple.com/swift/blog/?id=27">&#8220;Increasing Performance by Reducing Dynamic Dispatch&#8221;</a>. You should understand dynamic dispatch by now, even the Swifties, but especially if you used to develop in Objective-C.</p>
<p>While my sample code is not Earth-shatteringly innovative, it&#8217;s not supposed to be. I&#8217;m using a simple example so you can understand the language concepts and optimization tools.</p>
<p>Remember &#8220;Region 2&#8221; in my <em>Time Profiler</em> trace? Here&#8217;s a reminder:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest-1.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest-1.png" alt="" width="610" height="230" class="aligncenter size-auto wp-image-3189" srcset="https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest-1.png 610w, https://iosbrain.com/wp-content/uploads/2018/11/RegionsOfInterest-1-300x113.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>Let&#8217;s look at what Instruments showed me when I selected a slice of this part of the timeline:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped.png" alt="" width="2512" height="954" class="aligncenter size-auto wp-image-3190" srcset="https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped.png 2512w, https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped-300x114.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped-768x292.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped-1024x389.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/startButtonTapped-1200x456.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Hmmm&#8230; I see <code>ViewController.startButtonTapped(_:)</code>, which is close, but I&#8217;m not seeing what I&#8217;m interested in. (That&#8217;s because this is a simple example, I&#8217;m running code in the background using <a href="https://iosbrain.com/blog/2018/03/07/concurrency-in-ios-serial-and-concurrent-queues-in-grand-central-dispatch-gcd-with-swift-4/">GCD</a>, and therefore iOS is using as many threads/cores as necessary to keep my app responsive.) </p>
<p>I&#8217;m comparing the performance of two methods, <code>showEmployee()</code> and <code>show()</code>. See file <code>ViewController.swift</code> in my &#8220;Optimizing Swift Code&#8221; sample project:</p>
<p></p><pre class="crayon-plain-tag">@IBAction func startButtonTapped(_ sender: Any) {
        
        while true {
            
            DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
                
                for count in 0...count-1 { // 0...999999
                    
                        //let employeeInfo = self.organization.employees[count].showEmployee()
                        let employeeInfo = self.organization.employees[count].show()
                    
                        DispatchQueue.main.async {

                            self.newEmployeesTextView.text += employeeInfo
                            print(&quot;\(employeeInfo)\n&quot;)
                            
                        }
                    
                } // end for count in 0...count-1
                
            } // end DispatchQueue.global
            
        } // end while true

    } // end func startButtonTapped</pre><p></p>
<p>Remember &#8220;6 &#8211; Find symbols&#8221; in my map? I ran multiple profiling sessions, several to investigate <code>showEmployee()</code> and several for <code>show()</code>. Hey, call me a stickler for details, but I don&#8217;t trust one data sample. I&#8217;ve got two math minors with an emphasis on statistics, so yes, I profiled multiple times to make sure my claims were substantiated. I&#8217;ll present two representative samples from my research (and yes, I switched out of dark mode because my eyes were getting tired).</p>
<p>Here&#8217;s what I found out about the performance of <code>Employee.show()</code>:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/show-Core2.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/show-Core2.png" alt="" width="2524" height="822" class="aligncenter size-auto wp-image-3191" srcset="https://iosbrain.com/wp-content/uploads/2018/11/show-Core2.png 2524w, https://iosbrain.com/wp-content/uploads/2018/11/show-Core2-300x98.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/show-Core2-768x250.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/show-Core2-1024x333.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/show-Core2-1200x391.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Here&#8217;s what I found out about the performance of <code>Employee.showEmployee()</code>:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2.png" alt="" width="2524" height="824" class="aligncenter size-auto wp-image-3192" srcset="https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2.png 2524w, https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2-300x98.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2-768x251.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2-1024x334.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/showEmployee-Core2-1200x392.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>What I found was that <code>Employee.showEmployee()</code> is conservatively about 2.5 times faster than <code>Employee.show()</code>. Yes, I know&#8230; Is saving less than a millisecond really an optimization? In this app, no. If you&#8217;re working on some app that repeats a call millions of times, maybe optimization by taking out dynamic dispatch would be worth your effort.</p>

<p>So why is <code>Employee.showEmployee()</code> faster? Let&#8217;s look at the code. First, look in file <code>People.swift</code>:</p>
<p></p><pre class="crayon-plain-tag">import Foundation

class Person {
    
    /*
     final var firstName: String
     final var lastName: String
     final var age: Int
     final var streetAddress: String
     final var zip: String
    */
    var firstName: String
    var lastName: String
    var age: Int
    var streetAddress: String
    var zip: String
    
    init(firstName: String,
         lastName: String,
         age: Int,
         streetAddress: String,
         zip: String) {
        
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
        self.streetAddress = streetAddress
        self.zip = zip
        
    }
    
    func show() -&gt; String {
        let line = &quot;&quot;&quot;
        First name: \(firstName)
        Last name: \(lastName)
        Age: \(age)
        Street Address: \(streetAddress)
        Zip Code: \(zip)
        &quot;&quot;&quot;
        
        return line
    }
    
} // end class Person</pre><p></p>
<p>Notice method <code>show()</code> above. It is overriden in file <code>Employees.swift</code>, show here:</p>
<p></p><pre class="crayon-plain-tag">import Foundation

class Employee: Person {
    
    var employeeID: String
    var retirementAge: Int = 60
    
    init(firstName: String,
         lastName: String,
         age: Int,
         streetAddress: String,
         zip: String,
         employeeID: String) {
        
        self.employeeID = employeeID
        super.init(firstName: firstName, lastName: lastName, age: age, streetAddress: streetAddress, zip: zip)
    }
    
    func isRetirementReady() -&gt; Bool {
        if age &gt;= retirementAge {
            return true
        }
        else {
            return false
        }
    }
    
    override func show() -&gt; String {
        var line = super.show()
        line += &quot;Employee ID: \(employeeID)\n&quot;
        line += &quot;Retirement Age: \(retirementAge)&quot;
        return line
    }
    
    final func showEmployee() -&gt; String {
        let line = &quot;&quot;&quot;
        First name: \(firstName)
        Last name: \(lastName)
        Age: \(age)
        Street Address: \(streetAddress)
        Zip Code: \(zip)
        Employee ID: \(employeeID)
        Zip Code: \(zip)
        &quot;&quot;&quot;
        
        return line

    }
    
}  // end class Employee</pre><p></p>
<p>Notice that I&#8217;ve indulged in some overkill here to make a point. Not only have I completely rewritten the <code>show()</code> methods in the form of <code>showEmployee()</code>, but I&#8217;ve marked <code>showEmployee()</code> as <code>final</code> which <a href="https://developer.apple.com/swift/blog/?id=27">&#8220;allows the compiler to safely elide dynamic dispatch indirection.&#8221;</a></p>

<h5>Whole Module Optimization</h5>
<p>Remember earlier that I said that the Swift compiler is getting really smart? <strong>As I understand it, the optimizations that I&#8217;ll discuss from here onwards are already turned on by default. Even so, I believe it&#8217;s instructive and helpful for you to understand what the Swift compiler is doing with your code.</strong></p>
<p>Look at the default Xcode 10 <em>Build Settings</em> under <em>Swift Compiler &#8211; Code Generation</em>:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings.png" alt="" width="1220" height="560" class="aligncenter size-auto wp-image-3193" srcset="https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings.png 1220w, https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings-300x138.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings-768x353.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings-1024x470.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/CompilerBuildSettings-1200x551.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Notice that <em>Compilation Mode</em> is set to <em>Incremental</em> for <em>Debug</em> and that <em>Optimization Level</em> is set to <em>No Optimization</em> for <em>Debug</em>. These settings make for fast build times. It should be obvious why performing no optimizations is faster. Incremental building means only recompiling files that have changed since the last build, accounting for updated dependencies. Finally, the Swift compiler <a href="https://developer.apple.com/videos/play/wwdc2015-409/?time=402">&#8220;can compile many files in parallel on multiple cores in your machine.&#8221;</a></p>
<p><em>Compilation Mode</em> is set to <em>Whole Module</em> for <em>Release</em>. <em>Optimization Level</em> is set to <em>Optimize for Speed</em> for <em>Release</em>. That makes for fast apps that you publicly distribute.</p>
<p>I made it a point to break my code into as many logical modules as possible in my &#8220;Optimizing Swift Code&#8221; sample project:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/SeparateFiles.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/SeparateFiles.png" alt="" width="616" height="612" class="aligncenter size-auto wp-image-3194" srcset="https://iosbrain.com/wp-content/uploads/2018/11/SeparateFiles.png 616w, https://iosbrain.com/wp-content/uploads/2018/11/SeparateFiles-150x150.png 150w, https://iosbrain.com/wp-content/uploads/2018/11/SeparateFiles-300x298.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>I profiling of this project and many other projects for customers, I&#8217;ve seen <a href="https://developer.apple.com/swift/blog/?id=27">Whole Module Optimization</a> speed up my <em>public releases</em>. In fact, the changes I made to enhance performance in the previous section were done in <em>Debug</em>. When I removed the <em>final</em> keyword in <em>Release</em>, my profiling seemed to confirm that the Swift compiler inferred it as an optimization.</p>
<p><strong>NOTE:</strong> You should still consider applying the <code>final</code> keyword to both class properties and methods when performance is critical. You can always use Instruments to determine if your &#8220;optimizations&#8221; are indeed optimizations.</p>
<p>There&#8217;s one language feature where Whole Module Optimization has an additive effective on another one. We&#8217;ll discuss this in the next section.</p>
<h5>Generics</h5>
<p>Think about a generic function like the one included with my sample app. You&#8217;ll find it in <code>Generics.swift</code>:</p>
<p></p><pre class="crayon-plain-tag">func exists&lt;T: Equatable&gt;(item:T, inArray:[T]) -&gt; Bool {

    var index:Int = 0
    var found = false
    
    while (index &lt; inArray.count &amp;&amp; found == false)
    {
        if item == inArray[index]
        {
            found = true
        }
        else
        {
            index = index + 1
        }
    }
    
    if found
    {
        return true
    }
    else
    {
        return false
    }
    
} // func exists</pre><p></p>
<p>The compiler looks at this function and realizes that <a href="https://developer.apple.com/videos/play/wwdc2015-409/?time=1076">&#8220;it must be able to handle any type T&#8221;</a> that conforms to <code>Equatable</code>. Think about the complexities involved in generics. You&#8217;re writing code that ideally should be able to handle <em>any</em> type.</p>
<p>Swift already supports an optimization called <a href="https://developer.apple.com/videos/play/wwdc2015-409/?time=1086"><em>generic specialization</em></a>. It turns out that Whole Module Optimization <a href="https://developer.apple.com/videos/play/wwdc2015-409/?time=1207"><em>also</em> optimizes generics</a>. Why?</p>
<p>I know this is a relatively old video, but you should <a href="https://developer.apple.com/videos/play/wwdc2015/409/">watch the whole thing</a> to find out. </p>
<p>I proved to myself that Whole Module Optimization sped up calls in my sample project to my <code>exists</code> generic function. I profiled the project with Whole Module Optimization on and then profiled it with the setting turned off. This is how you learn about powerful tools.</p>
<h5>Simple optimizations</h5>
<p>Say you&#8217;re designing a data-intensive app and you need to pick the fastest data structures to use in your code. Go to a site like <a href="https://www.bigocheatsheet.com">this one</a>, look at the Big-O complexity chart, review the data structures, and look at the time requirements of their operations. Then pick the data structures that balance your requirements with speed.</p>
<h5>ARC memory management</h5>
<p>ARC memory management management has overhead, but I&#8217;ve read multiple scientific and commercial journal articles that <strong>do not</strong> conclude that reference types and reference semantics are slower than value types and value semantics.</p>
<p>In my own work, I&#8217;ve never been able to prove that, in general, one was faster than the other, as long as sound best practices were used in development across the board.</p>
<p>While writing this article, I actually coded an entire Swift project that performs the same task by <strong>1)</strong> entirely using reference types and semantics and <strong>2)</strong> entirely using value types and semantics. After multiple sessions with the <em>Time Profiler</em>, I couldn&#8217;t find any significant difference between the two.</p>
<p>Nevertheless, I&#8217;ve seen scenarios in which ARC <em>did</em> degrade performance when misused, for example, creating too many references, or using large numbers of reference types when value types could be used instead. One has to strike a balance. For example, if we replace a bunch of references with values, what happens if we have to constantly change and copy those values?</p>
<h4>Conclusion</h4>
<p>I encourage you to play with with my project&#8217;s Swift code and its <em>Swift Compiler &#8211; Code Generation</em> settings &#8212; and then practice with the <em>Time Profiler</em> to analyze and possibly optimize the code. If not my code, use your own code. But practice, practice, practice with the <em>Time Profiler</em>.</p>
<p>You need to be able to <em>find</em> bottlenecks in your code and then be able to <em>optimize</em> them. You&#8217;ll feel a bit overwhelmed if you&#8217;ve never used Instruments before. I&#8217;ve been using its templates for years and still find it a bit overwhelming. But <em>not</em> using Instruments is a travesty. It offers so many ways to solve problems more easily than using brute force.</p>
<p>By brute force, I mean only fixing bugs and making optimizations by using <code>print</code> statements and maybe some breakpoints.</p>
<p>Please don&#8217;t give up on tools like object-oriented programming, protocols and protocol-oriented programming, generics, and closures just because you&#8217;ve had a few bad experiences or because your heard they have &#8220;high overhead.&#8221; When used right, these tools can actually reduce the amount of code you write and <em>speed up</em> your apps. They can certainly help with code maintainability, readability, and reusability.</p>
<p>You have excellent tools with Xcode. <strong>Use them.</strong> </p>

]]></content:encoded>
			</item>
		<item>
		<title>Dividing and conquering your Xcode projects with targets</title>
		<link>https://iosbrain.com/blog/2018/11/10/dividing-and-conquering-your-xcode-projects-with-targets/</link>
		<pubDate>Sat, 10 Nov 2018 17:08:55 +0000</pubDate>
		<dc:creator><![CDATA[Andrew Jaffee]]></dc:creator>
				<category><![CDATA[Code Reuse]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Developer Tools]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">https://iosbrain.com/?p=3144</guid>
		<description><![CDATA[My original article &#8212; &#8220;Dividing and Conquering Your Xcode Projects with Targets&#8221; &#8212; was published on appcoda.com. In this tutorial, I&#8217;ll show you how to leverage Xcode targets to control the massive complexity involved in building iOS (and macOS, watchOS, and tvOS) apps. A lot of time can be saved when developers realize that not &#8230; <a href="https://iosbrain.com/blog/2018/11/10/dividing-and-conquering-your-xcode-projects-with-targets/" class="more-link">Continue reading<span class="screen-reader-text"> "Dividing and conquering your Xcode projects with targets"</span></a>]]></description>
				<content:encoded><![CDATA[<p><em>My original article &#8212; <a href="https://www.appcoda.com/xcode-targets/">&#8220;Dividing and Conquering Your Xcode Projects with Targets&#8221;</a> &#8212; was published on appcoda.com.</em></p>
<p>In this tutorial, I&#8217;ll show you how to leverage Xcode <em>targets</em> to control the massive complexity involved in building iOS (and macOS, watchOS, and tvOS) apps. A lot of time can be saved when developers realize that not everything they&#8217;re required to do has to be done by writing software language code, like Swift. Integrated development environments (IDEs) like Xcode offer very powerful tools, like targets, that allow developers to decouple nitty-gritty tasks that used to be done in code (or manually) out into project configuration settings. I&#8217;ve found that, because of the sheer number of project settings, developers often take one look at say, Xcode&#8217;s long, long list of <em>Build Settings</em>, and want to curl up and pass out. When finished reading this tutorial, you&#8217;ll see that you can <em>neatly</em> organize code into <em>one</em> project that&#8217;s capable of producing binaries for iOS, macOS, watchOS, and tvOS.</p>
<p><span id="more-3144"></span></p>

<p>If developers take the time to harness the power of Xcode&#8217;s features, they can spend most of their time doing what they should be doing: designing, writing, and organizing their code using tools like architectural design patterns (MVVM), tactical design patterns (factory method, facade, adapter), object-oriented techniques, protocol-oriented techniques, generics, delegation &#8212; all good, solid <em>development</em> concepts.</p>
<p>Developers should always be on the lookout for opportunities to <em>logically</em> organize and group related code and, conversely, <em>logically</em> separate unrelated code. Xcode targets can let you take related code, put it into one project, yet simultaneously target that code at each of Apple&#8217;s platforms: iOS, macOS, watchOS, and tvOS.</p>
<p>When it comes to the more mundane tasks, like changing an app&#8217;s name, version number, help bundle, app icon, or copyright text, programmers should be able to turn to Xcode&#8217;s tools. Developers <em>shouldn&#8217;t</em> be dealing with such tasks using hacks, pyramid-of-doom <code>if</code> statements, and hardcoding values and/or logic. Let&#8217;s decouple our coding from these usually boring but necessary responsibilities. Targets help here.</p>
<p>The protocol I&#8217;ll discuss herein is a mixture of using Xcode &#8220;targets&#8221; and &#8220;schemes.&#8221; I&#8217;m sure all sorts of people have all sorts of ways of doing things differently, but I&#8217;ve found that this works best for me. I&#8217;m not claiming this is the <em>only</em> way to do things.</p>
<p>I know I could&#8217;ve (possibly) made things even more generalized by using workspaces, but this is a tutorial. You need to grasp the basics of Xcode&#8217;s targets and schemes before building a better, newer, grander solution. There&#8217;s such a thing as being <em>too generalized</em> to be useful, too&#8230;</p>
<h4> Introduction</h4>
<p>When you create a new project in Xcode, <a href="https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/WorkingwithTargets.html#//apple_ref/doc/uid/TP40010215-CH32-SW1">one single target</a> is created for you. For example, I created an Xcode project for iOS, based on the <em>Single View App</em> template, and named it &#8220;Xcode Targets.&#8221; You can download it from <a href="https://github.com/iosbrain/Xcode-Targets">GitHub</a>. Let&#8217;s get a quick overview of how project configuration settings/options are stored.</p>
<p>According to the <a href="https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/CreatingProjects.html#//apple_ref/doc/uid/TP40010215-CH31-SW1">Xcode docs</a>, &#8220;By selecting the project name in the project navigator, you open the project editor.&#8221; Let&#8217;s do that and here&#8217;s what we&#8217;ll see:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/XcodeOverview.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/XcodeOverview-1024x458.png" alt="" width="840" height="376" class="aligncenter size-auto wp-image-3146" srcset="https://iosbrain.com/wp-content/uploads/2018/11/XcodeOverview-1024x458.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/XcodeOverview-300x134.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/XcodeOverview-768x344.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/XcodeOverview.png 1140w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>A we forge ahead through this tutorial, keep two concepts from the Xcode docs in mind. First, <a href="https://web.archive.org/web/20160315051113/https://developer.apple.com/library/ios/recipes/xcode_help-project_editor/Articles/BasingBuildConfigurationsonConfigurationFiles.html">consider that</a>:</p>
<p><em>Build settings defined at the target level override any values assigned to those build settings at the project level. Therefore, target-level configurations take precedence over any project-level configurations.</em></p>
<p>Second, <a href="https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/WorkingwithTargets.html#//apple_ref/doc/uid/TP40010215-CH32-SW1">recognize that</a>:</p>
<p><em>A target contains instructions&#8211;in the form of build settings and build phases&#8211;for building a product. A target inherits the project&#8217;s build settings. Although most developers seldom need to change these settings, you can override any of the project&#8217;s build settings by specifying different settings at the target level.</em></p>
<p>You&#8217;ll see that I generally disagree with the statement, &#8220;Although most developers seldom need to change these settings.&#8221; We&#8217;ll be changing settings. That&#8217;s a major concern in this tutorial.</p>
<h5>A note about &#8220;configurations&#8221;</h5>
<p>Apple <a href="https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/CreatingProjects.html#//apple_ref/doc/uid/TP40010215-CH31-SW1">notes that</a>: </p>
<p><em>When you create a project, Xcode provides two standard project-level build configurations: debug and release. &#8230; These two build configurations are probably sufficient for your product development needs. Most developers never need to change the values of the vast majority of build settings.</em></p>
<p>I would add that you can change debug and release settings in each of your <em>targets</em>, not just at the project level. Perhaps because of the length of time that I&#8217;ve developed Apple apps, and the complexity of most of the apps with which I&#8217;ve worked, I find myself and coworkers often needing to change the values of <em>Build Settings</em>. I also find it very confusing and difficult to manage when almost <em>every</em> build setting at the project and target level have a <code>Debug</code> and <code>Release</code> option. See the following image &#8212; and remember that these are <em>just a few</em> of the available options:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/DebugReleaseAdInfinitum.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/DebugReleaseAdInfinitum.png" alt="" width="370" height="986" class="aligncenter size-auto wp-image-3150" srcset="https://iosbrain.com/wp-content/uploads/2018/11/DebugReleaseAdInfinitum.png 370w, https://iosbrain.com/wp-content/uploads/2018/11/DebugReleaseAdInfinitum-113x300.png 113w" sizes="(max-width: 370px) 85vw, 370px" /></a></p>
<p>So when faced with debug/release, debug/release, debug/release, debug/release&#8230; I see the opportunity for developers to start unwittingly &#8212; and easily &#8212; commingling debug and release options, or just plain setting conflicting options. As we&#8217;ll soon see, I&#8217;d rather keep all my release settings in one target and my debug settings in another.</p>
<h4> Separating release settings from debug settings</h4>
<p>Once I&#8217;ve created a project as described above, the first thing I do is to rename the default target as shown here:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/RenameDefaultToRelease.gif" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/RenameDefaultToRelease.gif" alt="" width="238" height="58" class="aligncenter size-auto wp-image-3151" /></a></p>
<p>Let me just briefly mention <em>schemes</em>. There are a variety of ways to approach organizing project settings, and I want to keep this tutorial simple. Let me just quote the <a href="https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/BuildingYourApp.html">Xcode documentation</a> again:</p>
<p><em>When you open an existing project (or create a new one), Xcode automatically creates a scheme for each target. The default scheme is named after your project&#8230;</em></p>
<p>You can read up on schemes using the links I&#8217;ve provided. Since a default scheme was  generated when I created the project, I&#8217;m going to rename it with the same name as I did my default target:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/RenameDefaultScheme.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/RenameDefaultScheme.gif" /></a></center></p>
<p>Notice that I&#8217;ve left the <em>Autocreate schemes</em> checkbox ticked.</p>
<p>Now let&#8217;s set &#8220;Xcode Targets &#8211; Release&#8221; scheme&#8217;s <em>Build Configuration</em> to <code>Release</code> to match it&#8217;s name. Go to the <em>Set the active scheme</em> control, just where we started in the last video, <em>Edit Scheme&#8230;</em>, and change <code>Debug</code> to <code>Release</code> as follows:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/SetRelSchemeToRel.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/SetRelSchemeToRel.gif" /></a></center></p>
<p>Of course, now we want to create a new target (and scheme) for debugging. Here&#8217;s how we create and rename a new target:</p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/DuplicateDebugTarget.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/DuplicateDebugTarget.gif" /></a></center></p>
<p>The <em>Autocreate schemes</em> checkbox had its intended effect, creating a new scheme &#8212; <em>except</em> it didn&#8217;t catch my renaming of my new target to &#8220;Xcode Targets &#8211; Debug.&#8221; <em>Make sure</em> to change the newly auto-created scheme from &#8220;Xcode Targets &#8211; Release copy&#8221; to &#8220;Xcode Targets &#8211; Debug&#8221; just like I showed you up above. <em>Make sure</em> to set &#8220;Xcode Targets &#8211; Debug&#8221; scheme&#8217;s <em>Build Configuration</em> to <code>Debug</code>. You may find that it already is <code>Debug</code>, but check anyway.</p>
<p>To switch between debug and release configurations, all you have to do is switch/set the active scheme. <em>Very importantly</em>, make sure you confine all your <code>Release</code> configurations in <em>Build Settings</em> to the &#8220;Xcode Targets &#8211; Release&#8221; target and confine all your <code>Debug</code> configurations in <em>Build Settings</em> to the &#8220;Xcode Targets &#8211; Debug&#8221; target. We&#8217;ll see how to do this below.</p>
<h5>A note about <code>Info.plist</code></h5>
<p>When you <em>Duplicate</em> (create) a new target, Xcode creates a new <code>Info.plist</code>. It gives it a name you probably don&#8217;t want and puts the file where you probably don&#8217;t want it:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/NewInfoPlistLocation.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/NewInfoPlistLocation.png" alt="" width="598" height="360" class="aligncenter size-auto wp-image-3152" srcset="https://iosbrain.com/wp-content/uploads/2018/11/NewInfoPlistLocation.png 598w, https://iosbrain.com/wp-content/uploads/2018/11/NewInfoPlistLocation-300x181.png 300w" sizes="(max-width: 598px) 85vw, 598px" /></a></p>
<p>I like to use the <code>$(SRCROOT)</code> macro in my Xcode projects to standardize and organize my file locations. To keep things &#8220;Xcodey,&#8221; I set my <em>Build Settings</em> for my &#8220;Xcode Targets &#8211; Release&#8221; target&#8217;s <code>Info.plist</code> like so:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/ReleaseTargetInfoPlist.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/ReleaseTargetInfoPlist.png" alt="" width="1180" height="420" class="aligncenter size-auto wp-image-3153" srcset="https://iosbrain.com/wp-content/uploads/2018/11/ReleaseTargetInfoPlist.png 1180w, https://iosbrain.com/wp-content/uploads/2018/11/ReleaseTargetInfoPlist-300x107.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/ReleaseTargetInfoPlist-768x273.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/ReleaseTargetInfoPlist-1024x364.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>For my &#8220;Xcode Targets &#8211; Debug&#8221; target, I put my <code>Info.plist</code> here:</p>
<p></p><pre class="crayon-plain-tag">$(SRCROOT)/Xcode Targets/Debug/Info-Debug.plist</pre><p></p>
<p>I highly recommend that you clean up your <em>Project Navigator</em> setup after making these changes. (I control-clicked on my &#8220;Xcode Targets&#8221; folder in the <em>Project Navigator</em> and used the <em>Add Files to &#8220;Xcode Targets&#8221;&#8230;</em> context menu command.) Look at the sample project and you&#8217;ll understand.</p>
<h5>Release versus debug dependencies</h5>
<p>I&#8217;ve supported quite a few iOS and macOS Xcode apps that consume C++ libraries. In order to provide optimized production code, I only include release versions of libraries when distributing apps to the public. When developing and debugging, I want debug versions of libraries with all symbols linked into my apps so I can set breakpoints and step through code.</p>

<p>For production, I switch to my &#8220;Xcode Targets &#8211; Release&#8221; target and drag <em>release</em> versions of libraries into <em>Build Phases</em> -> <em>Link Binary With Libraries</em> like this:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/ReleaseLibDrag.gif" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/ReleaseLibDrag.gif" alt="" width="658" height="190" class="aligncenter size-auto wp-image-3154" /></a></p>
<p>For debugging and development:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/DebugLibDrag.gif" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/DebugLibDrag.gif" alt="" width="658" height="190" class="aligncenter size-auto wp-image-3155" /></a></p>
<p>Remember that if I&#8217;m calling code from linked libraries, I&#8217;ll need the paths to the header files (.h, .hpp). I usually specify those in <em>Build Settings</em> -> <em>Search Paths</em> -> <em>User Header Search Paths</em>:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/HeaderSearchPaths.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/HeaderSearchPaths.png" alt="" width="562" height="412" class="aligncenter size-auto wp-image-3156" srcset="https://iosbrain.com/wp-content/uploads/2018/11/HeaderSearchPaths.png 562w, https://iosbrain.com/wp-content/uploads/2018/11/HeaderSearchPaths-300x220.png 300w" sizes="(max-width: 562px) 85vw, 562px" /></a></p>
<p>If I am responsible for the library code and maintain it in Xcode, I can use the same separation of concerns structure outlined in this tutorial in my library projects. We&#8217;ll see an example below.</p>
<p>Suppose I have release and debug versions of <a href="https://iosbrain.com/blog/2018/01/13/building-swift-4-frameworks-and-including-them-in-your-apps-xcode-9/">iOS frameworks</a>. For release, I simply click on my &#8220;Xcode Targets &#8211; Release&#8221; target and drag the release framework version into <em>General</em> -> <em>Embedded Binaries</em>. For debug, I simply click on my &#8220;Xcode Targets &#8211; Debug&#8221; target and similarly drag the debug framework version into my target.  </p>
<p>Release and debug dependencies are cleanly separated using my targets protocol. We&#8217;ll talk more about dependencies later.</p>
<h4>Compilation conditions</h4>
<p>Those of us who used and/or are still using Objective-C are accustomed to leveraging symbols like <code>DEBUG</code> defined in Xcode under <em>Build Settings</em> -> <em>Apple LLVM 9.0 &#8211; Preprocessing</em> -> <em>Preprocessor Macros</em>. If you want similar behavior in Swift, you need to use what Apple calls <a href="https://docs.swift.org/swift-book/ReferenceManual/Statements.html#ID539"><em>conditional compilation</em></a>:</p>
<p><em>A conditional compilation block allows code to be conditionally compiled depending on the value of one or more compilation conditions.</em></p>
<p>You can use any of the symbols listed in <a href="https://docs.swift.org/swift-book/ReferenceManual/Statements.html#ID539">this link</a>, but I&#8217;ll talk about using custom symbols here. Swift still respects <code>DEBUG</code>, but if you want to use it, or the language&#8217;s built-in symbols, or custom symbols, you have to now define them in your <em>Build Settings</em> -> <em>Swift Compiler &#8211; Custom Flags</em> -> <em>Active Compilation Conditions</em>.</p>
<p>Let&#8217;s say I&#8217;m logging (<code>LOG</code>) in release to create an audit trail (i.e., I&#8217;m tracking logins). Here&#8217;s what&#8217;s in my &#8220;Xcode Targets &#8211; Release&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/PreProcRelease.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/PreProcRelease.png" alt="" width="1118" height="372" class="aligncenter size-auto wp-image-3157" srcset="https://iosbrain.com/wp-content/uploads/2018/11/PreProcRelease.png 1118w, https://iosbrain.com/wp-content/uploads/2018/11/PreProcRelease-300x100.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/PreProcRelease-768x256.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/PreProcRelease-1024x341.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Let&#8217;s say I&#8217;m not worried about auditing during development. Here&#8217;s what&#8217;s in my &#8220;Xcode Targets &#8211; Debug&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/PreProcDebug.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/PreProcDebug.png" alt="" width="1118" height="372" class="aligncenter size-auto wp-image-3158" srcset="https://iosbrain.com/wp-content/uploads/2018/11/PreProcDebug.png 1118w, https://iosbrain.com/wp-content/uploads/2018/11/PreProcDebug-300x100.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/PreProcDebug-768x256.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/PreProcDebug-1024x341.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>I&#8217;ve supported quite a few iOS and macOS Xcode projects that consume C++ code that runs on multiple platforms, including Unix/Linux flavors, Microsoft Windows, and macOS. Sometimes things get tricky and, for example, I run into code that will only compile and run on Windows, but not on Mac, and vice versa. I try to minimize such situations, but sometimes things just need to get done. When necessary, I use preprocessor macros or, as Apple now says in Swift, <em>compilation conditions</em>, like <code>WIN</code>, <code>MAC</code>, <code>LOG</code>, and <code>DEBUG</code>.</p>
<p>When calling into my portable C++ code, something like <code>MAC</code> would be defined in both release and debug versions so that I can selectively compile, or <em>not</em> compile, portable or non-portable core code that can only build and run, or <em>not</em> build and run, successfully under macOS (or Windows). Remember that I can use logical operators like <code>!</code> (not) with my compilation conditions.</p>
<p>I generally use <code>DEBUG</code> to report on and sometimes act upon error conditions. I generally use <code>LOG</code> when my code needs an audit trail (like when processing sensitive data).</p>
<p>If, for example, I have to deal with core code specific to Mac, and debugging and logging, I would use the following generalized though runnable <code>ViewController.swift</code> file:</p>
<p></p><pre class="crayon-plain-tag">class ViewController: UIViewController {
    
    var loginAttempts: Int = 0
    
    @IBAction func loginButtonPressed(&lt;/em&gt; sender: Any) {
        
#if LOG
        print(&quot;Login button pressed&quot;)
        loginAttempts += 1
        if loginAttempts &gt; 3 {
            print(&quot;HACK ATTEMPTED?&quot;)
            // CALL 911!
        }
#endif

    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
#if WIN
        print(&quot;Use Windows code...&quot;)
#elseif MAC
        print(&quot;Use Mac code...&quot;)
#endif
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
        
#if DEBUG
        print(&quot;ViewController::didReceiveMemoryWarning&quot;)
#endif
    }

} // end class ViewController</pre><p></p>
<p>Let&#8217;s say I build and distribute my app using the &#8220;Xcode Targets &#8211; Release&#8221; target. Here&#8217;s the console output from the previous code snippet:</p>
<p></p><pre class="crayon-plain-tag">Use Mac code...
Login button pressed
Login button pressed
Login button pressed
Login button pressed
HACK ATTEMPTED?</pre><p></p>
<p>The main takeaway here is that you can define as many or as few compilation conditions as you like and specify differing combinations of those conditions in different targets. While I generally frown upon conditionally compiling code, there a times when nothing else works in complex, realworld scenarios. I&#8217;m more comfortable with using compilation conditions for situations like turning logging (i.e., <code>print</code> statements) off and on.</p>

<h4> Different app flavors/branding</h4>
<p>What if you&#8217;ve licensed your code to partners/resellers who want their own branding, like custom logos/icons and specific product names, to be displayed by an app? In the iOS App Store, Apple generally frowns on a bunch of identical apps that only differ in their main icons&#8230; At least they say they do ;-). But you definitely can have multiple versions of the same app(s) differing in the sense of up-selling from free to intermediate to advanced features and functionality. Branding or &#8220;flavors&#8221; of iOS apps is much more flexible in an Apple Developer Enterprise Program environment. In macOS development, Apple allows you to build, brand, and distribute apps without going through the Mac App Store, and thus you&#8217;re afforded much more flexibility.</p>
<p>Do differing icons, graphics, text, and tiered features warrant multiple Xcode projects? Generally, no. Why not just use targets? I&#8217;ve supported apps that have 10 different flavors. </p>
<p>To show you how you can leverage targets to handle branding, I created an Xcode project for macOS, based on the <em>Cocoa App</em> template, and named it &#8220;Xcode Manage Config.&#8221; You can download it from <a href="https://github.com/iosbrain/Xcode-Manage-Config">GitHub</a>.</p>
<p>My project shows you how you can abstract out and customize an app&#8217;s <strong>1)</strong> help bundle, <strong>2)</strong> name, <strong>3)</strong> version number, <strong>4)</strong> app icon, and <strong>5)</strong> copyright text, <strong>all without hacking, i.e., without using if statements and hardcoding values.</strong> Reviewing the code and commentary in my sample project&#8217;s <code>ViewController.swift</code> file should give you a good idea of how I abstracted all details for the 5 tasks I just listed out of code and into targets:</p>
<p></p><pre class="crayon-plain-tag">import Cocoa

let reverseDomain = &quot;us.microit.&quot;

class ViewController: NSViewController {
    
    @IBOutlet weak var logoImage: NSImageView!
    @IBOutlet weak var productName: NSTextField!
    @IBOutlet weak var copyright: NSTextField!
    @IBOutlet weak var version: NSTextField!
    
    var helpPath: String = &quot;&quot;
    
    override func viewDidLoad() {
        
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        // Get the product name by stripping out the
        // reverse domain name.
        let bundleIdentifier = Bundle.main.bundleIdentifier?.replacingOccurrences(of: reverseDomain, with: &quot;&quot;)
        
        // Display the product name.
        productName.stringValue = bundleIdentifier!
        
        // Build app icon set name using concatenation.
        let appIconSetName:String = bundleIdentifier! + &quot;AppIcon&quot;
        // Get and display the product logo.
        logoImage.image = NSImage(named: NSImage.Name(rawValue: appIconSetName))
        
        // Get the copyright statement.
        let copyrightString = Bundle.main.object(forInfoDictionaryKey: &quot;NSHumanReadableCopyright&quot;)
        // Display the product copyright.
        copyright.stringValue = copyrightString! as! String
        
        // Get the product version.
        let versionString = Bundle.main.object(forInfoDictionaryKey: &quot;CFBundleShortVersionString&quot;)
        // Display the version.
        version.stringValue = &quot;Version: &quot; + (versionString! as! String)
        
        // Build and save the path to help files.
        helpPath = Bundle.main.path(forResource: &quot;index&quot;, ofType: &quot;html&quot;, inDirectory: bundleIdentifier!)!
        
    } // end func viewDidLoad()
    
    @IBAction func invokeHelp(&lt;/em&gt; sender: Any) {
        // Open help in default browser.
        NSWorkspace.shared.openFile(helpPath)
    }
    
    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

} // end class ViewController</pre><p></p>
<p>Let&#8217;s build and run the code to see how targets can differentiate two licensors of the same software but with different branding. Let&#8217;s build and run the &#8220;Acme &#8211; Release&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/AboutAcme.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/AboutAcme.png" alt="" width="1166" height="738" class="aligncenter size-auto wp-image-3159" srcset="https://iosbrain.com/wp-content/uploads/2018/11/AboutAcme.png 1166w, https://iosbrain.com/wp-content/uploads/2018/11/AboutAcme-300x190.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/AboutAcme-768x486.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/AboutAcme-1024x648.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Now let&#8217;s build and run the &#8220;Emca &#8211; Release&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/AboutEmca.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/AboutEmca.png" alt="" width="1162" height="740" class="aligncenter size-auto wp-image-3160" srcset="https://iosbrain.com/wp-content/uploads/2018/11/AboutEmca.png 1162w, https://iosbrain.com/wp-content/uploads/2018/11/AboutEmca-300x191.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/AboutEmca-768x489.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/AboutEmca-1024x652.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Notice that nothing was hardcoded&#8230; well, except my reverse domain name, and that <strong>hasn&#8217;t changed since 1999</strong>. It could easily be abstracted into a <code>plist</code>. Please forgive my one, minor transgression. Notice that the official app icons for each target are recognized by macOS: </p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/AppIconsDock.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/AppIconsDock.png" alt="" width="250" height="94" class="aligncenter size-auto wp-image-3161" /></a></p>
<p>What if we click on the &#8220;Help&#8221; button in either target&#8217;s app? This is help customized to the &#8220;Acme &#8211; Release&#8221; target, running in Safari:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/AcmeHelp.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/AcmeHelp.png" alt="" width="1020" height="716" class="aligncenter size-auto wp-image-3162" srcset="https://iosbrain.com/wp-content/uploads/2018/11/AcmeHelp.png 1020w, https://iosbrain.com/wp-content/uploads/2018/11/AcmeHelp-300x211.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/AcmeHelp-768x539.png 768w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>The &#8220;Emca &#8211; Release&#8221; target&#8217;s help is differentiated:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/EmcaHelp.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/EmcaHelp.png" alt="" width="1018" height="770" class="aligncenter size-auto wp-image-3163" srcset="https://iosbrain.com/wp-content/uploads/2018/11/EmcaHelp.png 1018w, https://iosbrain.com/wp-content/uploads/2018/11/EmcaHelp-300x227.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/EmcaHelp-768x581.png 768w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p><strong><em>The help bundle</em></strong><br />
A help bundle is often just a directory containing <code>HTML</code> files/resources. I dragged help folders named &#8220;Emca&#8221; and &#8220;Acme&#8221; into the <em>Project Navigator</em>. I was prompted by Xcode both times. I&#8217;ll just show you the prompt for the &#8220;Acme&#8221; folder. Notice I <em>only</em> set the &#8220;Acme&#8221; folder to be a member of the &#8220;Acme &#8211; Release&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/AddAcmeHelp.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/AddAcmeHelp.png" alt="" width="731" height="430" class="aligncenter size-auto wp-image-3164" srcset="https://iosbrain.com/wp-content/uploads/2018/11/AddAcmeHelp.png 731w, https://iosbrain.com/wp-content/uploads/2018/11/AddAcmeHelp-300x176.png 300w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></p>
<p>If you click on the &#8220;Emca&#8221; folder in Xcode&#8217;s <em>Project Navigator</em>, you&#8217;ll see its <em>Target Membership</em> is <strong>only</strong> ticked for the &#8220;Emca &#8211; Release&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/EmcaTargetMember.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/EmcaTargetMember.png" alt="" width="288" height="136" class="aligncenter size-auto wp-image-3165" /></a></p>
<p>I&#8217;ve seen multi-megabyte help bundles, so if you insist on including the actual help resources in your project, make sure you&#8217;re not including stuff that you don&#8217;t need, like don&#8217;t include Acme&#8217;s help in Emca and vice versa. On a side note, believe it or not, I&#8217;ve heard <em>many</em> customers insist that they get the actual help included in-situ in their products.</p>
<p>If you plan building, signing, and creating a signed installer for one or both of the &#8220;Xcode Manage Config&#8221; project&#8217;s targets, you need to take a few extra steps. For one thing, remember to go to <em>Build Phases</em> -> <em>Copy Bundle Resources</em> and add the &#8220;Acme&#8221; folder for copying in the &#8220;Acme &#8211; Release&#8221; target, and similarly add the &#8220;Emca&#8221; folder for copying in the &#8220;Emca &#8211; Release&#8221; target. Again, two products; two different targets.</p>

<p><strong><em>The app name and version number</em></strong><br />
The app name and version number are distinct per target. You set them by selecting the target and then going to <em>General</em> -> <em>Identity</em>. I&#8217;ll just show you how I set the values for the &#8220;Emca &#8211; Release&#8221; target:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/SetAppNameVer.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/SetAppNameVer.png" alt="" width="1132" height="458" class="aligncenter size-auto wp-image-3166" srcset="https://iosbrain.com/wp-content/uploads/2018/11/SetAppNameVer.png 1132w, https://iosbrain.com/wp-content/uploads/2018/11/SetAppNameVer-300x121.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/SetAppNameVer-768x311.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/SetAppNameVer-1024x414.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p><strong><em>The app icon</em></strong><br />
Here, you can see that I&#8217;ve already set the app icon for &#8220;Acme &#8211; Release&#8221; and am about to create a new app icon set for &#8220;Emca &#8211; Release&#8221; &#8212; this is in the <em>Asset Catalog</em> which is shared by all targets:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon.png" alt="" width="1334" height="1090" class="aligncenter size-auto wp-image-3167" srcset="https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon.png 1334w, https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon-300x245.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon-768x628.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon-1024x837.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/NewAppIcon-1200x981.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Notice that in my code above, I get the code-independent <em>Bundle Identifier</em> and append &#8220;AppIcon&#8221; to it to get the app icon set appropriate to the current target.</p>
<p><strong><em>The copyright text</em></strong><br />
I arranged the <code>Info.plist</code> files for the two targets in this project as I had discussed above in the first sample project. As you&#8217;d expect, there&#8217;s an <code>Info-Acme.plist</code> for the &#8220;Acme &#8211; Release&#8221; target and an <code>Info-Emca.plist</code> for the &#8220;Emca &#8211; Release&#8221; target. Changing the copyright text is code independent. You highlight the <code>plist</code> file in each target, click into the <code>Copyright (human-readable)</code> string value, and make your edits like so:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR.png" alt="" width="1342" height="624" class="aligncenter size-auto wp-image-3168" srcset="https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR.png 1342w, https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR-300x139.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR-768x357.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR-1024x476.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/EditingPlistCR-1200x558.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>We just went through a whole slew of examples of how you can leverage targets for keeping your app code and resources centralized <em>and</em> giving you the flexibility to make changes, like generating multiple flavors of the same app, <em>without</em> using hacks like hardcoding, writing scripts, or writing pyramid-of-doom <code>if</code> statements.</p>
<h4> Different dependencies for different app platforms</h4>
<p>Over the years, I&#8217;ve designed, encoded, used, and accumulated a lot of good, solid C++ code. This code is meant for solving a wide range of problems, or modelling a major gamut of everyday scenarios, for example, messaging, statistical tests, data manipulation, etc. Over the years, I&#8217;ve learned to <em>first</em> look for <em>existing</em> code that I can reuse <em>before</em> spending hundreds of hours reinventing the wheel&#8230; again (and again). <strong>TIP:</strong> Remember that you can divide and conquer your Swift code too by breaking it into modules like frameworks.</p>
<p>What does this have to do with targets? I&#8217;m going to show you how you can reuse existing code in one Xcode project that has targets for macOS and iOS (and tvOS and watchOS if you put a little thought into it). So one project can allow you to build binaries and reuse them in four different Apple app types.   </p>
<p>I could show you how to do this <a href="https://iosbrain.com/blog/2018/01/13/building-swift-4-frameworks-and-including-them-in-your-apps-xcode-9/">with frameworks</a>, and that&#8217;s the direction to which you&#8217;ll want to head, but to keep this didactic, short, and simple, I&#8217;m just going to build libraries. You can download a library-based project I created named &#8220;Xcode Cocoa Library&#8221; from <a href="https://github.com/iosbrain/Xcode-Cocoa-Library">GitHub</a> if you want to follow along.</p>
<p>Create a new Xcode project using these settings:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary.png" alt="" width="1468" height="1062" class="aligncenter size-auto wp-image-3169" srcset="https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary.png 1468w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary-300x217.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary-768x556.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary-1024x741.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrary-1200x868.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Click <em>Next</em> and configure thusly:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings.png" alt="" width="1472" height="1064" class="aligncenter size-auto wp-image-3170" srcset="https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings.png 1472w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings-300x217.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings-768x555.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings-1024x740.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/NewPortableLibrarySettings-1200x867.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Click <em>Next</em> and save in a location of your choosing. In the <em>Project Navigator</em>, find the file <code>Xcode_Cocoa_Library.m</code> and rename it to <code>Xcode_Cocoa_Library.mm</code> to be sure that C++ and Objective-C++ are supported.</p>
<p>As we did earlier, <em>Duplicate</em> the &#8220;Xcode Cocoa Library&#8221; target, renaming the new target and associated scheme as &#8220;Xcode iOS Library.&#8221; At this point, your project should look like so:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/InitLibConfiged.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/InitLibConfiged.png" alt="" width="1064" height="430" class="aligncenter size-auto wp-image-3171" srcset="https://iosbrain.com/wp-content/uploads/2018/11/InitLibConfiged.png 1064w, https://iosbrain.com/wp-content/uploads/2018/11/InitLibConfiged-300x121.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/InitLibConfiged-768x310.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/InitLibConfiged-1024x414.png 1024w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Highlight the &#8220;Xcode Cocoa Library&#8221; target, go to <em>Build Settings</em>, and look at the <em>Architectures</em> section. You&#8217;ll note that the library is configured to be run under macOS on an Intel-based machine:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch.png" alt="" width="1210" height="552" class="aligncenter size-auto wp-image-3172" srcset="https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch.png 1210w, https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch-300x137.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch-768x350.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch-1024x467.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/MacOSArch-1200x547.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>Notice the target builds successfully.</p>
<p>Highlight the &#8220;Xcode iOS Library&#8221; target, go to <em>Build Settings</em>, and look at the <em>Architectures</em> section. Change the <em>Base SDK</em> to the latest version of iOS, like so: </p>
<p><center><a href="https://iosbrain.com/wp-content/uploads/2018/11/ChangePlatformToiOS.gif" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/ChangePlatformToiOS.gif" /></a></center></p>
<p>You should notice that the library is configured to be run under iOS on an ARM-based machine. Build the &#8220;Xcode iOS Library&#8221; target. Notice the target builds successfully.</p>
<p>Let&#8217;s add some code to the project just to be sure we can write C++ and Objective-C++. (Note that many times I&#8217;ve added rock-solid existing C++ .h and .cpp files, blended in some Objective-C and Objective-C++, and <strong>was able to reuse mountains of code in my macOS, watchOS, and iOS apps.</strong>)</p>
<p>Here&#8217;s file <code>Xcode_Cocoa_Library.h</code>:</p>
<p></p><pre class="crayon-plain-tag">#import &lt;Foundation/Foundation.h&gt;
#include &lt;iostream&gt;

@interface Xcode_Cocoa_Library : NSObject

- (void)helloWorld;

@end

class Parent {
public:
    virtual void soundOff() {
        std::cout &lt;&lt; &quot;This is the parent class&quot; &lt;&lt; std::endl;
    }
};

class Child: public Parent {
public:
    virtual void soundOff() {
        std::cout &lt;&lt; &quot;This is the child class&quot; &lt;&lt; std::endl;
    }
};</pre><p></p>
<p>Here&#8217;s file <code>Xcode_Cocoa_Library.mm</code>:</p>
<p></p><pre class="crayon-plain-tag">#import &quot;Xcode_Cocoa_Library.h&quot;

@implementation Xcode_Cocoa_Library

- (void)helloWorld {
    
    Child child;
    child.soundOff();
    
    NSLog(@&quot;Hello, world!&quot;);
    
}

@end</pre><p></p>
<p>Build both targets with the new code added. Here&#8217;s the result (success):</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/LibsBuildSuccess.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/LibsBuildSuccess.png" alt="" width="474" height="302" class="aligncenter size-auto wp-image-3173" srcset="https://iosbrain.com/wp-content/uploads/2018/11/LibsBuildSuccess.png 474w, https://iosbrain.com/wp-content/uploads/2018/11/LibsBuildSuccess-300x191.png 300w" sizes="(max-width: 474px) 85vw, 474px" /></a></p>
<p>These library names would be red if they failed to build.</p>
<p>I&#8217;m not going to show you how to consume this library in a Swift-based project, as it&#8217;s beyond the scope of this tutorial. Rest assured that I&#8217;ve incorporated such libraries (and static libs and frameworks) many times into Swift-based projects (generally using a wrapper, a bridging header, and of course, including the libraries&#8217; header files).</p>
<p>The point I&#8217;m making here is that you can reuse code and organize it, without using hacks, build for multiple platforms, and get great maintainability and extensibility. How? By using targets.</p>
<h4> Truly universal app code</h4>
<p>Take a look at this image from the &#8220;Xcode Cocoa Library&#8221; project discussed in the last section:</p>
<p><a href="https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture.png" rel="noopener" target="_blank"><img src="https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture.png" alt="" width="1268" height="544" class="aligncenter size-auto wp-image-3174" srcset="https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture.png 1268w, https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture-300x129.png 300w, https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture-768x329.png 768w, https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture-1024x439.png 1024w, https://iosbrain.com/wp-content/uploads/2018/11/TowardsFuture-1200x515.png 1200w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></p>
<p>I could create two new targets, one for tvOS and one for watchOS. If I organize code properly, keeping abstraction in mind, I can build, maintain, and extend functionality for macOS, iOS, tvOS, and watchOS <strong>all in one project.</strong> </p>
<h4> Conclusion</h4>
<p>In reality, I currently have libraries that allow me to reuse much of my over-the-years-accumulated C, C++, Objective-C, Objective-C++, and Swift code in macOS, iOS, tvOS, and watchOS apps. The reason I mention all these languages is that Xcode&#8217;s targets and schemes have enabled me to reuse a lot of code I&#8217;ve written in the past &#8212; <em>and</em> I&#8217;ve been able to reuse my legacy code on <em>multiple</em> Apple platforms, namely iOS, macOS, watchOS, and a bit of tvOS.</p>
<p>I&#8217;ve <em>only</em> been able to do that by planning, doing requirements analysis, designing first before coding, concentrating on abstraction &#8212; looking before leaping. I&#8217;ve been able to abstract so much code by <em>implementing</em> concepts and techniques like <a href="https://iosbrain.com/blog/2018/10/05/some-best-practices-for-designing-and-coding-swift-classes/">best practices for building classes</a>, <a href="https://iosbrain.com/blog/2018/05/26/introduction-to-mvvm-refactoring-an-mvc-app-using-the-mvvm-design-pattern/">using architectural design patterns like MVVM</a>, using tactical design patterns (<a href="https://iosbrain.com/blog/2018/07/31/two-creational-design-patterns-in-swift-4-factory-method-and-singleton/">here</a>, <a href="https://iosbrain.com/blog/2018/08/13/two-behavioral-design-patterns-in-swift-observer-and-memento/">here</a>, and <a href="https://iosbrain.com/blog/2018/09/17/two-structural-design-patterns-in-swift-facade-and-adapter/">here</a>), and, of course, using <a href="https://iosbrain.com/blog/2018/03/28/protocol-oriented-programming-in-swift-is-it-better-than-object-oriented-programming/">object-oriented and protocol-oriented programming</a> techniques.</p>
<p>I&#8217;m waxing theoretical. You&#8217;ve got <strong>great tools</strong> available to you, like Xcode and its targets and schemes. Don&#8217;t be a just-get-it-done developer. Invest some time into reading up on the documentation provided with Xcode. Look at some third party books and videos. Join special interest groups. Join social media groups. Take the information you glean from your studying and <strong>put it to practice</strong> in your everyday work. Don&#8217;t be a stick in the mud. <strong>Try new things and constantly push the envelope.</strong></p>
<p>If you take the time, you&#8217;ll find that tools like Xcode provide features beyond your wildest dreams.</p>

]]></content:encoded>
			</item>
	</channel>
</rss>
