<?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>Sandboxing &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/sandboxing/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Tue, 11 Feb 2025 20:00:45 +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>Sandboxing, Hardened Runtime and Notarization arrives to the Xojo IDE</title>
		<link>https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:37:15 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[2024r4]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Hardened Runtime]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[Mac App Store]]></category>
		<category><![CDATA[Notarization]]></category>
		<category><![CDATA[Sandboxing]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13966</guid>

					<description><![CDATA[Starting with Xojo 2024r4 it is possible to apply Sandboxing, Hardened Runtime and Notarization on macOS apps built from the Xojo IDE on macOS and&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2024r4 it is possible to apply Sandboxing, Hardened Runtime and Notarization on macOS apps built from the Xojo IDE on macOS and Windows.</p>



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



<p>These new options are available in the Inspector Panel when selecting the Sign step available under Build Settings &gt; macOS.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img fetchpriority="high" decoding="async" width="604" height="626" src="https://blog.xojo.com/wp-content/uploads/2024/10/Sign-SandboxingOptions.png" alt="" class="wp-image-13967" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/Sign-SandboxingOptions.png 604w, https://blog.xojo.com/wp-content/uploads/2024/10/Sign-SandboxingOptions-289x300.png 289w" sizes="(max-width: 604px) 100vw, 604px" /></figure>
</div>


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



<p>In order to apply Sandboxing, Hardened Runtime and go through the Notarization process for your macOS app, you will need to make sure that the following is installed on your Mac:</p>



<ul class="wp-block-list">
<li>macOS 11.3 or later.</li>



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



<li>Apple Developer ID &#8211; 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 Internet connection.</li>
</ul>



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



<p>With the Sandboxing switch enabled, you can access the associated editor in order to enable the appropriate entitlements for the purposes of the app.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="1012" height="1252" src="https://blog.xojo.com/wp-content/uploads/2024/10/Sandboxing-Editor.png" alt="" class="wp-image-13968" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/Sandboxing-Editor.png 1012w, https://blog.xojo.com/wp-content/uploads/2024/10/Sandboxing-Editor-242x300.png 242w, https://blog.xojo.com/wp-content/uploads/2024/10/Sandboxing-Editor-828x1024.png 828w, https://blog.xojo.com/wp-content/uploads/2024/10/Sandboxing-Editor-768x950.png 768w" sizes="(max-width: 1012px) 100vw, 1012px" /></figure>
</div>


<p>The Sandboxing settings will be applied even when the app is run from the IDE (debug mode). That means that Sandboxing can be applied both using an Ad-Hoc Certificate or the user Developer ID Application Certificate.</p>



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



<p>When the Hardened Runtime switch is enabled, you will be able to access the associated editor in order to set the appropriate hardening entitlements for the purposes of the app.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="1140" height="1400" src="https://blog.xojo.com/wp-content/uploads/2024/10/HardenedRuntime-Editor.png" alt="" class="wp-image-13969" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/HardenedRuntime-Editor.png 1140w, https://blog.xojo.com/wp-content/uploads/2024/10/HardenedRuntime-Editor-244x300.png 244w, https://blog.xojo.com/wp-content/uploads/2024/10/HardenedRuntime-Editor-834x1024.png 834w, https://blog.xojo.com/wp-content/uploads/2024/10/HardenedRuntime-Editor-768x943.png 768w" sizes="(max-width: 1140px) 100vw, 1140px" /></figure>
</div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> The Hardened Runtime will not be applied when the project is run from the IDE.</p>
</blockquote>



<p>When building the app, if Hardened Runtime is enabled and no Developer ID Application value is entered in the Developer ID field (that is, signed as ad-hoc), then the following dialog will be shown and the build process will stop.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="744" height="688" src="https://blog.xojo.com/wp-content/uploads/2024/10/MissingDeveloperID.png" alt="" class="wp-image-13970" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/MissingDeveloperID.png 744w, https://blog.xojo.com/wp-content/uploads/2024/10/MissingDeveloperID-300x277.png 300w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>
</div>


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



<p>When the Notarization switch is enabled, it will automatically enable the Hardened Runtime Switch if it is not already enabled (because the Notarization process requires Hardened Runtime!).</p>



<p>With the Notarization switch enabled, you will be able to access the Setup dialog in order to setup the app-specific password required by this process to properly work. Creating this password only needs to be done one time, because it will be saved to the computer keychain and even synced via iCloud to others Macs from the same user (that is, iCloud account).</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1524" height="792" src="https://blog.xojo.com/wp-content/uploads/2024/10/App-PasswordSetup.png" alt="" class="wp-image-13971" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/App-PasswordSetup.png 1524w, https://blog.xojo.com/wp-content/uploads/2024/10/App-PasswordSetup-300x156.png 300w, https://blog.xojo.com/wp-content/uploads/2024/10/App-PasswordSetup-1024x532.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/10/App-PasswordSetup-768x399.png 768w" sizes="auto, (max-width: 1524px) 100vw, 1524px" /></figure>
</div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> As with the Hardened Runtime feature, the Notarization process will not take place if the project is run from the IDE.</p>
</blockquote>



<p>When building the app, if Notarization is enabled and no Apple Development value is entered in the Developer ID field, then the following dialog will be shown and the build process will stop.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="744" height="688" src="https://blog.xojo.com/wp-content/uploads/2024/10/MissingDeveloperID-1.png" alt="" class="wp-image-13972" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/MissingDeveloperID-1.png 744w, https://blog.xojo.com/wp-content/uploads/2024/10/MissingDeveloperID-1-300x277.png 300w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>
</div>


<p>The Notarization process does require an active network connection to the Internet because it needs to talk with the Apple Service responsible of checking the app bundle contents. This means that the required time to complete the process will vary depending of your Internet connection speed and the load or availability of the Apple Notarization service itself.</p>



<h2 class="wp-block-heading">Custom User Entitlements</h2>



<p>Besides the entitlements you may have selected in the Sandboxing and Hardened Runtime editors, you may need to add other ones not available in these editors. This is something you can do through the User Entitlements field (.Plist file format). Such custom entitlements will be merged with the ones selected in the editors. If the custom entitlements entries collide with the ones selected in the editors, then the ones from the editors will be applied, discarding the duplicated ones found in the provided file.</p>



<h2 class="wp-block-heading">Building macOS apps… from Windows</h2>



<p>When the macOS app is built from Windows, and Sandboxing, Hardened Runtime or Notarization is applied (and optionally custom entitlements), then the final compressed archive will include all the required supporting files including the shell script required to run from a macOS computer to complete the signing process using the provided Apple Developer certificate (except the option to create an App-specific password for the Notarization step, because that can&#8217;t be done from Windows).</p>



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



<p>As you can see, Xojo 2024r4 streamlines the ability to apply Sandboxing, Hardened Runtime and Notarization to your macOS apps, and even run them as sandboxed from the IDE, so you can get better feedback during the debugging process to everything related with the access to files, network user, camera access, etc. That is, the same behaviour your users will have once they run the app downloaded from the Mac App Store or from your website.</p>



<p>See detailed steps in the <a href="https://documentation.xojo.com/topics/application_deployment/desktop/macos.html">Xojo Documentation</a>. If you need to know about what Sandboxing, Hardened Runtime or Notarization means, please take a look to the &#8220;<a href="https://blog.xojo.com/2024/08/22/macos-apps-from-sandboxing-to-notarization-the-basics/">macOS Apps: From Sandboxing to Notarization, The Basics</a>&#8221; blog post.</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>Xojo 2024r4 is Now Available!</title>
		<link>https://blog.xojo.com/2024/12/10/xojo-2024r4-is-now-available/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:36:12 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r4]]></category>
		<category><![CDATA[App Localization]]></category>
		<category><![CDATA[Charts]]></category>
		<category><![CDATA[Code Editor]]></category>
		<category><![CDATA[Hardened Runtime]]></category>
		<category><![CDATA[Notarization]]></category>
		<category><![CDATA[Preemptive Threads]]></category>
		<category><![CDATA[Sandboxing]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14183</guid>

					<description><![CDATA[Xojo 2024 Release 4 introduces a suite of powerful new features and enhancements, along with numerous bug fixes, further solidifying Xojo’s commitment to providing a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2024 Release 4 introduces a suite of powerful new features and enhancements, along with numerous bug fixes, further solidifying Xojo’s commitment to providing a robust and versatile development environment. With 33 new features added and 182 bugs fixed, Xojo 2024r4 is designed to enhance your productivity and expand your creative possibilities.</p>



<h2 class="wp-block-heading">What’s New in Xojo 2024r4</h2>



<p>Xojo 2024r4 brings a range of exciting updates that enhance cross-platform development, improve security, and provide more tools for creating dynamic and interactive applications. Here are some of the standout features:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Android Localization</strong></p>



<p>Expand your app’s reach with comprehensive localization support for Android. Easily add translations and switch locales using the intuitive Constant Editor, allowing you to cater to a diverse, global audience without the hassle.</p>



<p><a href="https://blog.xojo.com/2024/12/10/android-localization/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/android-localization/" target="_blank" rel="noreferrer noopener">Learn more about Android Localization</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Extended Android Features</strong></p>



<p>We&#8217;ve enhanced Android support by integrating several standard Xojo language features, including Structures, ByRef parameters, Operator_Lookup, and Operator_Convert.</p>



<p><a href="https://blog.xojo.com/2024/12/10/android-language-features/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/android-language-features/" target="_blank" rel="noreferrer noopener">Discover the Extended Android Features</a></p>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Selection Matching</strong></p>



<p>Boost your coding efficiency with the new Selection Matching feature in Xojo&#8217;s Code Editor. Quickly highlight and track all occurrences of selected text in your code, making it easier to navigate, refactor, and maintain your projects.</p>



<p><a href="https://blog.xojo.com/2024/12/10/code-editor-selection-matching/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/code-editor-selection-matching/" target="_blank" rel="noreferrer noopener">Learn more about Code Selection Matching</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Secure Mac Apps</strong></p>



<p>Enhance the security of your Mac applications directly from the Xojo IDE with built-in support for Sandboxing, Hardened Runtime, and Notarization. These features ensure your apps meet the latest security standards, providing a safe and trusted experience for your users.</p>



<p><a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" data-type="link" data-id="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/" target="_blank" rel="noreferrer noopener">Learn more</a></p>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Enhanced Charts</strong></p>



<p>Take control of your data visualization with Enhanced Charts. Gain precise control over DataSets and legends, and design dynamic, interactive charts using new event handlers and properties. These improvements make it easier to create visually compelling and informative charts for your applications.</p>



<p><a href="https://blog.xojo.com/2024/12/10/more-control-over-your-charts/" target="_blank" rel="noreferrer noopener">Read about the enhanced Charts</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p><strong>Preemptive Threads</strong></p>



<p>Experience faster execution, better debugging, and smarter object handling with the enhanced Preemptive Threads. This feature maximizes your application’s performance on multi-core systems, allowing for more responsive and efficient code.</p>



<p><a href="https://blog.xojo.com/2024/12/10/sharpening-our-preemptive-threads/" target="_blank" rel="noreferrer noopener">Understand Preemptive Threads</a></p>
</div>
</div>



<p><strong>Web Framework</strong><br>Enjoy smoother and more efficient web applications with updates to Xojo&#8217;s Web Framework. Improved memory usage and numerous bug fixes ensure that your web apps run reliably and perform optimally, providing a better experience for your users.</p>



<p><a href="https://blog.xojo.com/2024/12/10/xojo-web-improvements-in-2024r4/" target="_blank" rel="noreferrer noopener">Discover Web Framework Improvements</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>These updates and enhancements are designed to make your development process more efficient, productive, and enjoyable. Whether you’re building new applications or enhancing existing ones, Xojo 2024r4 provides the tools and capabilities you need to succeed.</p>



<h2 class="wp-block-heading">Get Started</h2>



<p>To learn more about Xojo 2024 Release 4 and begin your development journey, please visit the&nbsp;<a href="https://documentation.xojo.com/versions/2024r4/resources/release_notes/2024r4.html" target="_blank" rel="noreferrer noopener">Xojo 2024r4 Release Notes</a>. The update is available for download now from the&nbsp;<a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Xojo downloads page</a>.</p>



<h3 class="wp-block-heading">What’s Next?</h3>



<p>We’re continuously working on new features, updates, and enhancements to our platform. If you have any suggestions or ideas, please add them to the&nbsp;<a href="https://tracker.xojo.com/xojoinc/xojo">Xojo tracker</a>. We’re always looking to improve and expand Xojo to better serve our community.</p>



<p><strong>Thank you for being part of the Xojo community. We’re excited to see what you create with Xojo 2024r4!</strong></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>
]]></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>In-App Purchases Tutorial on iOS</title>
		<link>https://blog.xojo.com/2019/12/19/in-app-purchases-tutorial-on-ios/</link>
		
		<dc:creator><![CDATA[Ryan Hartz]]></dc:creator>
		<pubDate>Thu, 19 Dec 2019 10:00:00 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Sandboxing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6323</guid>

					<description><![CDATA[This guide is going to walk you through the steps to set up in-app purchases in your iOS apps. It may be best to get&#8230;]]></description>
										<content:encoded><![CDATA[
<p>This guide is going to walk you through the steps to set up in-app purchases in your iOS apps. It may be best to get things set up first on Apple’s side, following with the app configurations in Xojo.</p>



<h3 class="wp-block-heading"><a href="http://developer.apple.com">Apple Developer</a></h3>



<ol class="wp-block-list"><li>Go into Certificates, Identifiers, &amp; Profiles.</li><li>Select Identifiers on the left.</li><li>Click the plus sign to add a new identifier.</li><li>Select App ID and hit Continue to Register an App ID.</li><li>Choose iOS under Platform, enter a Description, and enter an ExplicitBundle ID. This must be the same as your Xojo project’s Bundle Identifier. Make sure In-App Purchase is checked (it should be by default).</li><li>Click Continue, then click Register on the next screen after you verify the information.</li></ol>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="308" src="https://blog.xojo.com/wp-content/uploads/2019/12/1-Apple-dev-certs-1024x308.png" alt="" class="wp-image-6339" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/1-Apple-dev-certs-1024x308.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/12/1-Apple-dev-certs-300x90.png 300w, https://blog.xojo.com/wp-content/uploads/2019/12/1-Apple-dev-certs-768x231.png 768w, https://blog.xojo.com/wp-content/uploads/2019/12/1-Apple-dev-certs-1536x463.png 1536w, https://blog.xojo.com/wp-content/uploads/2019/12/1-Apple-dev-certs-2048x617.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ol class="wp-block-list" start="7"><li>Back in Certificates, Identifiers, &amp; Profiles, make sure you have a physical device listed. This will be used for the IAP test purchase since you cannot test a purchase in Simulator. </li><li>Select Devices on the left. If your device is not listed, click the plus sign to add it. </li><li>Select iOS as the Platform, enter in a name for the device, and enter in the Device ID (UDID). You get the UDID by connecting your phone to the computer, opening Xcode, choosing Window &gt;&gt; Devices and Simulators, right-click on your device listed on the left and select Copy Identifier. </li><li>Copy this into the UDID box in Apple Developer Register a Device.</li></ol>



<h3 class="wp-block-heading">iTunes Connect</h3>



<p>In the Agreements, Tax, and Banking section, make sure you have active agreements for Free Apps and Paid Apps. The process of getting these agreements set up can take a couple of days.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<p>Set up the new app:</p>



<ol class="wp-block-list"><li>Go to My Apps and create a new app using the plus sign on the left.</li><li>In the New App box that appears, check the box for iOS.</li><li>Enter a unique name for the app.</li><li>Choose the primary language.</li><li>Choose the Bundle ID created in Apple Developer.</li><li>Enter a SKU number.</li><li>Choose Full Access.</li></ol>
</div></div>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="977" height="1024" src="https://blog.xojo.com/wp-content/uploads/2019/12/2-ITC-new-app-977x1024.png" alt="" class="wp-image-6340" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/2-ITC-new-app-977x1024.png 977w, https://blog.xojo.com/wp-content/uploads/2019/12/2-ITC-new-app-286x300.png 286w, https://blog.xojo.com/wp-content/uploads/2019/12/2-ITC-new-app-768x805.png 768w, https://blog.xojo.com/wp-content/uploads/2019/12/2-ITC-new-app.png 1128w" sizes="auto, (max-width: 977px) 100vw, 977px" /></figure>



<p>To  set up the in-app purchase product select Features at the top, then In-App Purchases on the left. Click the plus sign next to the In-App Purchases and choose which IAP you are using in your app then click Create.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<p>There are 3 options when choosing which IAP is right for your app:</p>



<ul class="wp-block-list"><li>Consumable: Think of tokens to buy in a game. Once they’re spent, you need to buy more.</li><li>Non-Consumable: A one-time purchase to unlock a feature</li><li>Subscriptions: Auto-renewing or non-renewing</li></ul>
</div></div>



<p>Fill out the necessary data on the following screen:</p>



<ul class="wp-block-list"><li>Reference Name: This is a name that is not displayed to the user. It is only for your reference.</li><li>Product ID: Enter in the Bundle ID you made in Apple Developer but also include an end tag of the in-app purchase product name. For example, your Product ID might look like com.mycompany.myapp.myinappproduct.</li><li>Check the box for Cleared for Sale (this should be checked by default).</li><li>Choose a pricing tier.</li><li>Scroll down, under App Store Information enter in a Display Name and a Description. These will be shown to the user.</li><li>Scroll down to Review Information. You can include a screenshot of your app now or you can save your IAP product and add in a screenshot later. If you skip adding a screenshot, you will see a message saying Missing Metadata. This message will go away after you add a screenshot. The screenshot needs to be at least 640&#215;920, which is the size of the iPhone 5s. The screenshot I used is a display of my purchase view in the app. Not sure if that is what they expect, but the app and IAP got approved.</li></ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="393" src="https://blog.xojo.com/wp-content/uploads/2019/12/3-ITC-new-IAP-pt-1-1024x393.png" alt="" class="wp-image-6341" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/3-ITC-new-IAP-pt-1-1024x393.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/12/3-ITC-new-IAP-pt-1-300x115.png 300w, https://blog.xojo.com/wp-content/uploads/2019/12/3-ITC-new-IAP-pt-1-768x295.png 768w, https://blog.xojo.com/wp-content/uploads/2019/12/3-ITC-new-IAP-pt-1-1536x590.png 1536w, https://blog.xojo.com/wp-content/uploads/2019/12/3-ITC-new-IAP-pt-1-2048x787.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<p>Next set up your sandbox testers. Choose Users and Access from the top drop-down menu then select Testers on the left under Sandbox. Add at least one sandbox user for testing, preferably two or three so you can try a purchase more than once. Your sandbox user accounts cannot be tied to an Apple ID account. Use a personal email address for yourself that is not with Apple or make a new account in Gmail or Yahoo. After you create a sandbox user, you will need to verify the account in the email box you created, so it is best to create the email account first to make sure it hasn’t been taken.</p>
</div></div>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="640" src="https://blog.xojo.com/wp-content/uploads/2019/12/5-ITC-add-sandbox-user-1024x640.png" alt="" class="wp-image-6342" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/5-ITC-add-sandbox-user-1024x640.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/12/5-ITC-add-sandbox-user-300x188.png 300w, https://blog.xojo.com/wp-content/uploads/2019/12/5-ITC-add-sandbox-user-768x480.png 768w, https://blog.xojo.com/wp-content/uploads/2019/12/5-ITC-add-sandbox-user-1536x960.png 1536w, https://blog.xojo.com/wp-content/uploads/2019/12/5-ITC-add-sandbox-user.png 1782w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">Turn on In-App Purchases Xojo</h3>



<ol class="wp-block-list"><li>Under Build Settings in left panel, click iOS. </li><li>Then, in the Inspector, click the Entitlements (gear icon) and move the switch for In-App Purchases to on.</li></ol>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="427" src="https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.12-PM-1024x427.png" alt="" class="wp-image-6363" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.12-PM-1024x427.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.12-PM-300x125.png 300w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.12-PM-768x320.png 768w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.12-PM-1536x641.png 1536w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.12-PM-2048x854.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ol class="wp-block-list" start="3"><li>Include Jason King’s <a href="https://github.com/kingj5/iOSKit">iOSKit folder</a>. </li><li>In my sample project, I have a ModalPurchaseView to handle the purchase/restore pieces. If you want to activate this the same way, add to your project Jeremie Leroy’s <a href="https://github.com/jkleroy/iOSDesignExtensions">iOSExtensions</a> which has the method to call the modal in a neat way. The ModalPurchaseView from the sample project can be copied to your project and used to cover the purchase/restore functions. Be sure to change the pieces in the code that points to your in-app purchase product, such as com.mycompany.myapp.myIAPproduct</li><li>Build your app with all features, then choose which features you want to be included in your premium version. I have a boolean property ActivatePremium in Module1 to be set to true if the premium is purchased.</li></ol>



<h3 class="wp-block-heading">Testing the In-App Purchase</h3>



<p>You won’t be able to test the IAP in Simulator, so don’t even try. Instead, you will need to test on a physical device.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<ol class="wp-block-list"><li>Build the completed project in Xojo.</li><li>Connect your device to the computer and open Xcode.</li><li>In Xcode, select in the top menu Window &gt;&gt; Devices and Simulators.</li><li>Drag the app from your Builds folder to the bottom pane of the Devices and Simulators window in Xcode. It’s the one with that looks crossed out.</li></ol>
</div></div>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="848" height="668" src="https://blog.xojo.com/wp-content/uploads/2019/12/8-XCode-add-app-to-device-1.png" alt="" class="wp-image-6348" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/8-XCode-add-app-to-device-1.png 848w, https://blog.xojo.com/wp-content/uploads/2019/12/8-XCode-add-app-to-device-1-300x236.png 300w, https://blog.xojo.com/wp-content/uploads/2019/12/8-XCode-add-app-to-device-1-768x605.png 768w" sizes="auto, (max-width: 848px) 100vw, 848px" /></figure></div>



<ol class="wp-block-list" start="5"><li>You will need to sign out of your Apple ID on your device. In the Settings of your device, go into the iTunes &amp; App Store section, click your Apple ID at the top, then click Sign Out.</li></ol>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="206" height="300" src="https://blog.xojo.com/wp-content/uploads/2019/12/9-Device-settings-sign-out.png" alt="" class="wp-image-6349"/></figure></div>



<ol class="wp-block-list" start="6"><li>Open your app and click the Purchase option. You will be asked to sign in. Sign in with your sandbox account you created. After you sign in, you should see a Confirm Purchase [Sandbox Environment] box. Enter in your password and see what happens.</li></ol>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="496" src="https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.22-PM-1024x496.png" alt="" class="wp-image-6364" srcset="https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.22-PM-1024x496.png 1024w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.22-PM-300x145.png 300w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.22-PM-768x372.png 768w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.22-PM-1536x743.png 1536w, https://blog.xojo.com/wp-content/uploads/2019/12/Screen-Shot-2019-12-13-at-4.12.22-PM.png 1872w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div></div>
</div></div>



<ol class="wp-block-list" start="7"><li>If you need to test it again, go back into Settings &gt;&gt; iTunes and App Store, scroll to the bottom, and sign out of the sandbox test account. Try with another account.</li><li>You should also test the Restore function of your IAP. It might be best to test this before testing a purchase to make sure you don’t end up getting the app for free without “purchasing”. When testing your Restore after purchasing, you will need to delete the app from the device and add it back through the Xcode method above in steps 2 through 4.</li></ol>



<p>Credit to Jason King for creating iOSKit and to Jeremie Leroy for his personalized help with helping me get my first iOS app with in-app purchases off the ground. I hope you found this tutorial useful. You can download the project <a href="http://files.xojo.com/Documentation/SampleProjects/My%20IAP%20Sample.xojo_binary_project">here</a>. </p>



<p><em>Ryan Hartz has been a Xojo user for over 10 years.  He is a registered dietitian with no formal education in software development, illustrating that anyone can learn development in Xojo with its ease of use and understandable language.  In 2005, Ryan started his company, <a href="https://visualveggies.com/">Visual Veggies Software</a>, which offers software study guides to young nutrition students preparing to become registered dietitians.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Guest Post: Solving Sandboxing Issues and Improving Xojo Apps With Ohanaware&#8217;s Sandbox Kit</title>
		<link>https://blog.xojo.com/2015/02/18/guest-post-solving-sandboxing-issues-and-improving-xojo-apps-with-ohanawares-sandbox-kit/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Wed, 18 Feb 2015 00:00:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Ohanaware]]></category>
		<category><![CDATA[Sandboxing]]></category>
		<guid isPermaLink="false">http://blogtemp.xojo.com/2015/02/18/guest-post-solving-sandboxing-issues-and-improving-xojo-apps-with-ohanawares-sandbox-kit/</guid>

					<description><![CDATA[If you want to sell an app in the Mac App Store, the app must adopt the App Sandbox security. Trying to figure out solutions to these new issues often results in much head scratching and consulting with other developers via the Xojo Forums. In this post, I'm going to cover a few Sandboxing issues and how to resolve them with the tools / code that I've built for the apps that we sell.]]></description>
										<content:encoded><![CDATA[<p><em>Sam Rowlands has been developing Xojo apps since 1997. He and his wife, Joy Sha, make up <a href="http://www.ohanaware.com">Ohanaware</a> and they have been building award winning apps since 2008, notably Funtastic Photos, HDRtist and <a href="http://xojo.com/community/casestudies/shine.php">Shine</a>. Sam is an active Xojo developer and he also offers App Wrapper, which simplifies the process of preparing applications for submission to the Mac App Store and deploying on web sites, in the Xojo Third Party Store.</em></p>
<h2><span style="font-size: 20px;"><strong>What is the App Sandbox and why is it a chore?</strong></span></h2>
<p>The App Sandbox is a great end user security concept. The Sandbox governs what an application can and cannot do. This means that a virally infected word processor, cannot go on to infect other applications nor rampantly damage files on the users disk. It can however affect files which the user has created or opened within the word processor.</p>
<p><span id="more-185"></span></p>
<p>The developers&#8217; pain comes from the App Sandbox&#8217;s greatest strength. The app developer must perform additional work, just to reclaim functionality that the App Sandbox took away. If you want to sell an app in the Mac App Store, the app must adopt the App Sandbox security.</p>
<p><strong>Note</strong>: There are some functions which simply cannot be done within a Sandboxed application.</p>
<p>Trying to figure out solutions to these new issues often results in much head scratching and consulting with other developers via the Xojo Forums. I&#8217;ve seen some really creative solutions to reclaim features when using this security mechanism. In this post, I&#8217;m going to cover a few Sandboxing issues and how to resolve them with the tools / code that I&#8217;ve built for the apps that we sell.</p>
<h2><span style="font-size: 20px;"><strong>Chocks away&#8230;</strong></span></h2>
<p>Taking my latest, greatest app, which just so happens to be a really cool Text Editor built with Xojo.</p>
<p>1. If I simply Sandbox the application (using App Wrapper 3, with just the minimum), I can create new documents, but I can&#8217;t save or even open documents.</p>
<p>2. The Recent Items menu no longer works.</p>
<p>3. I personally like apps that re-open the last documents I was working on. The same issue persists, code that used to work, no longer does.</p>
<p>4. Even more scary, is that users can&#8217;t even print- what kind of text editor can&#8217;t print?</p>
<h3><strong>Problems 1 and 4</strong></h3>
<p>We&#8217;ll start with the simplest, problems #1 &amp; #4 are easily resolved with the options (&#8220;Open &amp; Save Panels&#8221; &amp; &#8220;Printer&#8221;) on the &#8220;Capabilities&#8221; panel within App Wrapper.</p>
<p><a href="http://www.xojo.com/blog/en/assets_c/2015/02/Screenshot%201%20-%20App%20Wrapper%20Settings-574.php"><img loading="lazy" decoding="async" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" src="https://blog.xojo.com/wp-content/uploads/2015/02/screenshot20120-20app20wrapper20settings-thumb-400x323-574.pngt1466486449161ampwidth400ampheight323" sizes="auto, (max-width: 400px) 100vw, 400px" alt="Screenshot 1 - App Wrapper Settings.png" width="400" height="323" /></a><strong>Note</strong>: There appears to be a new issue with Yosemite, I&#8217;m not 100% certain of the cause, but it seemed that changing the case of the application&#8217;s bundle identifier solved it. So &#8220;com.ohanaware.mytexteditor&#8221; doesn&#8217;t work, where as &#8220;com.ohanaware.myTextEditor&#8221; does.</p>
<h3><strong>Problem 2: Recent Items list</strong></h3>
<p>In order to solve problem 2, we&#8217;ll use the &#8220;OWRecentItems&#8221; class from the Sandbox Kit. It&#8217;s a little more complicated than just selecting checkboxes, but not much more complicated.</p>
<p>Add the Sandbox Kit to your Xojo project.</p>
<p>In the &#8220;Open&#8221; event of the &#8220;App&#8221; object, add the following line of code</p>
<pre>OWRecentItems.installRecentMenu( fileMenu, 1 )</pre>
<p>This single line of code will tell the OWRecentItems class to install the recent menu, you pass in the menu on the to add to, and where in the menubar you&#8217;d like the &#8220;Open Recent&#8221; submenu to appear.</p>
<p><a href="http://www.xojo.com/blog/en/assets_c/2015/02/Screenshot%202%20-%20Code%20%26%20Recent%20Menu%20items-577.php"><img loading="lazy" decoding="async" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" src="https://blog.xojo.com/wp-content/uploads/2015/02/screenshot20220-20code202620recent20menu20items-thumb-400x198-577.pngt1466486449161ampwidth400ampheight198" sizes="auto, (max-width: 400px) 100vw, 400px" alt="Screenshot 2 - Code &amp; Recent Menu items.png" width="400" height="198" /></a></p>
<p>For my Text Editor, I added it to the file menu and in position 2.</p>
<p>3. Now all that&#8217;s required is when a document is saved or opened, another line of code needs to be called.</p>
<pre>OWRecentItems.addToRecentMenu( file )</pre>
<p>Simply call the OWRecentItems class again and use the addToRecentMenu method, passing in the Xojo folderitem where the document is being saved. It will be added to the Recent Menu (it&#8217;s okay to call it multiple times as it will only list it once).</p>
<p>That&#8217;s it. Now the application has a Sandbox safe recent items menu.</p>
<p><strong>Note</strong>: Using this code will also add the Recent Item menu to the App&#8217;s dock item. It&#8217;s also pretty cool in the fact that the Apple Recent Item system work across Sandboxed and un-sandboxed versions.</p>
<h3><strong>Problem 3: Re-opening last open documents</strong></h3>
<p>There&#8217;s a bit more work involved to implement this solution, the great news is once you&#8217;ve mastered it for one window, it&#8217;s trivial to add to other windows.</p>
<p>1. In your Xojo application, you need to select your document window and click on the &#8220;Choose&#8221; button next to &#8220;Interfaces&#8221; in the Xojo inspector.</p>
<p><a href="http://www.xojo.com/blog/en/assets_c/2015/02/Screenshot%203%20-%20Interface%20selector-580.php"><img loading="lazy" decoding="async" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" src="https://blog.xojo.com/wp-content/uploads/2015/02/screenshot20320-20interface20selector-thumb-400x233-580.pngt1466486449161ampwidth400ampheight233" sizes="auto, (max-width: 400px) 100vw, 400px" alt="Screenshot 3 - Interface selector.png" width="400" height="233" /></a></p>
<p>2. Some new methods will be added to the Window class.</p>
<ul>
<li>classIdentifer as string</li>
<li>restoreData( data as JSONItem )</li>
<li>storeData as JSONItem</li>
</ul>
<p>&#8220;classIdentifer&#8221; is where we return a identifier, to which our restoration service uses to determine what window instance to create when the data is restored. I tend to return the window class name.</p>
<pre>Function classIdentifier() As string
  // Part of the OWRestorableWindow interface.
  return "documentWindow"
End Function</pre>
<p>&#8220;restoreData&#8221; is used to populate the controls when restoring the window. For our word processor, we&#8217;ll use the code below.</p>
<pre>Sub restoreData(data as JSONItem)
  // Part of the OWRestorableWindow interface.
  if data &lt;&gt; nil then
    if data.hasName( "text" ) then TextArea1.text = data.value( "text" )
  end if
End Sub</pre>
<p>It&#8217;s important to check that the data object isn&#8217;t NIL and also to check for each setting (this will help to future proof your application).</p>
<p>&#8220;storeData&#8221; is the last method to populate in the Window class. For our purposes we&#8217;ll use the following code. It will simply store the TextArea into the property &#8220;text&#8221;.</p>
<p><strong>Note</strong>: As we&#8217;re using JSONItems to save and restore the data, it&#8217;s not designed to contain vast amounts of data and some data types will need to be converted to text before storing.</p>
<pre>Function storeData() As JSONItem
  // Part of the OWRestorableWindow interface.
  if me.folderitem &lt;&gt; nil then call saveFile
  Dim r as new JSONItem
  if textArea1.text &lt;&gt; "" then r.value( "text" ) = textArea1.text
  Return r
End Function</pre>
<p>It&#8217;s important to know that if you&#8217;re writing Auto Save files, this is the place to do so. Once Window Restoration is properly configured, the window will never receive the &#8220;CancelClose&#8221; or &#8220;Close&#8221; events. Consider this the last place to save the user data.</p>
<p>Modify the Save routine of the window, to store the file into the Window, this is done by using the window.folderitem property.</p>
<pre>me.folderitem = f</pre>
<p><strong>Note</strong>: This is one of the key elements, without this the Window Restoration will not work correctly. The folderitem must be attached to the Window using this method.</p>
<p>Modify your file open routine to also use this property.</p>
<p>3. Now we need to alter the App object.<br />
In the &#8220;CancelClose&#8221; event of the &#8220;App&#8221; Object, add the code to store the open windows.</p>
<pre>Function CancelClose() As Boolean
<strong>OWWindowRestoration.storeOpenWindows</strong>
End Function</pre>
<p><strong>Note</strong>: Once this line is executed, no more code will be executed after it, nor will the application&#8217;s &#8220;Close&#8221;, window &#8220;CancelClose&#8221; and &#8220;Close&#8221; events will not fire.</p>
<p>4. The next step is to create a subclass of the &#8220;OWWindowRestoration&#8221; class, name this class something appropriate (for &#8220;My Text Editor&#8221;, I used the name &#8220;MTERestoration&#8221; ).</p>
<p>Add the event &#8220;windowByClassIdentifier&#8221; and in here is where we create a new instance of our window when requested. Earlier on, I returned &#8220;documentWindow&#8221; from the Window&#8217;s classIdentifer method.</p>
<pre>Function windowByClassIdentifier(classIdentifier as string) As window
  select case classIdentifier
  case "documentWindow"
    return new documentWindow
  end select
End Function</pre>
<p>5. Back to the &#8220;Open&#8221; event of the &#8220;App&#8221; and we ask our subclass to restore windows. For example, this app uses the following code.</p>
<pre>Sub Open()
  // --- Initiate the Recent Items Menu.
  OWRecentItems.installRecentMenu( fileMenu, 2 )
  // --- Initate Window Restoration.
<strong>  Dim nwrc as new MTERestoration
</strong>End Sub</pre>
<p>In order to test this, make sure that &#8220;Close windows when quitting an app&#8221; is unchecked, in the &#8220;General&#8221; section of &#8220;System Preferences&#8221;.</p>
<p>Now run the application, leave some windows open, quit the application and re-launch it&#8230;</p>
<p>6. Cleaning up<br />
In the final step, we need to restore window positions for files that were auto re-loaded (not just data that is stored). This is done by adding the following line to your file open routine.</p>
<pre>OWWindowRestoration.restoreWindowBounds( myNewWindow, fileToOpen )</pre>
<p>Replace &#8220;MyNewWindow&#8221; with the new instance of your window and &#8220;fileToOpen&#8221; with the file that was opened by the routine. Below is how it&#8217;s used in &#8220;My Text Editor&#8221;.</p>
<pre>Sub OpenDocument(item As FolderItem)
  Dim theText as string
  try
    Dim tis as textInputStream = textInputStream.open( item )
    if tis &lt;&gt; nil then
      theText = tis.readAll
      tis.close
      Dim ndw as new documentWindow
      ndw.TextArea1.text = theText
      ndw.contentsChanged = false
      ndw.folderitem = item
      OWRecentItems.addToRecentMenu( item )
<strong>      OWWindowRestoration.restoreWindowBounds( ndw, item )
</strong>      ndw.show
    end if
  catch err as IOException
    MsgBox "Unable to open the file """ + item.name + """." + EndOfLine + endOfLine + err.message
  End try
End Sub</pre>
<p>You may have noticed that your Xojo application is also creating new blank windows, which may be undesirable. This is can be solved by adding a property to the &#8220;App&#8221; class, name it &#8220;blockFirstNewWindow&#8221; and make it a boolean. Update the &#8220;NewDocument&#8221; event to use this new property.</p>
<pre>Sub NewDocument()
  if blockFirstNewWindow = false then
    Dim ndw as new documentWindow
    ndw.show
  else
    blockFirstNewWindow = false
  end if
End Sub</pre>
<p>Switch back to the &#8220;Open&#8221; event and add a line of code to set that property to the result of the window restoration code.</p>
<pre>Sub Open()
  // --- Initiate the Recent Items Menu.
  OWRecentItems.installRecentMenu( fileMenu, 2 )
  // --- Initate Window Restoration.
  Dim nwrc as new MTERestoration
<strong>  blockFirstNewWindow = nwrc.restored
</strong>End Sub</pre>
<p>Now, if you run the project, create some documents, open some, save others, then quit and re-launch, your app should restore the open documents as they were when the application was quit.</p>
<h2><strong>Benefits of using this code</strong></h2>
<p>Apart from solving some App Sandbox issues, you&#8217;ll also get some additional functionality for free.</p>
<ul>
<li>Using the Apple Recent Item system, recent documents are also available from the dock menu.</li>
<li>The Apple Recent Item system is compatible with both the Sandboxed application and unsandboxed (while everything else is not). Users of either version can swap between the two and still be able to use the Recent Items.</li>
<li>Using the Window Restoration system will make an application follow and behave more consistently with other applications.</li>
<li>The Window Restoration system will also add the file icon to the Window titlebar, and if the user control clicks on the file icon, they can see where on the disk the file is located.</li>
</ul>
<h2><strong>What&#8217;s included in the Sandbox Kit</strong></h2>
<ul>
<li>OWRecentItems; Used to implement a Sandbox Safe Recent Items menu</li>
<li>OWWindowRestoration; The Window Restoration handler</li>
<li>OWRestorableWindow; A Class Interface adding the functions for Window Restoration</li>
<li>OW_Sandbox_Kit; A shared module that the Sandbox Kit object require</li>
<li>OWAppleScript; The preferred method of executing Apple Scripts from within a Sandboxed application</li>
<li>OWBookmark; A last resort function for storing references to files, use this only if OWRecentItems &amp; OWWindowRestoration cannot solve the issue</li>
<li>SSBToken; Used by the OWBookmark class to ensure access to a referenced file is closed properly</li>
<li>OWShell; A Shell subclass that can also use NSTask, the only way to launch embedded &#8220;Helper&#8221; applications within a Sandboxed application</li>
</ul>
<h2><strong>How to get the Sandbox Kit</strong></h2>
<p>The Sandbox Kit is sold via the <a href="http://www.ohanaware.com/sandboxkit/">Ohanaware web site</a> for $99.99.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
