<?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>App Development &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/app-development/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 30 Jan 2025 21:38:07 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Provisioning Profiles for macOS Apps</title>
		<link>https://blog.xojo.com/2025/01/30/provisioning-profiles-for-macos-apps/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 30 Jan 2025 15:22:00 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[App Store Connect]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[Mac App Store]]></category>
		<category><![CDATA[Native App Development]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14405</guid>

					<description><![CDATA[Continuing our series on distributing Mac apps, this post will take you through properly setting up a provisioning profile, which is required for your apps&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Continuing our series on distributing Mac apps, this post will take you through properly setting up a <a href="https://developer.apple.com/help/account/manage-profiles/create-a-development-provisioning-profile/" target="_blank" rel="noreferrer noopener">provisioning profile</a>, which is required for your apps to get tested by others in <a href="https://developer.apple.com/testflight/" target="_blank" rel="noreferrer noopener">TestFlight</a>. To review or catch up on earlier steps in this process, see my posts on <a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" target="_blank" rel="noreferrer noopener">Sandboxing, Hardened Runtime and Notarization arrives to the Xojo IDE</a>, <a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/" target="_blank" rel="noreferrer noopener">macOS Apps: From Sandboxing to Notarization, The Basics</a> and <a href="https://blog.xojo.com/2025/01/14/uploading-macos-builds-to-app-store-connect/" target="_blank" rel="noreferrer noopener">Uploading macOS Builds to App Store Connect</a>. But if you have those steps done, let&#8217;s set up the provisioning profile you need.</p>



<span id="more-14405"></span>



<h2 class="wp-block-heading">Development or Distribution</h2>



<p>There are two types of provisioning profiles: Development and Distribution. Development provisioning profiles are for builds sent to the AppStore Connect service that are not meant to be available on the Mac App Store. Development profiles allow apps to be tested by the eligible users associated with that app in TestFlight. For Development provisioning profiles, set the Stage Code value (under Build Settings &gt; Shared) to &#8220;Development&#8221;, &#8220;Alpha&#8221; or &#8220;Beta&#8221;.</p>



<p>On the other hand, Distribution provisioning profiles for macOS are required for builds meant to be publicly available on the Mac App Store once approved by the <a href="https://developer.apple.com/distribute/app-review/" target="_blank" rel="noreferrer noopener">App Store Reviewing Process</a>, they are also available for TestFlight. For Distribution provisioning profiles, make sure the Stage Code value is set to &#8220;Final&#8221; under Build Settings &gt; Shared.</p>



<h2 class="wp-block-heading">Creating Provisioning Profiles</h2>



<p>Regardless of which type of provisioning profile you are creating, you&#8217;ll need to do it from the Apple Developer website (using  your paid developer membership).</p>



<p>In this example we will create a Distribution provisioning profile.</p>



<ul class="wp-block-list">
<li>Login into the <a href="https://developer.apple.com" target="_blank" rel="noreferrer noopener">Apple Developer Website</a>.</li>



<li>Select the Profiles option found under the &#8220;Certificates, IDs &amp; Profiles&#8221; section.</li>



<li>Click on the &#8220;+&#8221; icon found next to the &#8220;Profiles&#8221; header.</li>



<li>Next, select the &#8220;Mac AppStore Connect&#8221; option under the Distribution section, and click on the &#8220;Continue&#8221; button.</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img fetchpriority="high" decoding="async" width="2489" height="1595" src="https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile.png" alt="" class="wp-image-14406" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile.png 2489w, https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile-300x192.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile-1024x656.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile-768x492.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile-1536x984.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/01/1-TypeOfProfile-2048x1312.png 2048w" sizes="(max-width: 2489px) 100vw, 2489px" /></figure>
</div>


<ul class="wp-block-list">
<li>Select the &#8220;Mac&#8221; option under the Profile Type section, and select the App ID value from those available in the associated Popup menu. Make sure that the chosen one (without the value between parentheses) matches the one entered under Build Settings &gt; macOS &gt; Bundle Identifier. Then, click on the &#8220;Continue&#8221; button.</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="2358" height="731" src="https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID.png" alt="" class="wp-image-14407" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID.png 2358w, https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID-300x93.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID-1024x317.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID-768x238.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID-1536x476.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/01/2-SelectAppID-2048x635.png 2048w" sizes="(max-width: 2358px) 100vw, 2358px" /></figure>
</div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>For example the selected one in the screenshot (that, is BW7PU32485.com.aprendexojo.vcardtoqr), matches the one used as the Bundle Identifier for the app in the Xojo IDE (com.aprendexojo.vcardtoqr).</p>
</blockquote>



<ul class="wp-block-list">
<li>Next, select the &#8220;Distribution&#8221; Certificate to be included in the generated provisioning profile. The one selected must be the same one entered in the Developer ID field when building the App from the Xojo IDE (Build Settings &gt; macOS &gt; Sign). For example, I&#8217;m going to use the value (without the quotes) &#8220;Apple Distribution: Francisco Javier Rodriguez Menendez (BW7PU32485)&#8221; as the Developer ID value in Xojo, so I&#8217;m selecting that same Distribution certificate here. Next, click the &#8220;Continue&#8221; button.</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="2377" height="564" src="https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate.png" alt="" class="wp-image-14408" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate.png 2377w, https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate-300x71.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate-1024x243.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate-768x182.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate-1536x364.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/01/3-SelectCertificate-2048x486.png 2048w" sizes="(max-width: 2377px) 100vw, 2377px" /></figure>
</div>


<ul class="wp-block-list">
<li>Name the provisioning profile using a significative name, so you can easily distinguish it later among the many available ones. Next, click the &#8220;Generate&#8221; button so the provisioning profile is generated and downloaded to your local Mac disk (probably in the Downloads folder).</li>



<li>The downloaded provisioning profile will have the name you entered in the previous step. Select it and use the Finder options to rename it as &#8220;embedded.provisionprofile&#8221;.</li>
</ul>



<h2 class="wp-block-heading">Adding the Provisioning Profile to the Project</h2>



<p>macOS provisioning profiles need to be added to the Contents folder on the app bundle, and that is easy to do from the Xojo IDE!</p>



<ul class="wp-block-list">
<li>Open your project in the Xojo IDE and add a new Copy Files build step under Build Settings &gt; MacOS.</li>



<li>Add the &#8220;embedded.provisionprofile&#8221; file to the just added CopyFile build step.</li>



<li>Select the &#8220;Contents Folder&#8221; option from the Destination popup menu in the associated Inspector Panel for the Copy Files build step.</li>



<li>Select the &#8220;Release&#8221; option from the &#8220;Applies To&#8221; popup menu in the associated Inspector Panel for the Copy Files build step, so only this file is copied to the Contents folder when the app is built as a standalone app.</li>
</ul>



<h2 class="wp-block-heading">Adding New Entries to the Entitlements File</h2>



<p>In order for the provisioning profile to be recognized by TestFlight when the app package is sent to AppStore Connect, we need to add a couple more entries to the Entitlements file (see &#8220;<a href="https://blog.xojo.com/2025/01/14/uploading-macos-builds-to-app-store-connect/" target="_blank" rel="noreferrer noopener">Uploading macOS Builds to App Store Connect</a>&#8221; for more details on the Entitlements file).</p>



<ul class="wp-block-list">
<li><strong>Full Application Identifier</strong>. Use the &#8220;com.apple.application-identifier&#8221; as the Key for the entry. The value should be the Application Bundle Identifier (in our example com.aprendexojo.vcardtoqr) prefixed with the Team ID value of the Certificate we used both for signing our app and the provisioning profile itself. In this example it is BW7PU32485, making the string value for this key BW7PU32485.com.aprendexojo.vcardtoqr</li>



<li><strong>Team ID</strong>. Use &#8220;com.apple.developer.team-identifier&#8221; as the Key for the entry, while the value (following with our example) is just the Team ID from the certificate: BW7PU32485</li>
</ul>



<p>All in all, the final Entitlements file will look like this:</p>



<pre class="wp-block-code"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;com.apple.security.app-sandbox&lt;/key&gt;
	&lt;true/&gt;
	&lt;key&gt;com.apple.security.files.user-selected.read-write&lt;/key&gt;
	&lt;true/&gt;
	&lt;key&gt;com.apple.application-identifier&lt;/key&gt;
	&lt;string&gt;BW7PU32485.com.aprendexojo.vcardtoqr&lt;/string&gt;
	&lt;key&gt;com.apple.developer.team-identifier&lt;/key&gt;
	&lt;string&gt;BW7PU32485&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;</code></pre>



<p>That is: Sandboxing enabled, plus the ability for the app to read/write the selected user files, plus the two new entries required so the provisioning profile is recognized by TestFlight when the package is submitted to the AppStore Connect.</p>



<p>Save the changes to the modified Entitlements file (in our example named as &#8220;myEntitlements.entitlements&#8221;).</p>



<h2 class="wp-block-heading">Resign, Re-Package, and Uploading</h2>



<p>If you followed the two previous blog posts in this series, you may have already guessed the next step! Yep, because we modified our &#8220;myEntitlements.entitlements&#8221; file, we need to re-sign the app bundle, package it and submit it to AppStore Connect.</p>



<p>So for re-signing, type the following in a new Terminal window:</p>



<pre class="wp-block-code"><code>codesign --force --timestamp --entitlements path-to-your-myEntitlements.entitlements-file  -s "Apple Distribution: whatever-name-you-use (BZXXXXXXX)" path-to-the-bundle-of-the-compiled-app.app</code></pre>



<p>In order to create a package from the bundle, issue this command from the Terminal:</p>



<pre class="wp-block-code"><code>productbuild --sign "3rd Party Mac Developer Installer: whatever-name-you-use (BZXXXXXXX)"  --component path-to-the-bundle-of-the-compiled-app.app  /Applications path-to-the-generated-package-file.pkg</code></pre>



<p>And in order to upload the package to the AppStore Connect, type the following command in a Terminal window:</p>



<pre class="wp-block-code"><code>xcrun altool  --upload-package path-to-the-package-file.pkg -u your-apple-developer-login-id-goes-here -p "your-app-specific-password-goes-here" --type osx -apple-id "6111111111" --bundle-id "com.yourcomany.yourIdentifier" --bundle-short-version-string "current-short-value" --bundle-version "current-version-value"</code></pre>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1970" height="270" src="https://blog.xojo.com/wp-content/uploads/2025/01/4-AddedToTestFlight.png" alt="" class="wp-image-14410" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/4-AddedToTestFlight.png 1970w, https://blog.xojo.com/wp-content/uploads/2025/01/4-AddedToTestFlight-300x41.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/4-AddedToTestFlight-1024x140.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/4-AddedToTestFlight-768x105.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/4-AddedToTestFlight-1536x211.png 1536w" sizes="auto, (max-width: 1970px) 100vw, 1970px" /></figure>
</div>


<p>If everything went OK, open your Internet Browser and go to <a href="http://appstoreconnect.apple.com">http://appstoreconnect.apple.com</a>, select your app record from the Apps section and click on the TestFlight tab. You should be able to see the just submitted build ready for testing!</p>



<h2 class="wp-block-heading">In Summary</h2>



<p>As you see, adding provisioning profiles to macOS apps sent to the AppStore Connect website to be tested by in TestFlight, requires a bit of previous preparation for the provisioning profile generation itself, copying the file to the project using a Copy Files build step and, then, adding a couple more entries to the Entitlements file.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2048" height="1422" src="https://blog.xojo.com/wp-content/uploads/2025/01/5-macOSTestFlightApp.png" alt="" class="wp-image-14409" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/5-macOSTestFlightApp.png 2048w, https://blog.xojo.com/wp-content/uploads/2025/01/5-macOSTestFlightApp-300x208.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/5-macOSTestFlightApp-1024x711.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/5-macOSTestFlightApp-768x533.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/5-macOSTestFlightApp-1536x1067.png 1536w" sizes="auto, (max-width: 2048px) 100vw, 2048px" /></figure>
</div>


<p>Once everything this is done, your testers will be able to use the TestFlight app to download and test your builds and report feedback, crash reports and other information about it!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>More in this series on distributing Mac apps:</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" target="_blank" rel="noreferrer noopener">Sandboxing, Hardened Runtime and Notarization arrives to the Xojo IDE</a></li>



<li><a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/" target="_blank" rel="noreferrer noopener">macOS Apps: From Sandboxing to Notarization, The Basics</a></li>



<li><a href="https://blog.xojo.com/2025/01/14/uploading-macos-builds-to-app-store-connect/" target="_blank" rel="noreferrer noopener">Uploading macOS Builds to App Store Connect</a></li>



<li><a href="https://blog.xojo.com/2025/01/30/provisioning-profiles-for-macos-apps/">Provisioning Profiles for macOS Apps</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Uploading macOS Builds to App Store Connect</title>
		<link>https://blog.xojo.com/2025/01/14/uploading-macos-builds-to-app-store-connect/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 14 Jan 2025 20:53:32 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[App Store Connect]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[Mac App Store]]></category>
		<category><![CDATA[Native App Development]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14314</guid>

					<description><![CDATA[Since Xojo 2024r4 the IDE includes the ability to automatically compile macOS apps with Sandboxing, Hardened Runtime and Notarization. Continue reading to learn that extra&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Since Xojo 2024r4 the IDE includes the ability to automatically compile macOS apps with Sandboxing, Hardened Runtime and Notarization. Continue reading to learn that extra step in order to submit the created bundle directly to the App Store Connect website!</p>



<span id="more-14314"></span>



<p>There is a Xojo-made tool out there that can simplify the process, and if that&#8217;s your route, check out <a href="https://xojo.com/store/addons/ohanaware.php" target="_blank" rel="noreferrer noopener">AppWrapper from Ohanaware</a>. But if you are the kind of developer that enjoys &#8220;how things work under the hood&#8221;, then follow these steps to do it manually from the command line (or convert these instructions into Xojo Scripts that can be executed as part of the build process itself from the Xojo project).</p>



<p>There are some requirements for all of this to work, but you took care of them already if you already followed our <a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/">previous post about how to apply Sandboxing, Hardened Runtime and Notarize</a> manually to your Xojo macOS builds. Perhaps, the most important one is that this requires a paid Apple Developer Program membership (around US $99/yr). Additionally, Xcode needs to be installed on your Mac in order to use its included <em>altool</em> and <em>productbuild</em> command line tools. Create an app-specific password in order to execute the <em>notarytool</em> command line tool, which is also required when using the <em>altool</em> command line. You likely created one already for the <em>notarytool</em> command line tool which you can use as the password required by the <em>altool</em> command line tool.</p>



<p>If distributing your macOS apps from your website, these need to be signed using the &#8220;Apple Development&#8221; Certificate, but if you are compiling a macOS app for distribution through the Mac App Store, you need to sign it using the &#8220;Apple Distribution&#8221; certificate. So make sure to fill-in the macOS &gt; Signing &gt; Developer ID field properly.</p>



<p>Also important, in order to upload the app to App Store Connect, you need to create a package file from the app bundle, and that package file (.pkg) needs to be signed using the &#8220;3rd Party Mac Developer Installer&#8221;. Make sure you have this certificate installed in your Mac Keychain.</p>



<h2 class="wp-block-heading">First things … First</h2>



<p>Before you can upload you .pkg file to the App Store Connect website, there are some things you need to take care of that are required by Apple for apps to be distributed through the Mac App Store.</p>



<ol class="wp-block-list">
<li>The first thing is to register an App ID (or Identifier) in the <a href="https://developer.apple.com/account/resources/identifiers/">Apple Developer Portal</a>. When doing it, make sure you are creating an explicit Identifier instead of a wildcard one. Also very important, make sure that the identifier (in the reversed DNS form) is the same one you are using in the field macOS &gt; Build &gt; Bundle Identifier of your Xojo project. If they don&#8217;t match, then you can expect errors throughout the process.</li>



<li>The second thing is to create a new record for the App itself in the App Store Connect website. This is the place where you need to provide all the information requested by Apple for two main things: 1. what will be available as the app information when the users reach your app in the Mac App Store (for example product description, price, images, etc.), and, 2. what is for internal and compliance use. All in all, make sure you create a new macOS app record and go through all the available sections to fill in the requested information.</li>
</ol>



<p>Once these two steps are completed, we can focus on the command line itself to create the .pkg file and upload it manually (optionally, it is possible to use the Transporter app to select the .pkg file and upload it).</p>



<h2 class="wp-block-heading">Sing, sing, sing … the re-signing song!</h2>



<p>When building the macOS app from the Xojo IDE, it will be correctly signed based on the settings selected in the Build Settings &gt; Sign section. But because of the way Apple requires some entries to be formatted (specifically those for the CFBundleShortVersionString and CFBundleVersion keys), and the fact that it also requires the LSApplicationCategoryType key to be present in the Plist file with the associated value (the app category value <a href="https://developer.apple.com/documentation/bundleresources/information-property-list/lsapplicationcategorytype?language=objc">among those you can find here</a>), we need to manually edit the generated Info.Plist file for the compiled app.</p>



<p>Yeah, sure we can create an additional text file named Info.Plist file with the appropriate/expected keys and values and drop such file in the IDE navigator for our project so this information gets added/modified, as for example this one:</p>



<pre class="wp-block-code"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;CFBundleShortVersionString&lt;/key&gt;
	&lt;string&gt;1.0.0&lt;/string&gt;
	&lt;key&gt;CFBundleVersion&lt;/key&gt;
	&lt;string&gt;1.0.0&lt;/string&gt;
	&lt;key&gt;LSApplicationCategoryType&lt;/key&gt;
	&lt;string&gt;public.app-category.business&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;</code></pre>



<p>The bad news is that the value for the CFBundleVersion key will not be replaced with the one from our Info.Plist file.</p>



<p>What&#8217;s the downside of manually editing the Info.Plist file for the already compiled app? Well, as soon you make a change and save it,&nbsp;the app bundle signature will be invalidated. But no fear!&nbsp;We know how to do it already, right? If not, I suggest you to <a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/">take a look to the blog post about Sandboxing</a>, Hardened Runtime and Notarization for macOS apps that I mentioned earlier.</p>



<p>Go ahead, select your compiled app in the Finder, click on its icon and select the option &#8220;Show package Contents&#8221; from the contextual menu. This action will show the &#8220;inner files&#8221; of the bundle that composes your app. Inside the Contents folder you will see the Info.Plist file. Click on it and select the option from the contextual menu allowing you to edit it with the text editor of your preference (mine is to use <a href="https://www.barebones.com/products/bbedit/index.html">BBEdit</a> from BareBones Software).</p>



<ul class="wp-block-list">
<li>Locate the CFBundleVersion key entry and change its string value so it doesn&#8217;t have more than three numbers separated by the dot character (as shown in the previous Plist example file).</li>



<li>Locate the CFBundleShortVersionString and change its string to make sure it has three version numbers separated by the dot character.</li>
</ul>



<p>Of course for both of the previous keys, make sure these match your expected version numbers for the app! In the example I used 1.0.0 as it&#8217;s typical for the initial release of an app.</p>



<p>Next, add the expected LSApplicationCategoryType key with the value that better fits your app among those available at the <a href="https://developer.apple.com/documentation/bundleresources/information-property-list/lsapplicationcategorytype?language=objc">Apple Documentation website</a>. In the previous Plist file example I&#8217;m using the one for the Business category:</p>



<pre class="wp-block-code"><code>	&lt;key&gt;LSApplicationCategoryType&lt;/key&gt;
	&lt;string&gt;public.app-category.business&lt;/string&gt;</code></pre>



<p>Save the changes to our modified Info.Plist file. Now it is time to sign it again!</p>



<h2 class="wp-block-heading">What about the Entitlements?</h2>



<p>Heh… wait! Because we need to re-sign our app bundle again, we also need to attach the expected entitlements to it! That means at least one very-important-and-required entitlement: enabling Sandboxing, which needs to be done to any app sent for distribution through the Mac App Store.</p>



<p>While Xojo 2024r4+ is able to do it automatically when building the app, now we also need to do it manually. That means creating our own .entitlements file that will be used when re-signing the app. For example, for a very typical (and bare-bones) app that only needs to read and write files it would look like this:</p>



<pre class="wp-block-code"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;com.apple.security.app-sandbox&lt;/key&gt;
	&lt;true/&gt;
	&lt;key&gt;com.apple.security.files.user-selected.read-write&lt;/key&gt;
	&lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;</code></pre>



<p>Save it as &#8220;myEntitlements.entitlements&#8221; to your Mac drive. Of course, if you app requires more entitlements, go ahead and add them to the previous &#8220;template&#8221; .entitlements file.</p>



<p>We now have our modified .Plist file and the required .Entitlements file… so we have everything we need to re-sign the app bundle again!</p>



<p>Open a Terminal window and type the following command:</p>



<pre class="wp-block-code"><code>codesign --force --timestamp --entitlements path-to-your-myEntitlements.entitlements-file  -s "Apple Distribution: whatever-name-you-use (BZXXXXXXX)" path-to-the-bundle-of-the-compiled-app.app</code></pre>



<p>Look how we are using the reference to the entitlements file, and the &#8220;Apple Distribution&#8221; certificate instead of the &#8220;Apple Development&#8221; certificate.</p>



<h2 class="wp-block-heading">Packaging Acme</h2>



<p>So far so good. We have our app bundle signed again, so we are ready now to create a .pkg file from it! All you need to do is to type the following command from a Terminal window:</p>



<pre class="wp-block-code"><code>productbuild --sign "3rd Party Mac Developer Installer: whatever-name-you-use (BZXXXXXXX)"  --component path-to-the-bundle-of-the-compiled-app.app  /Applications path-to-the-generated-package-file.pkg</code></pre>



<p>As you can see, we are using the &#8220;3rd Party Mac Developer Installer&#8221; certificate in order to create the package file.</p>



<h2 class="wp-block-heading">Uploading it!</h2>



<p>With the package file already created, we now have all we need to upload it to the App Store Connect website. At this point you can follow two paths. The first one is to use the Transporter App that you can download from the Mac App Store itself. In that case:</p>



<ul class="wp-block-list">
<li>Open the Transporter app.</li>



<li>Click on the &#8220;+&#8221; icon. That action will bring a dialog where you can select the previously created .pkg file.</li>



<li>Once it is added, Transporter will make some early checks on the package contents. If everything goes OK, you should see something like this:</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1824" height="1420" src="https://blog.xojo.com/wp-content/uploads/2025/01/TransporterA.png" alt="" class="wp-image-14320" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/TransporterA.png 1824w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterA-300x234.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterA-1024x797.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterA-768x598.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterA-1536x1196.png 1536w" sizes="auto, (max-width: 1824px) 100vw, 1824px" /></figure>
</div>


<p>The interesting thing about using Transporter is that you can select the &#8220;Verify&#8221; option from the associated contextual menu (the one with the three dots icon). That action will start some more deeply checking on the package (and its contents) so you can get some early information about things that need to be fixed prior uploading it to the App Store Connect Website. For example, this error generated when the bundle version is duplicated:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1824" height="1420" src="https://blog.xojo.com/wp-content/uploads/2025/01/TransporterB.png" alt="" class="wp-image-14333" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/TransporterB.png 1824w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterB-300x234.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterB-1024x797.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterB-768x598.png 768w, https://blog.xojo.com/wp-content/uploads/2025/01/TransporterB-1536x1196.png 1536w" sizes="auto, (max-width: 1824px) 100vw, 1824px" /></figure>
</div>


<p>The second option involves using the aforementioned <em>altool</em> command line to automatically upload the package to the App Store Connect website. If you choose this path, all you need to do is to execute the following command from a Terminal window:</p>



<pre class="wp-block-code"><code>xcrun altool  --upload-package path-to-the-package-file.pkg -u your-apple-developer-login-id-goes-here -p "your-app-specific-password-goes-here" --type osx -apple-id "6111111111" --bundle-id "com.yourcomany.yourIdentifier" --bundle-short-version-string "1.0.0" --bundle-version "1.0.0"     </code></pre>



<p>Some considerations about the provided options/values for this command:</p>



<ul class="wp-block-list">
<li><strong>-u</strong>: This is the login name you use when accessing the Apple Developer website</li>



<li><strong>-p</strong>: This is the app-specific password you created from scratch following the steps provided in the aforementioned blog post.</li>



<li><strong>-apple-id</strong>: This is the numeric value you can find under General &gt; App Information at the appstoreconnect.apple.com website for the record created for this app:</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1358" height="788" src="https://blog.xojo.com/wp-content/uploads/2025/01/AppStoreConnectA.png" alt="" class="wp-image-14321" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/AppStoreConnectA.png 1358w, https://blog.xojo.com/wp-content/uploads/2025/01/AppStoreConnectA-300x174.png 300w, https://blog.xojo.com/wp-content/uploads/2025/01/AppStoreConnectA-1024x594.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/01/AppStoreConnectA-768x446.png 768w" sizes="auto, (max-width: 1358px) 100vw, 1358px" /></figure>
</div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>This information can also be retrieved using:</p>



<pre class="wp-block-code"><code>xcrun altool --list-apps -u your-apple-developer-login-id-goes-here -p "your-app-specific-password-goes-here" --output-format json</code></pre>
</blockquote>



<ul class="wp-block-list">
<li><strong>&#8211;bundle-id</strong>: Make sure to provide the same value as the one used when creating the Identifier for the App and, thus, the same one used under Build Settings &gt; macOS &gt; Build &gt; Build Identifier field in your Xojo project.</li>



<li><strong>&#8211;bundle-short-version-string</strong>: Make sure it&#8217;s the same value used for the CFBundleShortVersionString key in the .Plist file.</li>



<li><strong>&#8211;bundle-version</strong>: Make sure to provide the same value as the one used for the CFBundleVersion key in the .Plist file.</li>
</ul>



<p>Once the command is executed, your package file will be uploaded to the App Store Connect website and, once completed, eligible as a new Build to be added to your app record so you can send it to review as part of the Apple reviewing process.</p>



<h2 class="wp-block-heading">In Summary</h2>



<p>There are several details to take care of, but Xojo has simplified the process of covering the &#8220;last mile&#8221; of sending you compiled app for review at the App Store Connect website.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>More in this series on distributing Mac apps:</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" target="_blank" rel="noreferrer noopener">Sandboxing, Hardened Runtime and Notarization arrives to the Xojo IDE</a></li>



<li><a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/" target="_blank" rel="noreferrer noopener">macOS Apps: From Sandboxing to Notarization, The Basics</a></li>



<li><a href="https://blog.xojo.com/2025/01/14/uploading-macos-builds-to-app-store-connect/" target="_blank" rel="noreferrer noopener">Uploading macOS Builds to App Store Connect</a></li>



<li><a href="https://blog.xojo.com/2025/01/30/provisioning-profiles-for-macos-apps/">Provisioning Profiles for macOS Apps</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>macOS Apps: From Sandboxing to Notarization, The Basics</title>
		<link>https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 22 Aug 2024 15:45:28 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[App Store Connect]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[Entitlements]]></category>
		<category><![CDATA[Hardened Runtime]]></category>
		<category><![CDATA[Mac App Store]]></category>
		<category><![CDATA[Native App Development]]></category>
		<category><![CDATA[Notarization]]></category>
		<category><![CDATA[Sandboxing]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13510</guid>

					<description><![CDATA[You are likely already familiar with terms like Sandboxing, hardened runtime and Notarization. After all, these are required if you plan to distribute your macOS&#8230;]]></description>
										<content:encoded><![CDATA[
<p>You are likely already familiar with terms like Sandboxing, hardened runtime and Notarization. After all, these are required if you plan to distribute your macOS apps through the Mac App Store. But, starting with macOS Sequoia 15 (expected in the fall of 2024), Apple has tightened the runtime security protections even more. For example, it was common to Control + click on any downloaded macOS app from Internet that has not been signed and simply choose the Open option from the contextual menu to open it. That won&#8217;t be an option under Sequoia (although it still possible to run the unsigned app).</p>



<p>In fact, Apple recommends to Notarize the software even if you are going to distribute it from your own website, outside of the Mac App Store. But, don&#8217;t be scared! Currently there are good third parties options available that ease the path, like <a href="https://ohanaware.com/appwrapper/">App Wrapper from Ohanaware</a>, or some OpenSource options as for example <a href="https://github.com/jo-tools/xojo2dmg">Xojo2DMG</a>; and through this article you will see how to enable Sandboxing, runtime hardening and even Notarizing on a simple example app. Of course, this will touch only the basics and it is up to you to read the related Apple Documentation to add the entries, both the Entitlements and additional keys/values in the app Info.plist file, required by the purposes of your particular app, for example file access, camera or mic access, network access, etc.</p>



<h2 class="wp-block-heading">A Bit of Common Ground</h2>



<p>At this point, your head may be spinning if you are unfamiliar with these app security terms; so, what do Sandbox, hardened runtime and Notarizing mean when they are applied to macOS apps?</p>



<h3 class="wp-block-heading">Sandboxing</h3>



<p>When a macOS app is sandboxed, that means that macOS will create an exclusive container for everything related to the app the first time it is launched. This is what happens when installing an iOS app, too! Such a container will have its own structure to access things like documents, pictures, downloads, etc. Think about it as the own private execution space for the app:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1006" height="640" src="https://blog.xojo.com/wp-content/uploads/2024/08/1-Container.png" alt="" class="wp-image-13511" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/1-Container.png 1006w, https://blog.xojo.com/wp-content/uploads/2024/08/1-Container-300x191.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/1-Container-768x489.png 768w" sizes="auto, (max-width: 1006px) 100vw, 1006px" /></figure>
</div>


<p>Of course, there are <a href="https://developer.apple.com/documentation/security/app_sandbox?language=objc">entitlements waiting for you</a> so your sandboxed app can access the files created by other apps (including the Desktop, Downloads, Movies, Music and Picture folders), among other things.</p>



<h3 class="wp-block-heading">Hardened Runtime</h3>



<p>When enabled for your macOS app, hardened runtime adds an extra layer of protection to the running code itself. For example, it prevents certain classes of exploits, like code injection, dynamically linked library (DLL) hijacking, and process memory space tampering. This kind of protection is also enhanced by the <a href="https://support.apple.com/en-us/102149">System Integrity Protection (SIP)</a>.</p>



<h3 class="wp-block-heading">Notarization</h3>



<p>In brief, this is a third layer of confidence for the potential users of your macOS app. When the app is notarized, that ensures to the user that the Developer ID-signed software you distribute has been checked by Apple for malicious components. This is not related with the Apple Review process of your app when it is submitted to the Mac App Store, it&#8217;s related to the <a href="https://support.apple.com/en-gb/guide/security/sec5599b66df/web">macOS Gatekeeper technology</a>. So, when a Notarized app is downloaded from Internet, for example, Gatekeeper will use the notarization ticket attached to your app/DMG file to provide more meaningful information about the origin of the app, including if it is safe for the user to open it.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="744" height="752" src="https://blog.xojo.com/wp-content/uploads/2024/08/2-Gatekeeper.png" alt="" class="wp-image-13513" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/2-Gatekeeper.png 744w, https://blog.xojo.com/wp-content/uploads/2024/08/2-Gatekeeper-297x300.png 297w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>
</div>


<h2 class="wp-block-heading">Preparation</h2>



<p>In order to follow this article, you will need:</p>



<ul class="wp-block-list">
<li><strong>Xojo</strong>. <a href="https://www.xojo.com/download">Download it for macOS</a> if you have not done yet.</li>



<li><strong>macOS 11.3</strong> or later.</li>



<li><strong>Xcode 13</strong> or later. Run it at least one time and make sure that all its required components and SDKs are installed.</li>



<li><strong>Apple Developer ID</strong>. This needs to be a paid Apple Developer membership. Also, make sure you have your Developer certificates installed in the Mac.</li>



<li>A working <strong>Internet</strong> connection.</li>
</ul>



<p>With all of this in place, open Xojo to create a macOS Desktop project and do some basic layout in the by default window. It is not required to add any functionality to keep the focus in the task at hand. Then, use Build Settings &gt; macOS &gt; Mac App Name to give an appropriate name to the built application (for this example I named it &#8220;SandboxedApp&#8221;).</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="594" height="654" src="https://blog.xojo.com/wp-content/uploads/2024/08/3-XojoProjectName.png" alt="" class="wp-image-13512" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/3-XojoProjectName.png 594w, https://blog.xojo.com/wp-content/uploads/2024/08/3-XojoProjectName-272x300.png 272w" sizes="auto, (max-width: 594px) 100vw, 594px" /></figure>
</div>


<p>Lastly, save the project (for example into the Documents folder) and click the Build button to build the app! It is not required at this point to assign the Developer ID in the Build Settings &gt; macOS &gt; Sign section, because we are going to sign it (again) in the next steps.</p>



<h2 class="wp-block-heading">Creating the Entitlements File</h2>



<p>The entitlements file is pretty similar to the Info.plist file you probably already know that is in charge of storing the required keys and values for the app to properly work. Both of these are in XML format, and the only difference is that while the Info.plist file is created for you by Xojo, the Entitlements file needs to be, currently, manually created for you.</p>



<p>So, open your text editor of choice (there a lot of there out there, both free and paid ones; personally I tend to use BBEdit from BareBones Software). Add the following lines to the text document and save it with the name &#8220;Entitlements.plist&#8221; (if you keep it next to the saved built macOS app, the better). This is the file where you will probably want to add more entitlement entries as your app requires them:</p>



<pre class="wp-block-code"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"&gt;
&lt;plist version="0.9"&gt;
&lt;dict&gt;
  &lt;key&gt;com.apple.security.app-sandbox&lt;/key&gt;
  &lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;</code></pre>



<h2 class="wp-block-heading">Sandbox Your App</h2>



<p>With the compiled app and the entitlements file in place, open the Terminal app and type the following command and press the return key:</p>



<pre class="wp-block-code"><code>&gt; codesign --force --deep --timestamp --entitlements &lt;path-to-your-entitlements.plist-file&gt; -s "Developer ID Application: &lt;your-full-developer-name (including-the-team-id)&gt;" &lt;path-to-the-bundle-of-your-app&gt;</code></pre>



<p>Once executed, run the &#8220;SandboxedApp&#8221;, open the Activity Monitor app and make sure that the Sandbox option is enabled under the View &gt; Columns options. Then, use the search box of the main window to filter the displayed processes so it only displays your app. Take a look to the value under the Sandbox column and you will see that the app is now Sandboxed, and the Container for it has been created under the Library/Containers path. Quit the app when you are done.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1704" height="992" src="https://blog.xojo.com/wp-content/uploads/2024/08/4-Sandbox.png" alt="" class="wp-image-13514" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/4-Sandbox.png 1704w, https://blog.xojo.com/wp-content/uploads/2024/08/4-Sandbox-300x175.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/4-Sandbox-1024x596.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/4-Sandbox-768x447.png 768w, https://blog.xojo.com/wp-content/uploads/2024/08/4-Sandbox-1536x894.png 1536w" sizes="auto, (max-width: 1704px) 100vw, 1704px" /></figure>
</div>


<h2 class="wp-block-heading">Hardened Runtime</h2>



<p>With our app already sandboxed, let&#8217;s look how to add the hardened option to it. Once again, type the following command in the Terminal prompt:</p>



<pre class="wp-block-code"><code>&gt; codesign --force --deep <strong>--options runtime</strong> --timestamp --entitlements &lt;path-to-your-entitlements.plist-file&gt; -s "Developer ID Application: &lt;your-full-developer-name (including-the-team-id)&gt;" &lt;path-to-the-bundle-of-your-app&gt;</code></pre>



<p>As you can see, it doesn&#8217;t vary much from the previous command. All it adds is the &#8220;<strong>&#8211;options runtime</strong>&#8221; text in charge of enabling the runtime hardening. Also, as you might guess, using this command will enable the Sandboxing of the app and also the runtime hardening, at all once.</p>



<p>Do you want to check if it worked? Well, type the following command at the Terminal prompt:</p>



<pre class="wp-block-code"><code>&gt; codesign --display --verbose &lt;path-to-the-bundle-of-your-app&gt;</code></pre>



<p>It will produce an output similar to this one:</p>



<pre class="wp-block-code"><code>Executable=&lt;path-to-the-executable&gt;
Identifier=com.xojo.sandboxedapp
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=43297 <strong>flags=0x10000(runtime)</strong> hashes=1342+7 location=embedded
Signature size=9100
Timestamp=13 Aug 2024 at 12:51:28 PM
Info.plist entries=15
TeamIdentifier=************
Runtime Version=11.1.0
Sealed Resources version=2 rules=13 files=4
Internal requirements count=1 size=184</code></pre>



<p>It is the &#8220;<strong>flags=0x1000(runtime)</strong>&#8221; which shows that, in fact, the app runtime is hardened. Congrats!</p>



<h2 class="wp-block-heading">Notarizing the App</h2>



<p>This is the final step, but is going to require an extra step from your side. Because the notarytool command line tool, used for notarizing the app, is going to require the ID and password from your Apple ID account, plus the fact that it uses 2FA authentication, it is very convenient to create an app specific password for it.</p>



<h3 class="wp-block-heading">Creating an App-Specific Password</h3>



<p>In order to create the password used by the notarytool process, follow this steps:</p>



<ol class="wp-block-list">
<li>Sign in to <a href="https://appleid.apple.com">appleid.apple.com</a></li>



<li>In the Sign-in and Security section, select the App-Specific Passwords option:</li>
</ol>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1408" height="1462" src="https://blog.xojo.com/wp-content/uploads/2024/08/5-AppSpecificPasswordA.png" alt="" class="wp-image-13515" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/5-AppSpecificPasswordA.png 1408w, https://blog.xojo.com/wp-content/uploads/2024/08/5-AppSpecificPasswordA-289x300.png 289w, https://blog.xojo.com/wp-content/uploads/2024/08/5-AppSpecificPasswordA-986x1024.png 986w, https://blog.xojo.com/wp-content/uploads/2024/08/5-AppSpecificPasswordA-768x797.png 768w" sizes="auto, (max-width: 1408px) 100vw, 1408px" /></figure>
</div>


<ol start="3" class="wp-block-list">
<li>The previous action will bring a new dialog displaying all the app-specific passwords already created. Click the &#8220;+&#8221; button to add a new one:</li>
</ol>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1392" height="1308" src="https://blog.xojo.com/wp-content/uploads/2024/08/6-AppSpecificPasswordB.png" alt="" class="wp-image-13516" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/6-AppSpecificPasswordB.png 1392w, https://blog.xojo.com/wp-content/uploads/2024/08/6-AppSpecificPasswordB-300x282.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/6-AppSpecificPasswordB-1024x962.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/6-AppSpecificPasswordB-768x722.png 768w" sizes="auto, (max-width: 1392px) 100vw, 1392px" /></figure>
</div>


<ol start="4" class="wp-block-list">
<li>Type a meaningful name for as the &#8220;Title&#8221; or description for your new password in the presented dialog (<strong>notarytool</strong> could be a good one):</li>
</ol>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="918" height="742" src="https://blog.xojo.com/wp-content/uploads/2024/08/7-AppSpecificPasswordC.png" alt="" class="wp-image-13517" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/7-AppSpecificPasswordC.png 918w, https://blog.xojo.com/wp-content/uploads/2024/08/7-AppSpecificPasswordC-300x242.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/7-AppSpecificPasswordC-768x621.png 768w" sizes="auto, (max-width: 918px) 100vw, 918px" /></figure>
</div>


<ol start="5" class="wp-block-list">
<li>Once you click the Create button it is possible that you will be asked to authenticate again using your Apple ID. Once done, a new dialog will present the generated password to you. Copy it and write it down (or paste it) into a safe place, because we are going to need it in the next step.</li>
</ol>



<h3 class="wp-block-heading">Adding the notarytool specific password to the Keychain</h3>



<p>Because this app-specific password is going to be used by the notarytool command line tool, it would be very convenient to have it stored in the macOS Keychain. To do so, type the following command at the Terminal prompt, and press the Return key:</p>



<pre class="wp-block-code"><code>&gt; xcrun notarytool store-credentials "notarytool-password" --apple-id "&lt;your-apple-ID&gt;" --team-id &lt;your-developer-team-id&gt; --password &lt;the-password-copied-from-the-previous-step&gt;</code></pre>



<p>Once executed, you will be able to see the password added to the Keychain app under the name of &#8220;notarytool-password&#8221;:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1948" height="1068" src="https://blog.xojo.com/wp-content/uploads/2024/08/8-NotaryToolPassword.png" alt="" class="wp-image-13518" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/8-NotaryToolPassword.png 1948w, https://blog.xojo.com/wp-content/uploads/2024/08/8-NotaryToolPassword-300x164.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/8-NotaryToolPassword-1024x561.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/8-NotaryToolPassword-768x421.png 768w, https://blog.xojo.com/wp-content/uploads/2024/08/8-NotaryToolPassword-1536x842.png 1536w" sizes="auto, (max-width: 1948px) 100vw, 1948px" /></figure>
</div>


<h3 class="wp-block-heading">Creating a Zip file for your app</h3>



<p>The notarization process is handled by the Apple notary service running in the Internet, what means that notarytool needs to send (upload) the bundle of your app in an appropriate format. There are two options: as a DMG file (that needs to be signed before submitting), or as a zipped file, what is even faster and easier (Trivia: Did you know how easy it is to <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-zip">create Zip files in Xojo code</a>?)</p>



<p>So, in order to upload our app for notarization, we need to create a Zip file first. Once again, it is time to type a new command at the Terminal prompt:</p>



<pre class="wp-block-code"><code>&gt; /usr/bin/ditto -c -k --keepParent &lt;path-to-app-bundle&gt; &lt;path-to-generated-zip-file/file-name.zip&gt;</code></pre>



<h3 class="wp-block-heading">&nbsp;</h3>



<h3 class="wp-block-heading">Uploading the app for Notarization</h3>



<p>With our Zip file in place, we now have all the pieces to send it to the notarization process. The time spent by that process may (and will) vary depending of several factors.</p>



<p>In order to send the file, type the following command at the Terminal prompt:</p>



<pre class="wp-block-code"><code>&gt; xcrun notarytool submit &lt;path-to-zip-file/file-name.zip&gt; --keychain-profile "notarytool-password" --wait </code></pre>



<p>After pressing the Return key, the process will start and the Terminal will output information about the progress; something similar to this:</p>



<pre class="wp-block-code"><code>Conducting pre-submission checks for &lt;name-of-your-zip-file&gt; and initiating connection to the Apple notary service...
Submission ID received
  id: &lt;some-id-number-goes-here&gt;
Upload progress: 100.00% (8.65 MB of 8.65 MB)   
Successfully uploaded file
  id: &lt;some-id-number-goes-here&gt;
  path: &lt;path-of-the-zip-file&gt;
Waiting for processing to complete.
Current status: Accepted........
Processing complete
  id: &lt;keep-this-id-in-a-safe-place-you-will-need-it-later&gt;
  status: Accepted</code></pre>



<p>Have you seen the last line? The &#8220;<strong>status: Accepted</strong>&#8221; means that everything worked OK, and the notarization process has been successful, but it&#8217;s better if we check! Type the following command at the Terminal prompt. This one will ask the notarytool command to download the log file in JSON format to be saved at the desired path. It is a good habit to do it, because such a log file will include some eventual error and explanation about possible errors during the notarization process, including those related to the app itself:</p>



<pre class="wp-block-code"><code>&gt; xcrun notarytool log &lt;put-here-the-value-you-saved-in-a-secure-place-from-the-id-field-in-the-previous-output&gt; --keychain-profile "notarytool-password" &lt;path-to-save-the-log.json&gt;</code></pre>



<h2 class="wp-block-heading">Staple the Ticket!</h2>



<p>Assuming that everything worked OK, it is time to staple the notarization ticket to the app itself. It is not required, but is convenient to avoid online checks when the user runs the app, or Gatekeeper inspects it.</p>



<p>Yeah, that means using a new command from Terminal on the already signed, sandboxed and runtime hardened app bundle (not the Zip file you created for submitting using notarytool):</p>



<pre class="wp-block-code"><code>&gt; xcrun stapler staple "&lt;path-to-the-signed-sandboxed-and-hardened-app-bundle&gt;"</code></pre>



<p>After that, you can check that everything went OK using the following command:</p>



<pre class="wp-block-code"><code>&gt; spctl -a -vvv -t install &lt;path-to-the-signed-sandboxed-and-hardened-app-bundle&gt;</code></pre>



<p>And you should get something similar to this as the output:</p>



<pre class="wp-block-code"><code>source=Notarized Developer ID
origin=&lt;your-full-developer-ID-Application&gt;</code></pre>



<h2 class="wp-block-heading">App Distribution</h2>



<p>That&#8217;s fine, but you will probably want to distribute your app from the Internet using a DMG container. In that case, follow these steps:</p>



<ol class="wp-block-list">
<li>Create a DMG container (file).</li>



<li>Copy your already notarized app bundle into it.</li>



<li>Notarize the DMG file.</li>



<li>Staple the ticket to the DMG file.</li>
</ol>



<p>That way the DMG container will be Notarized along with the app bundle inside it.</p>



<h2 class="wp-block-heading">In Summary</h2>



<p>As we did see, all the process of sandboxing, runtime hardening and Notarization involves a bunch of commands from the terminal, including the creation of the Zip file. But the good news is that all the process could be automated using Xojo itself! (take a look to the <a href="https://documentation.xojo.com/api/os/shell.html#executemodes">Shell</a> class and the <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-zip">Zip method from the FolderItem class</a> if you are not familiar with them).</p>



<p>As I said before, this article only on touches the basics and doesn&#8217;t dig into Provisioning Profile creation (associated with Capabilities required by the app), the Entitlements your app may need to properly work, among other topics; so you may find these Apple Developer Documentation of interest:</p>



<p>&#8211; <a href="https://developer.apple.com/help/account/manage-profiles/create-a-development-provisioning-profile/">Provisioning profiles</a>.<br>&#8211; <a href="https://developer.apple.com/documentation/bundleresources/entitlements?language=objc">macOS Entitlements</a>.<br>&#8211; <a href="https://developer.apple.com/documentation/security/app_sandbox?language=objc">macOS Sandbox</a>.<br>&#8211; <a href="https://developer.apple.com/documentation/security/hardened_runtime?language=objc">macOS Hardened Runtime</a>.<br>&#8211; <a href="https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution?language=objc">macOS Notarization</a>.</p>



<p>Happy Xojo Coding!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>More in this series on distributing Mac apps:</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" target="_blank" rel="noreferrer noopener">Sandboxing, Hardened Runtime and Notarization arrives to the Xojo IDE</a></li>



<li><a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/" target="_blank" rel="noreferrer noopener">macOS Apps: From Sandboxing to Notarization, The Basics</a></li>



<li><a href="https://blog.xojo.com/2025/01/14/uploading-macos-builds-to-app-store-connect/" target="_blank" rel="noreferrer noopener">Uploading macOS Builds to App Store Connect</a></li>



<li><a href="https://blog.xojo.com/2025/01/30/provisioning-profiles-for-macos-apps/">Provisioning Profiles for macOS Apps</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Over 20 years of native, cross-platform app development and still going strong</title>
		<link>https://blog.xojo.com/2023/09/06/over-20-years-of-native-cross-platform-app-development-and-still-going-strong/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Wed, 06 Sep 2023 21:32:28 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Development Tools]]></category>
		<category><![CDATA[FileMaker]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Native App Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[VB]]></category>
		<category><![CDATA[VB Alternative]]></category>
		<category><![CDATA[VB for Mac]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12012</guid>

					<description><![CDATA[The recent news about Microsoft discontinuing Visual Studio's support for Mac has got us talking about longevity in the field of software development. We all know technology changes rapidly and you, and the tools you use, can't afford to stand still. Here's an infographic that illustrates how Xojo's been continually updating and modernizing since 1996 while other development tools come and go.]]></description>
										<content:encoded><![CDATA[
<p>The recent news about Microsoft <a href="https://9to5mac.com/2023/08/30/microsoft-visual-studio-mac-discontinued/">discontinuing Visual Studio</a>&#8216;s support for Mac has got us talking about longevity in the field of software development. We all know technology changes rapidly and you, and the tools you use, can&#8217;t afford to stand still. </p>



<p>With this in mind, here&#8217;s an infographic that illustrates how Xojo&#8217;s been continually updating and modernizing since 1996 while other development tools come and go. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="410" height="1024" src="https://blog.xojo.com/wp-content/uploads/2023/08/FINAL-2023-black-edit-VS-ARM-edits-410x1024.jpg" alt="" class="wp-image-12014" srcset="https://blog.xojo.com/wp-content/uploads/2023/08/FINAL-2023-black-edit-VS-ARM-edits-410x1024.jpg 410w, https://blog.xojo.com/wp-content/uploads/2023/08/FINAL-2023-black-edit-VS-ARM-edits-120x300.jpg 120w, https://blog.xojo.com/wp-content/uploads/2023/08/FINAL-2023-black-edit-VS-ARM-edits-768x1920.jpg 768w, https://blog.xojo.com/wp-content/uploads/2023/08/FINAL-2023-black-edit-VS-ARM-edits.jpg 800w" sizes="auto, (max-width: 410px) 100vw, 410px" /></figure>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The Value of a Native App</title>
		<link>https://blog.xojo.com/2019/11/06/the-value-of-a-native-app/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Wed, 06 Nov 2019 17:45:39 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Native App Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6236</guid>

					<description><![CDATA[It was reported that Apple is rejecting from the Mac App Store apps written using the Electron framework.  This is where we see the advantage of writing a native application. ]]></description>
										<content:encoded><![CDATA[
<p>Quite recently it was <a href="https://mjtsai.com/blog/2019/11/04/electron-apps-rejected-from-the-mac-app-store/">reported</a> that Apple is rejecting apps written using the <a href="https://electronjs.org">Electron</a> framework from the Mac App Store. The apparent problem is that Electron is calling private macOS APIs which are APIs that Apple has not documented. The presumption is that the use of these APIs provided some performance benefits.</p>



<p>Electron is a framework for building cross-platform apps using HTML, CSS and JavaScript. Essentially, it&#8217;s for building web apps that run locally rather than from a server. They are cross-platform in as much as HTML is. Some elements of HTML can be native such as textfields but not all elements are.</p>



<p>This is where we see the advantage of writing a native application. Native apps utilize more of the look and feel of the host OS and thus appear and behave more inline with the end user&#8217;s expectation. At Xojo, we use <a href="https://www.slack.com">Slack</a> for text chatting. On desktop operating systems such as MacOS and Windows, Slack is an Electron app. As such it doesn&#8217;t look and feel like other desktop apps. It also suffers (needlessly as I understand it) from the fact that it does not auto-correct as you type the way <em>nearly every other native desktop app does</em>. It&#8217;s interesting to note that the mobile version of Slack, which <em>is</em> a native app, does auto-correct text as you type just as you&#8217;d expect. This makes the native version pleasant to use and the Electron-based version annoying. It&#8217;s unfortunate, because I use the Electron-based version far more than the native version simply because I spend a lot of time on my computer everyday. I&#8217;ve been told that the Electron-based version <em>could</em> be made to auto-correct but I&#8217;m suspicious of this because if it were easy, I have to believe that the fine folks at Slack would have done so long ago.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1002" height="62" src="https://blog.xojo.com/wp-content/uploads/2019/11/SlackTyping.png" alt="" class="wp-image-6238" srcset="https://blog.xojo.com/wp-content/uploads/2019/11/SlackTyping.png 1002w, https://blog.xojo.com/wp-content/uploads/2019/11/SlackTyping-300x19.png 300w, https://blog.xojo.com/wp-content/uploads/2019/11/SlackTyping-768x48.png 768w" sizes="auto, (max-width: 1002px) 100vw, 1002px" /></figure>



<p>Slack no doubt chose Electron upon which to base their product because of the time it would save them building it. They could focus on what makes their app unique rather than all the details of Linux, macOS and Windows. While that&#8217;s a sensible goal, Electron may not have been the best choice. It&#8217;s possible (perhaps even likely) that Slack didn&#8217;t know Electron was using private APIs. I&#8217;m surprised that those behind Electron would not have the foresight to realize the significant negative impact of using private APIs but sometimes as humans we get so far down the path with something only to run into a show stopping obstacle at the last moment that we begin to become more morally flexible in order to reach our goal. This is of course short-sighted and can come back to haunt us. We could have done the same with Xojo, but we didn&#8217;t nor would we. We always strive for what is right over what is easy.</p>



<p>One of the comments on the blog post I linked to above said that perhaps Slack would now choose to write a native app. I&#8217;m doubtful about this. However, that <em>is</em> what Slack <em>should</em> do. A native app would provide a better end user experience and that&#8217;s what ultimately counts. It&#8217;s all well and good to save development time but if the result is a user experience that annoys the end user, then the saved development time wasn&#8217;t worth while.</p>



<p>There are options (Xojo among them) for building cross-platform native applications. Xojo has a lot of text-parsing functions and our <a href="http://documentation.xojo.com/api/deprecated/textfield.html">TextField</a> control has built-in support for both spellchecking and auto-correct because it&#8217;s a native control on all platforms. This is something that we provide to Xojo users nearly for free because we use native controls. It&#8217;s another example of why native applications are inherently better.</p>



<p>If you want your app to provide the best user experience, it should be native on whatever platform it runs. HTML is great for the web because that is the native way to create web pages. Anyone who ever tried a Java app running in a browser knows how unnatural that feels. On the desktop or mobile, the app should be written using native (and public) APIs. In the end, software is for the user and should be written first with their user experience in mind. Saving time with a particular tool or framework is a secondary consideration.</p>



<p>Update: Electron has submitted an update to resolve the private API issue.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Why we don’t provide ETAs &#8230; and why you shouldn’t either</title>
		<link>https://blog.xojo.com/2019/10/29/why-we-dont-provide-etas-and-why-you-shouldnt-either/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Tue, 29 Oct 2019 17:34:55 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Team Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6187</guid>

					<description><![CDATA[Brent Simmons did an excellent job explaining why developers shouldn't provide ETAs. ]]></description>
										<content:encoded><![CDATA[
<p>Brent Simmons <a href="https://inessential.com/2019/10/28/no_etas">recently</a> did a better job of explaining this than I ever have. His summary just nails it:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>This is all just to say that app-making is nothing like building a house. It’s more like building the first house ever in the history of houses, with a pile of rusty nails and your bare hands, in a non-stop tornado. It’s different every time, and it’s astonishingly complex, non-linear, and unpredictable &#8230; <em>The only reason anything ever ships is because people just keep working until it’s ready.</em></p><cite>*emphasis mine</cite></blockquote>



<p>And if you have any doubt of the truth of this, just look at software projects that ship on a pre-defined schedule rather than when they are ready. </p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 Things Developers Need To Release Their App Right</title>
		<link>https://blog.xojo.com/2019/01/07/3-things-you-need-to-announce-your-app-or-release-right/</link>
		
		<dc:creator><![CDATA[Dana Brown]]></dc:creator>
		<pubDate>Mon, 07 Jan 2019 10:00:37 +0000</pubDate>
				<category><![CDATA[Dev Marketing]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[App Marketing]]></category>
		<category><![CDATA[Developer Marketing]]></category>
		<category><![CDATA[Social Media Marketing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4953</guid>

					<description><![CDATA[Marketing and promoting your app is the key to its commercial success, starting with announcing it.  Here are the 3 most essential steps you should take when announcing your app (or release) to the world.]]></description>
										<content:encoded><![CDATA[<p>So you&#8217;ve created an app that you plan to sell, now you&#8217;re done, right? Nope, not even close! Developing your app is just step one. Marketing and promoting your app is the key to its commercial success, starting with announcing it. We talked to one successful Xojo developer who has several apps in the App Store. He told us that he spends 50% of his time on development and 50% of his time on marketing. Marketing. You think it&#8217;s just something for the Pros or people with a big offering, but it&#8217;s not.</p>
<p>Making sure everyone knows about your new app or latest update is really important. I have been in PR/Marketing for many years and have seen it all! The biggest mistake I see is developers forgetting to put a link back to their website or sitelet when talking about their app. In announcements and on social media it&#8217;s so important to make sure people can find you easily! Here are the 3 most essential steps you should take when announcing your app (or release) to the world.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5271 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2018/12/extra-extrawe-have-an-update.png" alt="" width="600" height="200" /></p>
<p><span id="more-4953"></span></p>
<p><strong>Step 1: Generate Buzz</strong></p>
<p>If your release has something interesting in it that customers or prospects might like or talk about, do what you can to generate buzz. The best thing to do is to create a preview trailer that can be shared on your website and social media. This can be done easily with inexpensive tools like iMovie’s trailer feature.</p>
<p>Don&#8217;t keep it a secret, people like to be informed &#8211; blog about the development process on your website if possible. Don&#8217;t start too early though, make sure you are at a point where you are fairly certain it will be shipped within the next few weeks.</p>
<p><strong>Step 2:</strong> <strong>Spread the Word</strong></p>
<p>Writing a good announcement is really important. It should communicate four primary things:</p>
<ol>
<li>Your name (or your company&#8217;s name)</li>
<li>The app&#8217;s name</li>
<li>The URL to find your app</li>
<li>The main point of your app</li>
</ol>
<p>All of these items should appear in in the first paragraph. If you have an announcement that goes into features, benefits and more, great. But keep in mind that the majority of your readers <strong>will not</strong> make it past the first paragraph. Get your main idea across early.</p>
<p>Know your audience: who is reading this announcement? Customize it to them and their goals. Are they your prospective users? Are they members of the media? Are they other developers? Speak their language. Keep it fun and have a sense of humor (if applicable), showcase your brand&#8217;s voice. People are generally more inclined to give you their attention if you keep it interesting.</p>
<p>Another thing to consider is where the announcement will be posted. It is good to have a list at the ready for when you are going to ship a release. It is important that you collected email addresses of people on your website and your customers so you can email them about the update, you can send it to bloggers, post it on complimentary forums, like the Xojo forum. See &#8220;<a href="https://forum.xojo.com/5423-how-to-get-your-announcements-posted">How To Get Your Announcement Posted</a>.&#8221; If you send it to me, it might make its way onto our social media feed or the Xojo newsletter.</p>
<p><strong>Step 3:</strong> <strong>Write A Press Release</strong></p>
<p>Press Releases should always be written in third person. A good model we like to follow is:</p>
<ol>
<li>Summary of your announcement (main idea) in the first paragraph, callout main new features and number of fixes/improvements.</li>
<li>Next paragraph should be an overview of your app itself. What is the value proposition? How is your app useful and to whom? What does your app make easier?</li>
<li>Quote from a CEO/developer/employee or customer (or both) are great things to include here. They can showcase how the important new features are useful or innovative and give real life examples to support your main idea.</li>
<li>Include bulleted list of important features of the release</li>
<li>Contact information &#8211; how to find your app and yourself.</li>
</ol>
<p>What to do with it? We recommend compiling your own media list of writers who have written about your subject before. You can submit news on tons of websites. Also, you can submit your press release on relevant newswires, like PR Newswire or prMac. Don&#8217;t forget to post it on your own website!</p>
<p>The marketing work is never done. It involves a lot of trial and error. But announcing your app is the first step &#8211; if people don&#8217;t know about it, then what is the point? Hopefully these tips will help you write better announcements and develop your own process for announcing releases.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Name Your App</title>
		<link>https://blog.xojo.com/2018/07/25/name-your-app/</link>
		
		<dc:creator><![CDATA[Dana Brown]]></dc:creator>
		<pubDate>Wed, 25 Jul 2018 10:00:27 +0000</pubDate>
				<category><![CDATA[Dev Marketing]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[App Marketing]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Social Media Marketing]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4559</guid>

					<description><![CDATA[There’s a lot of thought that goes into picking the best name for your app. The ideal name sets the right tone, clarifies the purpose, and makes it easy to rank and market your app. Here are key strategies that help you get started.]]></description>
										<content:encoded><![CDATA[<p class="p1"><span class="s1">Naming your app may seem like the last step and the easiest part of the process, but it actually should involve some careful thought and consideration. A name needs to set the right tone for your app, should relate to it in some way, and should be searchable, meaning something that can be found easily in search engines. For example, you don’t want to name your app TravelTips &#8211; there are thousands of google searches that will come up before your app. You want a name you can own. </span></p>
<p class="p1"><span class="s1">When we changed our name from Real Studio to Xojo, we wanted to make sure we could find a name that we could own. Not only was Xojo a pretty wide open space in terms of search, but it also stands for something that describes what Xojo is &#8211; X is for Cross-platform and “OJO” is for Object-Oriented.</span></p>
<p><span id="more-4559"></span></p>
<p class="p1"><span class="s1"><b>Be Your Own App Name Generator</b></span></p>
<p class="p1"><span class="s1">It’s never too early to start the process. Your name might morph or change several times during the process, so the more time you have to think about it, the better.<span class="Apple-converted-space"> </span>All you need is pencil &amp; paper (or a notes app) and some time to start brainstorming. Start your list by answering the following questions.</span></p>
<ol class="ol1">
<li class="li1"><span class="s1">What is the main purpose of your app?</span></li>
<li class="li1"><span class="s1">Who is the target audience?</span></li>
<li class="li1"><span class="s1">What’s the value proposition?</span></li>
</ol>
<p class="p1"><span class="s1">Write down every word that comes to mind. When you’re done, you have a great bank of words to brainstorm with.</span></p>
<p class="p1"><span class="s1"><b>First Impressions Really Do Matter</b></span></p>
<p class="p1"><span class="s1">They say don’t judge a book by the cover, but … we do. We are more attracted to things that catch our eye. The name of your app and the icon are the first interaction a prospect user has with your app, it’s sort of like its book cover, it’s what makes people stop and think, “Oooh this is nice&#8230; Is this app right for me?”</span></p>
<p class="p1"><span class="s1">While reviewing your list of words, start thinking about images and emotions that will resonate with your audience. Conduct some research to find descriptive words and imagery that correlate to your app, ask your friends, get input from potential users.</span></p>
<p class="p1"><span class="s1">Pro tip: <i>Make sure you research the meanings and different connotations of your words to make sure they make sense for your intended audience. Avoid words that evoke negative emotions. </i></span></p>
<p class="p1"><span class="s1"><b>Make It Recognizable</b></span></p>
<p class="p1"><span class="s1">Try to find a name that might reveal the literal purpose of your app. In general, when a user can understand the point of your app just by the icon and name, they’re more successful. Names like Evernote and GrubHub are good examples of this. They are short and catchy, but also describe exactly what the app is or does. If your app can’t really be summarized, make sure the icon clearly and visually describes its purpose so they work together to catch the prospective user. Instagram is a good example of this &#8211; the name does not necessarily describe what it does, but coupled with it’s camera icon, it conveys the purpose of the app, that it has something to do with photos. App stores also give preference to names that are not totally arbitrary and appropriately describe the apps purpose.</span></p>
<p class="p1"><span class="s1">Pro tip: <i>If you are trying to put two words together that need to be pronounced separately (example &#8211; Instagram vs. GrubHub), it is recommended to use camel case, rather than all caps.</i></span></p>
<p class="p1"><span class="s1">Though you do want to use words that describe your app, make sure you aren’t <a href="https://support.google.com/webmasters/answer/66358?hl=en">keyword stuffing</a>. Picking applicable, even high traffic keywords, to go in your title is a good thing, but too many or too much repetition actually detracts from your preference and ranking. <a href="https://adwords.google.com/home/resources/using-google-adwords-keyword-planner.html#?modal_active=none">Google Keyword Planner</a> is a great free tool to start your keyword search.</span></p>
<p class="p1"><span class="s1">Its common for consumers to download an app just because it sounds interesting or fun, so try to find a name and design to make your app stand out.</span></p>
<p class="p1"><span class="s1"><b>Do Market Research</b></span></p>
<p class="p1"><span class="s1">Don’t forget to check out your competition. See what others are doing, without duplicating their name or icon, of course. Identify what emotions their name and icon emote, are the words you use to describe them the same as what is on your list? Is there something you missed that you might want to add? Maybe you might see something that really works you want to try to incorporate into yours, maybe you’ll see some things that really don’t work, like a specific icon, word or color palette. But, make sure to differentiate your app from the rest. Your app could be outright rejected from an App Store if the name is too similar to other apps that are already there.</span></p>
<p class="p1"><span class="s1">Pro tip: <i>Make sure the name you choose is not <a href="https://www.uspto.gov/trademarks-application-process/search-trademark-database">trademarked</a> by anyone else.</i></span></p>
<p class="p1"><span class="s1"><b>Other Considerations</b></span></p>
<p class="p1"><span class="s1">In searching for your name, take a look to see if you can also get a reasonable domain and and social media account. If the name of your app is not available as a domain, don’t discount it, there are variations you can consider for your name (like <a href="http://GoXojo.com"><span class="s2">GoXojo.com</span></a> or <a href="http://XojoApp.com"><span class="s2">XojoApp.com</span></a>). </span></p>
<p class="p1"><span class="s1">There’s a lot of thought that goes into picking the best name for your app. These strategies only just scratch the surface. The ideal name sets the right tone, clarifies the purpose, and makes it easy to rank and market your app. </span></p>
<p class="p1"><span class="s1">Good luck with your name-storming!</span></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>More Important Than Ever: Cross-Platform&#8217;s History</title>
		<link>https://blog.xojo.com/2013/06/13/cross-platform-more-important-than-ever/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Thu, 13 Jun 2013 00:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[Citizen Developer]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<guid isPermaLink="false">http://blogtemp.xojo.com/2013/06/13/cross-platform-more-important-than-ever/</guid>

					<description><![CDATA[There was a time when many would have said the world is standardizing and the future means fewer and fewer platforms. Look at what happened. Cross-platform is now more important than ever.]]></description>
										<content:encoded><![CDATA[<p>There was a time when the idea of running the same code on different computers wasn&#8217;t even imagined. Programming languages were written specifically for a particular computer. And computers were purchased for very specific purposes so why would you even <em>want</em> to run a particular program on another type of computer?</p>
<p>It was the desktop computer revolution that changed that. By the mid-to-late 1980&#8217;s, there were more and more desktop computers and developers wanted to target all of them. Soon, however, Windows became so dominant that many developers chose to focus on that one OS. Some Mac developers, not wanting to miss out on the potentially enormous Windows market, either went to the trouble of writing two versions of their applications or used a tool/language that would allow them to target both Mac and Windows from a single code base. <strong>This was the beginning of cross-platform development.</strong></p>
<p>Recently, I was asked by tech blogger <a href="http://www.lockergnome.com/web/2013/06/11/start-programming-free-xojo/" target="_blank" rel="noopener">Chris Pirillo</a> if cross-platform was really important anymore. <strong>Cross-Platform is actually more important than ever.</strong> Why? First of all, while the Windows PC market is seeing flat or declining sales, Apple&#8217;s Mac marketshare is growing. We are seeing this at <a href="http://www.xojo.com">Xojo</a>. More and more Windows developers are coming to us because they can no longer ignore the Mac market. Linux is the predominant server OS. If you want to write server software that can run on some combination of Linux, Windows and OS X, you&#8217;ll want to be writing cross-platform code.</p>
<p><span id="more-30"></span></p>
<p><strong>What about the web?</strong> It&#8217;s just a single platform right? Well, not really. Web developers using what I call the assembly language of the web (HTML, CSS, JavaScript, PHP and AJAX) must deal with at least 4 different browsers (IE, Chrome, Firefox and Safari). In theory, these browsers all interpret HTML, CSS and JavaScript the same way but anyone who&#8217;s ever created a web app knows that&#8217;s unfortunately not the case. Ideally, a cross-platform development tool greatly reduces these sorts of differences for you.</p>
<p>If you&#8217;re developing mobile applications there&#8217;s a good chance you&#8217;ll want to support iOS and Android. This is yet another place where cross-platform is important.</p>
<p>Finally, there&#8217;s a very good chance you&#8217;ll want your code to run on several of these <em>types</em> of platforms. You may need a desktop, web and mobile version of your app. And you might even want the core business logic of your app to run on a server somewhere and be accessed by client-side apps runing on these very different platforms. So being able to write code that is transportable across not just operating systems but from the desktop to the server, to the web and mobile, is arguably more important than ever before.</p>
<p><strong>Our goal with Xojo has always been to abstract you from the details of these different operating systems, devices and computing platforms so you can focus on what makes your applications unique.</strong> Xojo provides you with a single <a title="Xojo, Programming Language" href="http://www.xojo.com" target="_blank" rel="noopener">programming language</a> and tool that allows you to target them all. Why should you have to learn different languages and tools? With Xojo, you can build for OS X, Windows and Linux. And you can build for the desktop, the server, the web and coming soon, mobile with iOS (<a href="http://www.xojo.com/blog/en/2014/12/ios-app-screenshots.php">Xojo iOS</a> was release in Xojo 2014r3 and Xojo Pi for Raspberry Pi was released in 2015). That&#8217;s cross-platform.</p>
<p>There are other tools that take short cuts with interpreted code, dependences on runtime libraries and by drawing all controls themselves. <strong>Xojo compiles to machine code, creates native apps and uses native controls so that your app takes on the look and feel of the target platform. That&#8217;s cross-platform.</strong></p>
<p>Xojo started out supporting just the Mac. Not OS X but its predecessor, Mac OS. Xojo supported the Motorola 68000 and PowerPC processors back then. Next we added support for Windows and the x86 processor followed by Linux. Later, when Apple made the jump to OS X, we were right there as well. Now we support the web. Through all of these transitions, Xojo users have been, for the most part, shielded from these changes. Moving their projects from platform to platform, from processor to processor, has been relatively painless for Xojo users. We will be adding another OS and processor later this year with iOS and the ARM processor. ARM opens up some interesting additional possiblities.</p>
<p>There was a time when many would have said the world is standardizing and the future means fewer and fewer platforms. Look at what happened. <a href="http://www.xojo.com" target="_blank" rel="noopener">Cross-platform</a> is now more important than ever.<!-- end HubSpot Call-to-Action Code --></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
