<?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>Javier Menendez &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/author/javier/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, 31 Mar 2026 15:21:26 +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>Team-based Signing Arrives to macOS</title>
		<link>https://blog.xojo.com/2026/03/31/team-based-signing-arrives-to-macos/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:21:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15951</guid>

					<description><![CDATA[In Xojo 2026r1 we revised the macOS Developer ID field and replaced it with a Team-based popup menu that aligns with the style found in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In Xojo 2026r1 we revised the macOS Developer ID field and replaced it with a Team-based popup menu that aligns with the style found in iOS projects. This change aims to offer a cleaner, more intuitive way to manage developer certificates for the distribution of your built macOS app.</p>



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



<p>The Developer ID field was introduced in Xojo 2022r1, allowing you to fill in the developer certificate information needed for signing built macOS apps; however, it could be confusing to know exactly what information was expected.</p>



<ul class="wp-block-list">
<li>Developer ID Application</li>



<li>Developer ID Application: Francisco Javier Rodriguez Menendez</li>



<li>Developer ID Application: Francisco Javier Rodriguez Menendez (BW7PU32485)</li>



<li>7D767DB917A45A8976BEB5B92F04E8C18D09501A</li>
</ul>



<p>And… which certificate should be used for Development builds, Direct Distribution, or Mac App Store publishing? That may not be obvious for someone new to all this.</p>



<p>Additionally, what happens if the entered data comes from an expired certificate or if the certificate isn’t in the Keychain?</p>



<h2 class="wp-block-heading">The new approach: How it works</h2>



<p>The Team-based signing chooser for the Mac Developer ID field follows these steps:</p>



<ul class="wp-block-list">
<li><strong>Collects all the developer certificates</strong> found under the user Keychain.</li>



<li><strong>Groups the valid certificates by Team</strong> (what Apple designates as the TeamID).</li>



<li>Based on the previous information, the new popup menu &#8220;Build For&#8221; will offer only the code-signing options available for the current selected Team:
<ul class="wp-block-list">
<li><strong>Development</strong>. This is the equivalent to using the Apple Development certificate.</li>



<li><strong>Direct Distribution</strong>. This is the equivalent to using the Developer ID Application certificate.</li>



<li><strong>App Store</strong>. This is the equivalent to using the Apple Distribution certificate. In addition, the Publish feature will be enabled if, for the selected Team, there is also a valid 3rd‑party Mac Developer Installer certificate available.</li>
</ul>
</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img fetchpriority="high" decoding="async" width="600" height="540" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.28.02.png" alt="" class="wp-image-15962" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.28.02.png 600w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.28.02-300x270.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></figure>
</div>


<p>If None is selected in the Developer ID popup menu, the macOS app will be built/debugged using Ad-Hoc signing.</p>



<p>Both menus update on the fly, so if new certificates are added (or removed) from the keychain, or if any have expired since last opened, both the Developer ID and Build For popup menus will reflect those changes.</p>



<h2 class="wp-block-heading">macOS Certificates Inspector Window</h2>



<p>Under the Teams popup menu, there is also an Inspect… option. When selected, it opens a new window where you can view and gather additional information for:</p>



<ul class="wp-block-list">
<li>Installed / Missing Apple Intermediate Certificates.</li>



<li>Installed / Missing / Expired Developer Certificates, grouped by Team.</li>
</ul>



<p>At a glance, you’ll see useful details for each certificate, such as:</p>



<ul class="wp-block-list">
<li>The expiration date</li>



<li>The keychain where it is stored.</li>



<li>Serial number, useful for identifying same-kind developer / intermediate certificates under different Macs.</li>



<li>Issuer specific information.</li>
</ul>



<p>Clicking any certificate provides more detailed information about the role it plays in the macOS signing process.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="2522" height="1920" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21.png" alt="" class="wp-image-15963" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21.png 2522w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-1024x780.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-768x585.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-1536x1169.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-2048x1559.png 2048w" sizes="(max-width: 2522px) 100vw, 2522px" /></figure>
</div>


<p>This Inspector is also useful in order to identify some of the most common issues related with the handling of certificates such as:</p>



<ul class="wp-block-list">
<li><strong>Missing certificates for a given Team</strong>, determining thus the options that are available under the &#8220;Build For&#8221; popup menu.</li>



<li><strong>Expired certificates</strong>. These also determine the options that are available under the &#8220;Build For&#8221; popup menu for a given Team. In addition, if you want to do some cleanup, it is possible to delete these expired certificates directly from the Inspector without needing to open the Keychain Access app.</li>



<li><strong>About to expire certificates</strong>, so you are aware of it and the impact it could have on apps close to be distributed or on already created Provisioning Profiles, for example.</li>



<li><strong>Certificates with their private key missing</strong>. These can&#8217;t be used for signing purposes, so you will be able to re-install them in the keychain (if you have a backup) or install a new certificate.</li>



<li><strong>Developer Certificates where some of the required intermediate certificate is missing</strong>. You will be able to install the missing Intermediate (active Internet connection required).</li>
</ul>



<h2 class="wp-block-heading">Improvements to macOS Builds and Debugged apps</h2>



<p>Although Sandboxing, Entitlements, and Provisioning Profiles have been part of macOS app development, this release brings several enhancements in these areas:</p>



<ul class="wp-block-list">
<li>Now it is possible <strong>debug Sandboxed apps</strong> directly from the IDE.</li>



<li><strong>Entitlements and Provisioning Profile</strong> are applied when the app is debugged from the IDE.</li>



<li>Improvements in how the required Entitlements are added and signed when the macOS app is built; and also a better handling of the user-added entitlements and provisioning profile files (if required).</li>



<li><strong>Debugged and Built apps can be attached to the Instruments app</strong>. Among other things, Instruments can be used to detect issues such as memory leaks in the executed app. The IDE now automatically adds the required entitlement for this when: the app is debugged/built using the &#8220;None&#8221; (Ad-Hoc signing) from the Team popup menu, or, 2) when the app is built for Development (Build For) for a given Team.</li>
</ul>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2026/03/Untitled.mp4"></video></figure>



<p>When Build For is set to Direct Distribution or App Store, the required entitlement for Instruments to attach to the app, will be added only when the app is debugged from the IDE. If you want to use Instruments with a built app signed using these certificates, then you need to add that entitlement explicitly.</p>



<p>This decision is because when get-tasks-allow is set to True (the entitlement required in order Instrument being able to function), there are some well documented vulnerabilities that could be used to escalate privileges or inject code into your app. That&#8217;s not desirable for your distributed apps for sure (whether using Direct Distribution or if your app is installed through the Mac App Store).</p>



<h2 class="wp-block-heading">Looking forward</h2>



<p><br>We know there are still some areas to improve regarding code signing on macOS (and iOS) and we are working on some of them already. In the meantime, you’ll likely find the new Team-based Developer ID option more approachable, especially if this is your first experience dealing with certificates, signing, and distributing your freshly built macOS app.</p>



<p>A big THANK YOU to Richard Grafl for all his help and feedback during the beta-testing cycle of this feature.</p>



<p>Happy macOS code-signing!</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>Learn more about Code Signing in our recent series:</p>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>
</ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/03/Untitled.mp4" length="2577230" type="video/mp4" />

			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 3</title>
		<link>https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 24 Mar 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15944</guid>

					<description><![CDATA[If you followed the previous two articles in this series, you should be set up properly now, right? Your Mac developer certificates are stored in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>If you followed the previous two articles in this series, you should be set up properly now, right? Your Mac developer certificates are stored in Keychain Access, so you only need to fill in the Developer ID field under Build Settings &gt; macOS &gt; Sign with the appropriate certificate value, click Build (or Publish), and distribute your new amazing app worldwide. Well, not quite. There are still other pieces to consider when signing and distributing your macOS app.</p>



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



<p>For the past 20 years, Apple has increasingly tightened security measures when it comes to running apps distributed by third parties. Let&#8217;s take a look at this summarized timeline of code-signing and security measures added by Apple over years:</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-scaled.png"><img decoding="async" width="2560" height="1056" src="https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-scaled.png" alt="" class="wp-image-15945" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-scaled.png 2560w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-300x124.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-1024x422.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-768x317.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-1536x634.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-2048x845.png 2048w" sizes="(max-width: 2560px) 100vw, 2560px" /></a></figure>
</div>


<p>The most notable developments happened in 2011, 2012 and 2018, when terms like Sandbox and, especially, Containers, Gatekeeper, Hardened Runtime and Notarization were introduced and began to impact other pieces of the puzzle to consider when signing macOS apps. In fact, we could say that technologies such as code-signing, Sandboxing, Entitlements or Provisioning Profiles were among the first iOS technologies to make their way to macOS.</p>



<p>So here is an broad overview what these technologies mean:</p>



<ul class="wp-block-list">
<li><strong>Sandboxing</strong>&#8211; When used, Sandboxing confines applications to a restricted, designated area of the system (its own &#8220;container&#8221;), preventing them from accessing user data, hardware or other apps without explicit permission. The system requires apps to ask for permission to use hardware resources or access user files. Sandboxing is mandatory for apps distributed through the Mac App Store.</li>



<li><strong>Gatekeeper-</strong> This technology is the primary security layer that checks whether a downloaded app comes from a verified/known developer, especially when the application has been Notarized by Apple.</li>



<li><strong>Hardened Runtime</strong>&#8211; Acts as a proactive, system-enforced shield that protects applications while they run, preventing malicious code from exploiting legitimate software. Enabling Hardened Runtime is required for Notarization.</li>



<li><strong>Notarization</strong>&#8211; Notarization is an automated security screening process run by Apple that scans software distributed outside the Mac App Store for malicious components and known security issues. Today, notarization is required for software distributed outside the Mac App Store that has been signed with the Developer ID application certificate. As a result of the process, notarization generates and staples a ticket, signed by an Apple certificate, to the app so Gatekeeper can trust it when executed.</li>
</ul>



<p>So, basically, while Sandboxing is still optional for apps distributed outside the Mac App Store (i.e., signed with your Developer ID certificate), Notarization and Hardened Runtime are the recommended defaults. Enabling Sandboxing for your app is something you should consider based on the needs (features) and the privacy balance you want to offer your users.</p>



<p>If you plan to distribute the app through the Mac App Store as well, it will need to be Sandboxed and signed with your Apple Distribution certificate, while enabling Hardened Runtime is optional.</p>



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



<p>Entitlements and Provisioning Profiles are also required for many of these security measures, depending on the features and services your app uses, and they come into play during building and signing.</p>



<p>If you decide to go the Sandboxing route, then using Entitlements is mandatory. The good news is that Sandboxing entitlements are free to use (they don’t require creating or adding a Provisioning Profile to the project). However, if your app needs special access to the Keychain or uses iCloud, Apple Pay, or other services, you’ll need to create a Provisioning Profile in the Apple Developer portal.</p>



<p>Wait—what are Entitlements and Provisioning Profiles, and how do they relate to macOS app code signing?</p>



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



<p>Entitlements are XML-based .plist files (not unlike the app’s Info.plist) containing a set of key-value pairs. They are embedded directly into the app’s binary as part of the code signing process, typically using your Developer ID Application or Apple Distribution certificates.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="931" height="651" src="https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements.png" alt="" class="wp-image-15946" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements.png 931w, https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements-300x210.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements-768x537.png 768w" sizes="auto, (max-width: 931px) 100vw, 931px" /></figure>



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



<p>While Entitlements are just a file, Provisioning Profiles are a different beast:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="911" height="514" src="https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles.png" alt="" class="wp-image-15947" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles.png 911w, https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles-300x169.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles-768x433.png 768w" sizes="auto, (max-width: 911px) 100vw, 911px" /></figure>



<p>Provisioning Profiles must be created in the Apple Developer Portal. When you create one, you specify the App ID (the combination of your Team ID and the app bundle identifier which are case sensitive so pay attention). Even if you don’t plan to distribute your macOS app via the Mac App Store, you still need a Provisioning Profile, which requires creating an App ID first in the Developer Portal.</p>



<p>There are two kinds of Provisioning Profiles: Development and Distribution. As part of the provisioning profile creation, you must choose which type you will use.</p>



<ul class="wp-block-list">
<li><strong>Development Provisioning Profiles</strong> are used while you’re developing your app; the app is signed with an Apple Development certificate and is intended to run on a set of Mac computers you’ve registered. During creation, you can add as many Apple Development certificates as you have under your Team ID.</li>



<li><strong>Distribution Provisioning Profiles</strong> are used when distributing your app. For direct distribution, sign with the same Developer ID certificate you’ll use for signing the app; for Mac App Store distribution, sign with the Apple Distribution certificate.</li>



<li><strong>Development and Distribution Provisioning Profiles do expire</strong>. This is something to keep in mind, especially when deploying new or updated versions of your app, because you may need to create new profiles.</li>



<li><strong>Development and Distribution Profiles are editable</strong>. If you make a mistake, note that both types can be edited in the Apple Developer portal, but only for certain fields: the App ID, the profile name, the selected certificate, and (for Development profiles) the included testing devices.</li>
</ul>



<h2 class="wp-block-heading">When Certificates and/or Provisioning Profiles expire…</h2>



<p>We’ve already noted in previous articles that Apple Developer certificates expire one year after they’re created. We’ve also learned that if your app relies on a Distribution Provisioning Profile, that profile can expire as well. So, what does this mean for your already deployed apps?</p>



<p>No worries. Let’s focus first on directly distributed macOS apps (those signed with the Developer ID certificate) and pull one screenshot from the previous article:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1740" height="882" src="https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp.png" alt="" class="wp-image-15948" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp.png 1740w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-300x152.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-1024x519.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-768x389.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-1536x779.png 1536w" sizes="auto, (max-width: 1740px) 100vw, 1740px" /></figure>



<p>Observe the highlighted Timestamp line. When the app is signed, the date is added automatically (retrieved from Apple’s servers). So, when a user runs an app whose embedded Developer ID Certificate has expired since its release, Gatekeeper will rely on that timestamp, compare it to the embedded certificate’s expiration date, and if everything matches—meaning it was signed before the certificate expired—the app will continue to work, provided the embedded certificate has not been revoked by the developer. In addition, if the app was Notarized, that helps a lot, because the stapled ticket includes its own timestamp and was signed with a longer-lasting Apple Certificate.</p>



<p>If the app is distributed through the Mac App Store, there’s good news. After you submit the app for distribution via App Store Connect and it passes Apple’s review, the app’s signing with your Apple Distribution certificate is replaced by Apple’s own signing. This means that users who install the app from the Mac App Store can continue to run it even if your original Apple Distribution certificate expired long ago.</p>



<p>Distribution Provisioning Profiles behave differently from others: once they expire, the app containing such a Distribution Profile will fail to execute.</p>



<p>The good news is that a Distribution Profile lasts for a very long time (around 18 years) so you’ll likely have ample time to create new distribution provisioning profiles and deploy updates that use renewed profiles well before users are affected.</p>



<p>Of course, as soon as any of your Apple Developer certificates expire, you already know how to request and install new ones in your Mac keychain.</p>



<h2 class="wp-block-heading">Nearly Concluded</h2>



<p>In the next, and last article, we will see how Xojo helps with everything related to signing and distributing your macOS apps. I&#8217;ll also show you how to deal with some of the most common issues related with certificates.</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>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 2</title>
		<link>https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 18 Mar 2026 14:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15864</guid>

					<description><![CDATA[On the Apple side of code signing with developer certificates, we already know that the required root certificate, acting as the base anchor of the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>On the Apple side of code signing with developer certificates, we already know that the required root certificate, acting as the base anchor of the trust chain, is installed already on our Macs under the System Roots keychain.</p>



<p>But before we can reach our leaf developer certificates,&nbsp;we also need to have the Apple Development Intermediate certificates installed in our keychain. These are typically found in the Login keychain, though they can also be found in the System Roots or System keychains.</p>



<h2 class="wp-block-heading">Installing Apple Developer Intermediate Certificates</h2>



<p>Since Xcode 11.4.1 and later, these can be automatically downloaded and installed in the keychain, but if not, they can also can be downloaded from the <a href="https://www.apple.com/certificateauthority/" target="_blank" rel="noreferrer noopener">Apple PKI</a> webpage. The ones we are interested in are:</p>



<ul class="wp-block-list">
<li>Developer ID &#8211; G2</li>



<li>Worldwide Developer Relations &#8211; G2</li>



<li>Worldwide Developer Relations &#8211; G3</li>



<li>Worldwide Developer Relations &#8211; G4</li>



<li>Worldwide Developer Relations &#8211; G5</li>



<li>Worldwide Developer Relations &#8211; G6</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: The Developer ID &#8211; G2 certificate corresponds to the Developer ID Certification Authority. The WWDR certificates (G2–G6) correspond to the Apple Worldwide Developer Relations Certification Authority.</p>
</blockquote>



<p>As you can see from the list, there are several versions (or generations) for the WWDR Intermediate certificate; so, which one should you download? The short answer: it depends.</p>



<p>On February, 7, 2023 the previous WWDR intermediate certificate expired; so Apple decided to rollout a new renewed version that will expire on February 20, 2030. As part of that update Apple issued additional Intermediate certificates to better segment the purpose of different certificates:</p>



<ul class="wp-block-list">
<li>G2: ECDSA signing for Apple Pay.</li>



<li>G3: Software signing and Services.</li>



<li>G4: Features supported by Apple Push Notification Service.</li>



<li>G5: App Store Signing and Services.</li>



<li>G6: ECDSA signing of Software and Services.</li>
</ul>



<p>In practice, G3, G4, and G5 are sufficient for most scenarios.</p>



<h2 class="wp-block-heading">Developer Certificates: The final goal!</h2>



<p>To focus on the subject, what kind of leaf developer certificates are created from these two types of Intermediate certificates? This scheme will help:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1644" height="912" src="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust.png" alt="" class="wp-image-15865" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust.png 1644w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-300x166.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-1024x568.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-768x426.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-1536x852.png 1536w" sizes="auto, (max-width: 1644px) 100vw, 1644px" /></figure>



<p>As you can see from the above diagram, there are four main leaf certificates we will use to sign our macOS apps, based on their prefix:</p>



<ul class="wp-block-list">
<li><strong>Developer ID Application</strong>. Use this one to code sign a macOS app distributed outside the Mac App Store.</li>



<li><strong>Developer ID Installer</strong>. Use this one to code sign the Installer, DMG or .pgk file of a macOS app distributed outside the Mac App Store.</li>



<li><strong>Apple Distribution</strong>. This certificate is required to code sign a macOS app sent to the AppStore Connect for its distribution through the Mac App Store.</li>



<li><strong>3rd Party Mac Developer Installer</strong>. This Certificate is required to code sign the package of the app sent to the AppStore Connect. For example, when using the Publish feature from the Xojo IDE.</li>
</ul>



<h2 class="wp-block-heading">Creating and Installing the Developer Certificates</h2>



<p>As stated in the <a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">first article</a> of this series, you need a paid Apple Developer Program membership. Once that’s in place, the easiest way to install these required certificates in your macOS Keychain is through Xcode.</p>



<p>So, if it is the first time you need to install them on a Mac computer:</p>



<ol class="wp-block-list">
<li>Go to Xcode &gt; Preferences.</li>



<li>Select Apple Accounts.</li>



<li>Use your developer credentials to login into your developer account, or select it from the list if you are already logged.</li>



<li>Select the Team from the list.</li>



<li>Click the &#8220;Manage Certificates…&#8221; button.</li>



<li>Click the &#8220;+&#8221; popup menu in the lower-left corner of the resulting window, and select the developer certificate you want to install (all of these if it is the first time you install them).</li>
</ol>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="468" height="398" src="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00.png" alt="" class="wp-image-15866" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00.png 468w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00-300x255.png 300w" sizes="auto, (max-width: 468px) 100vw, 468px" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> Under the hood, Xcode follows the same process described for installing the developer certificates manually.</p>
</blockquote>



<p>If you prefer to go through the manual process instead:</p>



<ol class="wp-block-list">
<li>Access the <a href="https://developer.apple.com" target="_blank" rel="noreferrer noopener">Apple Developer website</a>.</li>



<li>In <a href="https://developer.apple.com/account/resources" target="_blank" rel="noreferrer noopener">Certificates, Identifiers &amp; Profiles, click Certificates in the sidebar.</a></li>



<li>On the top left, click the add button (+).</li>



<li>Under Software, select Developer ID, then click Continue.
<ul class="wp-block-list">
<li><strong>Developer ID Application</strong>: This certificate is used to code sign your app for distribution outside of the Mac App Store Connect.</li>



<li><strong>Developer ID Installer</strong>: This certificate is used to sign your app’s installer Package for distribution outside of the Mac App Store Connect.</li>



<li><strong>Apple Development</strong>: Used to run and debug apps on macOS during development.</li>



<li><strong>Apple Distribution</strong>: Used to sign apps for submission to App Store Connect.</li>



<li><strong>Mac App Distribution</strong>: Used to sign macOS apps intended to be distributed through the Mac App Store.</li>



<li><strong>Mac Installer Distribution</strong>: Used to send the macOS app to the App Store Connect for TestFlight or distribution through the Mac App Store.</li>
</ul>
</li>



<li>Follow the instructions to <a href="https://developer.apple.com/help/account/certificates/create-a-certificate-signing-request" target="_blank" rel="noreferrer noopener">create a certificate signing request</a>.</li>



<li>Click Choose File.</li>



<li>In the dialog that appears, select the certificate request file (a file with a .certSigningRequest file extension), then click Choose.</li>



<li>Click Continue.</li>



<li>Click Download.</li>



<li>The certificate file (a file with a .cer file extension) appears in your Downloads folder.</li>



<li>To install the certificate in your keychain, double-click the downloaded certificate file. The certificate appears in the My Certificates category in Keychain Access.</li>
</ol>



<h2 class="wp-block-heading">It&#8217;s All About Identities</h2>



<p>While Intermediate and Root certificates only have the Public Key on them, so they can verify other (leaf) certificates, the leaf certificates installed on your macOS Login keychain behave a bit different. Let&#8217;s see how.</p>



<p>Both if you use Xcode or create the CSR request manually to generate the developer certificates, using the Keychain Access app for that, in both of these scenarios <strong>a Private Key will be created and stored locally on your keychain</strong> as part of the process. <strong>Only the public key section of that private key is sent to the Apple servers</strong> so it can be included in the generated developer certificate. Once any of the possible developer certificates is downloaded and installed in the keychain, such certificate will have its private key associated with it:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="872" height="88" src="https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM.png" alt="" class="wp-image-15867" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM.png 872w, https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM-300x30.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM-768x78.png 768w" sizes="auto, (max-width: 872px) 100vw, 872px" /></figure>



<p>The pair of the developer certificate and the associated private key is what is called an Identity.</p>



<h2 class="wp-block-heading">Code signing With Developer Certificates</h2>



<p>In fact, while we often say or hear “code signing with certificates,” the real signing of the app is done with the private key associated with that certificate. The certificate itself (and thus the public key portion of that key pair) is included in the signing process. This allows macOS to verify the signature each time the user runs the app</p>



<p>Do you remember the diagram showing how the &#8220;Ad-Hoc&#8221; code signing process works? Let&#8217;s compare it when the same process is done using a &#8220;Developer ID Application&#8221; Certificate… and, most important, the associated private key:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1724" height="812" src="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing.png" alt="" class="wp-image-15869" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing.png 1724w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-300x141.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-1024x482.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-768x362.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-1536x723.png 1536w" sizes="auto, (max-width: 1724px) 100vw, 1724px" /></figure>



<p>As you can see, in this case the data is cyphered using the private key from the developer certificate and, then, the certificate itself is stored as part of the app itself. So, if for example we build this time an empty Desktop app for macOS using the Developer ID Application, and open the resulting CodeResources file in a text editor we will see something different compared with the Ad-Hoc signed version:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1298" height="974" src="https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed.png" alt="" class="wp-image-15870" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed.png 1298w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-300x225.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-1024x768.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-768x576.png 768w" sizes="auto, (max-width: 1298px) 100vw, 1298px" /></figure>



<p>In this case the field <strong>requirement&nbsp;</strong>associated with each file and hash value is significantly more strict. In fact, it makes reference to the Chain of Trust Gatekeeper is required to follow and validate. In plain English, the highlighted lines come to say something like:</p>



<ol class="wp-block-list">
<li>Hey! make sure there is a <strong>Developer ID Application</strong> certificate (Apple Extension attribute —OID— <em>1.2.840.113635.100.6.1.13&nbsp;</em>for the X.509 certificate), for the developer with a <strong>TeamID</strong> BW7PU32485.</li>



<li>Next, verify such certificate is issued by the &#8220;<strong>Apple Developer ID Certificate Authority</strong>&#8221; (other of the Apple-specific X.509 extension, attribute or OID. In this case: 1.2.840.113635.100.6.2.6).</li>



<li>And finally, go down through the Chain of Trust and verify the previous one with the <strong>Anchor</strong> certificate (Apple Root CA, do you remember?)</li>
</ol>



<p>So far so good. But how we can know if the app meets these requirements; and what about the certificates themselves? Well, it&#8217;s easy to check both using the codesign tool.</p>



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



<pre class="wp-block-preformatted">codesign --verify -vvv "MyApp.app"</pre>



<p>The output will be something similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2198" height="336" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement.png" alt="" class="wp-image-15871" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement.png 2198w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-300x46.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-1024x157.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-768x117.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-1536x235.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-2048x313.png 2048w" sizes="auto, (max-width: 2198px) 100vw, 2198px" /></figure>



<p>As you can see in the highlighted lines, yes, it satisfies the <strong>Designated Requirements</strong> we saw in our CodeResources file! Also, the previous line states that it is valid on disk. That means:</p>



<ul class="wp-block-list">
<li>All of the expected files are present.</li>



<li>There are no extra files.</li>



<li>None of the files have been modified.</li>



<li>A basic trust evaluation of the leaf certificate was successful.</li>



<li>And it satisfies its own Designated Requirements (DR).</li>
</ul>



<p>It is even possible to see the Chain of Trust for the code signature issuing:</p>



<pre class="wp-block-preformatted">codesign --display -vv "MyApp.app"&nbsp;</pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1222" height="340" src="https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust.png" alt="" class="wp-image-15872" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust.png 1222w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-300x83.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-1024x285.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-768x214.png 768w" sizes="auto, (max-width: 1222px) 100vw, 1222px" /></figure>



<p>And if you are curious enough, it is even possible to extract the embedded certificates stored in the <a href="https://www.ietf.org/rfc/rfc3852.txt" target="_blank" rel="noreferrer noopener">CMS structure within the code signature</a>:</p>



<pre class="wp-block-preformatted">codesign --display --extract-certificates "MyApp.app"</pre>



<p>As result it will, usually, create three files. Take a closer look at the &#8220;Issuer&#8221; and &#8220;Subject&#8221; lines; specially on the Subject line for the OU value (Organizative Unit or, using Apple wording, the TeamID) for the codesign0 file. Do you remember the &#8220;leaf[subject.OU=BW7PU32485]&#8221; data from the CodeResources file?&nbsp;:</p>



<p><strong>codesign0.</strong> This is the file for the Leaf certificate; in our example &#8220;Developer ID Application&#8221;.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1820" height="368" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate.png" alt="" class="wp-image-15873" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate.png 1820w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-300x61.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-1024x207.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-768x155.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-1536x311.png 1536w" sizes="auto, (max-width: 1820px) 100vw, 1820px" /></figure>



<p><strong>codesign1.</strong> This one is for the Intermediate Certificate; in our example &#8220;Apple Developer ID Certificate Authority&#8221;.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1562" height="366" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate.png" alt="" class="wp-image-15874" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate.png 1562w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-300x70.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-1024x240.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-768x180.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-1536x360.png 1536w" sizes="auto, (max-width: 1562px) 100vw, 1562px" /></figure>



<p><strong>codesign2.</strong> This one is for the Anchor Certificate; in our example &#8220;Apple Root CA&#8221;</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1274" height="344" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate.png" alt="" class="wp-image-15875" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate.png 1274w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-300x81.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-1024x276.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-768x207.png 768w" sizes="auto, (max-width: 1274px) 100vw, 1274px" /></figure>



<p><br>As shown by the <strong>Issuer</strong> line in the codesign0 file for our “Developer ID Application,” it points to the previous certificate in the trust chain—the Developer ID Certification Authority. The codesign1 file for the extracted Developer ID Certification Authority points to the Apple Certification Authority in its Issuer field. Finally, the codesign1 certificate points to itself because, as the Root Certificate, it serves as the <strong>anchor</strong> for the trust chain.</p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>In this second article, we delved deeper into how Apple Developer certificates work, how a macOS app is signed (Ad-Hoc or with a specific developer certificate), and how the OS’s security features validate the signing when a user tries to run the app.</p>



<p>In the next article, we will cover more details about signing apps for the two main distribution types: Direct distribution and Mac App Store. We will also discuss what happens when certificates expire and how to troubleshoot the most common issues related to development certificates.</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>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 1</title>
		<link>https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 04 Mar 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15856</guid>

					<description><![CDATA[Your macOS app is finished and ready to go. But unless you plan to run it only on your own machine, there’s one essential step&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Your macOS app is finished and ready to go. But unless you plan to run it only on your own machine, there’s one essential step before sharing it with others: code signing with certificates.</p>



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



<p>This blog series provides a clear, practical overview of how certificates work, with a focus on signing and distributing macOS applications. Some concepts apply to digital certificates in general, while others are specific to the macOS code signing process. By the end of the series, you’ll understand what certificates are, why they matter, and the role they play when building and distributing a macOS app.</p>



<p>The Developer ID field in the Build Settings &gt; macOS &gt; Sign Inspector Panel is our starting point:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1000" height="574" src="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17.png" alt="" class="wp-image-15857" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17.png 1000w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17-300x172.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17-768x441.png 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<p>By default, this field is empty. When you click Build, the app bundle (and its contents) is signed using a more relaxed security configuration. This does not require an explicit developer certificate and does not verify that the app comes from a known, trusted developer.</p>



<p>This type of signing is called Ad-Hoc signing. It is perfectly fine when debugging from the IDE or when building apps you intend to run locally.</p>



<p>In earlier versions of macOS, it was even possible to distribute and run Ad-Hoc–signed apps on other Macs, as long as the user explicitly chose to trust them. While this is still technically possible on recent versions of macOS, Apple has continued to tighten security, making it increasingly difficult for users to launch Ad-Hoc–signed applications.</p>



<p>In most cases, <a href="https://support.apple.com/en-au/guide/security/sec5599b66df/web" target="_blank" rel="noreferrer noopener">Gatekeeper</a> will intervene and prevent the app from launching. Since the system cannot verify the identity of a trusted developer, it treats the app as unverified. With Ad-Hoc signing, macOS can only confirm that the app has not been modified since it was signed, it cannot validate who created it.</p>



<h2 class="wp-block-heading">Under the hood: How &#8220;Ad-Hoc&#8221; signing works</h2>



<p>Every time an app is signed (including all the contents inside its bundle) macOS uses Apple’s codesign tool. When Ad-Hoc signing is applied, the simplified process works roughly like this:<br></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1390" height="812" src="https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works.png" alt="" class="wp-image-15858" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works.png 1390w, https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works-300x175.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works-1024x598.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works-768x449.png 768w" sizes="auto, (max-width: 1390px) 100vw, 1390px" /></figure>



<ul class="wp-block-list">
<li>A hash value (a unique digital fingerprint) is calculated for every file in the app bundle, whether it is executable or not, as well as for the bundle itself.</li>



<li>These hash values are stored inside the app bundle, in the <code>_CodeSignature</code> folder.</li>



<li>If the app contains multiple architectures (for example, x86 and ARM), the process is repeated for each supported architecture.</li>
</ul>



<p>When a user double-clicks the app to launch it, macOS performs a similar verification process:</p>



<ul class="wp-block-list">
<li>It recalculates the hash value for every file in the bundle.</li>



<li>It compares the newly calculated values with those stored in the <code>_CodeSignature</code> folder and if any hash differs from the stored value, macOS determines that the bundle has been modified since it was signed and it will refuse to launch the app.</li>
</ul>



<p>Want to see this in action? Create a new Desktop project in the Xojo IDE, save it to your Documents folder, and build it for macOS.</p>



<p>Next, locate the built app in Finder. Control-click it and choose “Show Package Contents.” Then open the Contents &gt; _CodeSignature folder and inspect the CodeResources file using your favorite text editor. You’ll see a list of hash values and digests corresponding to every file in the app bundle.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1248" height="1344" src="https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile.png" alt="" class="wp-image-15859" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile.png 1248w, https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile-279x300.png 279w, https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile-951x1024.png 951w, https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile-768x827.png 768w" sizes="auto, (max-width: 1248px) 100vw, 1248px" /></figure>



<h2 class="wp-block-heading">Apple Developer Certificates: Establishing Trust on macOS</h2>



<p>What must you do so your apps are recognized as first-class citizens on macOS and can be distributed without Gatekeeper intervening? The answer is likely familiar: enroll in the Apple Developer Program (currently US $99 per year).</p>



<p>Among its many benefits, membership in the Apple Developer Program allows you to create your own Developer ID certificates. When you use these certificates to sign your apps, macOS can validate the signature and identify you as the verified developer distributing the software.</p>



<p>But how is this trust established and verified? To answer that, we need to start at the very root, literally!</p>



<p>Every computer, smartphone, tablet, and many other devices come with preinstalled Root Certificates. These certificates are issued by trusted organizations known as Root Certificate Authorities (CAs), including Apple. They serve as the foundation of a chain of trust, allowing other certificates issued by those authorities to be verified.</p>



<p>Technically speaking, a Root Certificate Authority (CA) is the top-level trusted entity in a public key infrastructure (<a href="https://en.wikipedia.org/wiki/Public_key_infrastructure">PKI</a>). It issues self-signed root certificates that act as the trust anchor for verifying other digital certificates. In other words, it is the foundation upon which the entire certificate trust model is built.</p>



<p>It is easy to take a look to these installed on your Mac:</p>



<ol class="wp-block-list">
<li>Open Keychain Access.</li>



<li>Select Certificates at the top of the window.</li>



<li>In the sidebar, choose System Roots.</li>



<li>You will then see the complete list of root certificates trusted by macOS.</li>
</ol>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2186" height="1264" src="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates.png" alt="" class="wp-image-15860" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates.png 2186w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-300x173.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-1024x592.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-768x444.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-1536x888.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-2048x1184.png 2048w" sizes="auto, (max-width: 2186px) 100vw, 2186px" /></figure>



<p>You’ll notice that there are three different Apple Root CA certificates. Why?</p>



<p>Each <a href="https://en.wikipedia.org/wiki/X.509" target="_blank" rel="noreferrer noopener">X.509</a> certificate contains detailed metadata defining its cryptographic properties and permitted usage. This includes the key type (such as <a href="https://en.wikipedia.org/wiki/RSA_cryptosystem" target="_blank" rel="noreferrer noopener">RSA</a> or <a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm" target="_blank" rel="noreferrer noopener">ECDSA</a>), the public key length, and the signature algorithm used.</p>



<ul class="wp-block-list">
<li><strong>Apple Root CA</strong>: Is a RSA type, with a public key length of 2048 bits that uses the SHA-1 algorithm.</li>



<li><strong>Apple Root CA-G2</strong>: Is a RSA type, with a public key length of 4096 bits that uses the SHA-384 algorithm.</li>



<li><strong>Apple Root CA-G3</strong>: Is a ECDSA type, with a public key length of 384 bits that uses the SHA-384 algorithm.</li>
</ul>



<h2 class="wp-block-heading">Intermediate Certificates and the Chain of Trust</h2>



<p>Root certificates are highly valuable and sensitive, so they are rarely used directly to sign end-user certificates (also called “Leaf” certificates). In the case of macOS app development, the developer’s certificate is the Leaf. This is where Intermediate Certificates come into play.</p>



<p>In simple terms, Intermediate Certificates are signed by Root Certificates and, in turn, are used to sign Leaf certificates. This protects the Root certificate from direct exposure. Together, the Root, Intermediate, and Leaf certificates form what is called the “Chain of Trust.”</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1254" height="932" src="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span.png" alt="" class="wp-image-15861" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span.png 1254w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span-300x223.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span-1024x761.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span-768x571.png 768w" sizes="auto, (max-width: 1254px) 100vw, 1254px" /></figure>



<p>The Chain of Trust verification starts with the Leaf certificate and works upward through the Intermediate to the Root. This same process occurs whenever you visit a secure website, make an online payment, or transmit sensitive data securely.</p>



<p>For example, the Leaf certificate is validated against its Intermediate certificate. If the Intermediate certificate is missing or expired, the Leaf certificate is considered invalid. Similarly, the Intermediate certificate itself must be validated against the Root certificate. If the Root certificate is missing or expired, the Intermediate is invalid, and all Leaf certificates signed by it are also invalid.</p>



<p>The same process happens when you sign your macOS apps: macOS validates the entire certificate chain before allowing the app to run.</p>



<p>Finally, certificates closer to the Root generally have longer validity periods. Leaf certificates must be renewed more frequently, while Root certificates are valid for many years.</p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>In this first article, we covered the fundamentals of digital certificates and their role in macOS app security. In the next article, we will focus specifically on Apple Developer certificates and how they enable trusted app distribution.</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>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Scatter Chart: Connecting the Points</title>
		<link>https://blog.xojo.com/2026/02/09/scatter-chart-connecting-the-points/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 09 Feb 2026 16:26:56 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Charts]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15826</guid>

					<description><![CDATA[A user recently asked whether it’s possible to connect the (x, y) points in a Scatter chart using DesktopChart, and if so, how to do&#8230;]]></description>
										<content:encoded><![CDATA[
<p>A user recently asked whether it’s possible to connect the (x, y) points in a Scatter chart using DesktopChart, and if so, how to do it. The short answer is yes, it is possible. Read on and I’ll show you just how easy it is.</p>



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



<p>For this example, we’ll use the x and y coordinate values of the sine and cosine functions as the data for our scatter DataSets. Go ahead and create a new Desktop project in the Xojo IDE.</p>



<p>Next, select the default Window1 and drag a DesktopChart control from the Library panel into the Layout Editor for Window1. Adjust the right margin to the recommended right layout guide, then lock the Top, Left, and Right layout locks for the Chart1 instance using the Inspector. At this point, your design should look similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2560" height="1800" src="https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-scaled.png" alt="" class="wp-image-15827" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-scaled.png 2560w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-300x211.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-1024x720.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-768x540.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-1536x1080.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-2048x1440.png 2048w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></figure>



<p>While you’re there, select Chart1 and, in the Inspector, set the option Behavior &gt; Mode to Scatter.</p>



<p>Next, with Window1 selected, add two properties using the following values:</p>



<p><strong>Property 1:</strong></p>



<ul class="wp-block-list">
<li><strong>Name:</strong> CosStyle</li>



<li><strong>Type:</strong> ChartLinearStyle</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p><strong>Property 2</strong></p>



<ul class="wp-block-list">
<li><strong>Name:</strong> SineStyle</li>



<li><strong>Type:</strong> ChartLinearStyle</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p>These properties will be used to store references to the Style objects associated with the cosine and sine function DataSets.</p>



<p>Finally, with Window1 still selected, add the Opening event and enter the following lines of code into the associated code editor:</p>



<pre class="wp-block-preformatted">CosStyle = New ChartLinearStyle<br>CosStyle.Line = ChartLinearStyle.LineTypes.Dashed<br><br>SineStyle = New ChartLinearStyle<br>SineStyle.Line = ChartLinearStyle.LineTypes.Solid<br><br>DrawScatterChart</pre>



<p>In brief, this code creates new ChartLinearStyle instances for the properties added earlier. It assigns a solid line style to connect the cosine function data points and a dashed line style to connect the sine function data points. After that, it calls the DrawScatterChart method, which is responsible for rendering the sine and cosine functions on the Chart1 instance.</p>



<p>Now, let’s create that method on Window1 using the following values in the Inspector:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> DrawScatterChart</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p>Type the following snippet of code in the associated Code Editor for the method:</p>



<pre class="wp-block-code"><code>// These are the Array variables in charge of storing the Scatter data points
// for the Sine and Cosine functions
Var sinePoints() As ChartScatterDatapoint
Var cosinePoints() As ChartScatterDatapoint

// …and these variables will handle the DataSet instances
// for the previous arrays of data points on both functions
Var sineDataSet As ChartScatterDataset
var cosDataSet As ChartScatterDataset

Const pi = 3.14159265359
Var y As Double
Var maxXValue As Double = 2.0 * pi

// Using a simple loop to feed the x and y
// values for the Sine and Cosine
For x As Double = 0.0 To maxXValue Step 0.5
  
  y = Sin(x)
  sinePoints.Add(New ChartScatterDatapoint(x, y, 1))
  
  y = Cos(x)
  cosinePoints.Add(new ChartScatterDatapoint(x, y, 1))
  
Next

// Next, we create the new instances for the Scatter DataSets
sineDataSet = New ChartScatterDataset(Color.Blue, sinePoints)
cosDataSet = New ChartScatterDataset(color.Red, cosinePoints)

// …and we set the Style to be used on each of them
sineDataSet.Style = SineStyle
cosDataSet.Style = CosStyle

// … and of course the labels to be shown on the Legend section
// of the chart itself
sineDataSet.Label = "Sine Function"
cosDataSet.Label = "Cos Function"

// As the last step, we add both DataSets to the chart
// so these can be rendered
Chart1.AddDatasets(sineDataSet, cosDataSet)</code></pre>



<p>Run the app, and it should look similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1424" height="1088" src="https://blog.xojo.com/wp-content/uploads/2026/02/Chart2.png" alt="" class="wp-image-15828" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Chart2.png 1424w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart2-300x229.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart2-1024x782.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart2-768x587.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>



<h2 class="wp-block-heading">A change of Style… on the fly!</h2>



<p>As with many aspects of DesktopChart, any changes made at runtime are reflected immediately, without the need to redraw the chart, re-feed the data sets, or perform any other complex operations. Let’s take advantage of this by changing the sine and cosine styles at runtime, allowing users of our example app to toggle whether the points are connected.</p>



<p>Add two DesktopCheckBox controls below the bottom margin of the Chart1 instance on Window1. Set the Caption of the first checkbox to “Connect Sine Points” and the second to “Connect Cos Points.” For both checkboxes, use the Inspector to set Initial State &gt; Visual State to Checked.</p>



<p>The final layout should look similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1292" height="954" src="https://blog.xojo.com/wp-content/uploads/2026/02/Chart3.png" alt="" class="wp-image-15829" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Chart3.png 1292w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart3-300x222.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart3-1024x756.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart3-768x567.png 768w" sizes="auto, (max-width: 1292px) 100vw, 1292px" /></figure>



<p>Lastly, add the ValueChanged event to both CheckBox instances. Then, for the checkbox with the caption “Connect Sine Points,” add the following lines of code to its event handler:</p>



<pre class="wp-block-code"><code>If Me.Value Then
  SineStyle.Line = ChartLinearStyle.LineTypes.Dashed
Else
  SineStyle.Line = ChartLinearStyle.LineTypes.None
End If</code></pre>



<p>Add the following lines of code to the ValueChanged event handler for the checkbox with the caption “Connect Cos Points”:</p>



<pre class="wp-block-code"><code>If Me.Value Then
  CosStyle.Line = ChartLinearStyle.LineTypes.Solid
Else
  CosStyle.Line = ChartLinearStyle.LineTypes.None
End If</code></pre>



<p>Run the app again and, this time, click each checkbox to see how the points are no longer connected when a checkbox is unchecked, and are connected when it is selected.</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2026/02/Grabacion-de-pantalla-2026-02-02-a-las-13.53.35.mp4"></video></figure>



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



<p>As you can see, styles can be used not only to connect points in a Scatter chart, but also to customize the point endpoints beyond the default appearance. For example, you can set the endpoint to “None” or choose from many other available options. Even better, any changes made to a style at runtime are applied immediately.</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>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/02/Grabacion-de-pantalla-2026-02-02-a-las-13.53.35.mp4" length="171622" type="video/mp4" />

			</item>
		<item>
		<title>Detecting UI Compatibility Mode in macOS Apps with Xojo</title>
		<link>https://blog.xojo.com/2026/01/14/detecting-ui-compatibility-mode-in-macos-apps-with-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 22:49:34 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15762</guid>

					<description><![CDATA[As you may already know, starting with Xojo 2025r3, macOS apps can be developed and compiled with UI Compatibility Mode either enabled or disabled. Now&#8230;]]></description>
										<content:encoded><![CDATA[
<p>As you may already know, starting with Xojo 2025r3, macOS apps can be developed and compiled with UI Compatibility Mode either enabled or disabled. Now imagine you are creating a Library intended for use in other projects and, as part of its UI-related functionality, the Library needs to determine whether the host application is running with UI Compatibility Mode enabled. How can you do that? Read on to find out.</p>



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



<p>To determine whether a macOS app is running with UI Compatibility Mode enabled, we’ll use a small set of <a href="https://documentation.xojo.com/topics/declares/calling_native_macos_apis.html">Declares</a> inside a method contained in a Module, purely for the purposes of this example. Begin by creating a new Desktop project and adding a new Module to it (for example, a simple “Module1”). Next, add a new method to the Module with the following signature:</p>



<p><code>IsCompatibilityModeEnabled As Boolean</code></p>



<p>Then add the following code to the method:</p>



<pre class="wp-block-code"><code>#If TargetMacOS Then
  
  If System.Version.MajorVersion >= 26 Then
    
    Declare Function NSClassFromString Lib "Foundation" (clsName As CFStringRef) As Ptr
    Declare Function NSMainBundle Lib "AppKit" Selector "mainBundle" (obj As Ptr) As Ptr
    Declare Function NSInfoDictionary Lib "AppKit" Selector "infoDictionary" (obj As Ptr) As Ptr
    Declare Function NSDictValueForKey Lib "AppKit" Selector "valueForKey:" (obj As Ptr, key As CFStringRef) As Ptr
    Declare Function NSGetBoolValue Lib "AppKit" Selector "boolValue" (obj As Ptr) As Boolean
    
    Var Bundle As Ptr = NSClassFromString("NSBundle")
    
    If Bundle &lt;> Nil Then
      Var MainBundle As Ptr = NSMainBundle(Bundle)
      
      If MainBundle &lt;> Nil then
        Var infoDictionaryPlist As Ptr = NSInfoDictionary(MainBundle)
        
        If infoDictionaryPlist &lt;> Nil Then
          Var valueObj As Ptr = NSDictValueForKey(infoDictionaryPlist, "UIDesignRequiresCompatibility")
          
          If valueObj &lt;> Nil Then 
            Return NSGetBoolValue(valueObj)
          End If
          
        End If
        
      End If
      
    End If
  End If
  
  Return False
  
#EndIf</code></pre>



<p>In short, the previous code retrieves the app’s Info.plist from the macOS bundle and loads it into an NSDictionary object (similar to Xojo’s Dictionary). It then attempts to access the value associated with the key <code>UIDesignRequiresCompatibility</code>. If the returned object is Nil, it means the Info.plist does not contain that key and the app is therefore running in native macOS Tahoe mode. If the key is present, the method returns the Boolean value associated with it; a value of True indicates that the app is running with UI Compatibility Mode enabled under macOS Tahoe. That’s all there is to it!</p>



<h2 class="wp-block-heading">Testing the Method</h2>



<p>Now add a DesktopButton to the project’s default window and implement its Pressed event. Next, insert the following line of code into the associated Code Editor:</p>



<pre class="wp-block-code"><code>MessageBox("Compatibility Mode Enabled: " +  IsCompatibilityModeEnabled.ToString)</code></pre>



<p>For testing purposes, select Build Settings &gt; macOS in the Project Browser and enable UI Compatibility Mode, which can be found under the Build section of the Inspector. Run the app and, if your Mac is running macOS 26 or later, you will see the following message:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1204" height="860" src="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54.png" alt="" class="wp-image-15763" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54.png 1204w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-1024x731.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-768x549.png 768w" sizes="auto, (max-width: 1204px) 100vw, 1204px" /></figure>



<p>Quit the app and return to Build Settings &gt; macOS to disable UI Compatibility Mode. Run the app again and this time you will see the following message:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1204" height="866" src="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22.png" alt="" class="wp-image-15764" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22.png 1204w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-300x216.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-1024x737.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-768x552.png 768w" sizes="auto, (max-width: 1204px) 100vw, 1204px" /></figure>



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



<p>As you can see, Declares are a powerful feature in Xojo’s extensive toolbox, allowing developers to directly access and use APIs provided by the operating system. In this case, they enable you to retrieve the app’s Info.plist from the main bundle, load it into a dictionary, and read the value associated with a specific key.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tip: Customize Toolbars on macOS apps</title>
		<link>https://blog.xojo.com/2025/12/17/tip-customize-toolbars-on-macos-apps/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 17 Dec 2025 17:04:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[macOS 26]]></category>
		<category><![CDATA[Toolbar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15727</guid>

					<description><![CDATA[Starting with Xojo 2025r3, macOS apps are built using macOS SDK 26. One benefit of this is that your apps automatically gain access to newer&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2025r3, macOS apps are built using macOS SDK 26. One benefit of this is that your apps automatically gain access to newer native macOS features with little or no extra work. In some cases, these features are available immediately; in others, they can be enabled with a simple Declare. One such example is allowing users to customize an app’s toolbar.</p>



<p>To demonstrate this, we’ll use the Desktop Toolbar example project that ships with Xojo. You can find it in the Examples section of the New Project window. Open this project using the Xojo 2025r3 IDE.</p>



<p>Once the project is open, locate the MainWindow in the Project Browser. Under MainWindow, select the WindowToolbar item and then choose its Opening event. At the top of the Code Editor for this event, add the following lines of code:</p>



<pre class="wp-block-code"><code>Var hdl As Ptr = Me.Handle
If hdl.Integer &lt;> 0 Then
  Declare Sub AllowCustomization Lib "AppKit" Selector "setAllowsUserCustomization:" (hdl As Ptr, value As Boolean)
  AllowCustomization(hdl, True)
End If</code></pre>



<p>It&#8217;s that simple!</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/12/Grabacion-de-pantalla-2025-12-09-a-las-14.13.05.mp4"></video></figure>



<p>Run the app and open the contextual menu by right-clicking (or Control-clicking) on the window’s toolbar. You’ll see a new Customize Toolbar menu item. Select it to open the standard macOS toolbar customization panel, where you can rearrange or remove items as you like. When you click OK, your changes are immediately applied to the current toolbar.</p>



<p>One important caveat: these customizations are not preserved between app launches. This happens because each toolbar must have a unique identifier that macOS uses to save and restore its configuration. Since the example toolbar does not provide one, the OS has nothing to store or retrieve. But… who knows what the future holds?</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>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/12/Grabacion-de-pantalla-2025-12-09-a-las-14.13.05.mp4" length="512280" type="video/mp4" />

			</item>
		<item>
		<title>macOS and iOS: UI Compatibility Mode</title>
		<link>https://blog.xojo.com/2025/12/09/macos-and-ios-ui-compatibility-mode/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:31:52 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Liquid Glass]]></category>
		<category><![CDATA[macOS 26]]></category>
		<category><![CDATA[macOS Tahoe]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15600</guid>

					<description><![CDATA[macOS 26 and iOS 26 bring many changes, most notably a major UI overhaul. This means that some elements in your existing layouts, both small&#8230;]]></description>
										<content:encoded><![CDATA[
<p>macOS 26 and iOS 26 bring many changes, most notably a major UI overhaul. This means that some elements in your existing layouts, both small and significant, may look different. To help developers with this transition, Apple has introduced UI Compatibility Mode in both operating systems for this release.</p>



<p>So, what is UI Compatibility Mode? It’s Apple’s way of ensuring that your app’s UI appears in macOS 26 and iOS 26 just as it did on previous OS versions. No Liquid Glass effects, no unexpected changes in control sizes or behavior, everything stays as you designed it. This means your pixel-perfect layouts from older OS versions, like Sequoia or iOS 18, will continue to look exactly as intended.</p>



<p>More technically, when UI Compatibility Mode is enabled, your app behaves as if it were compiled with an earlier SDK.</p>



<p>The caveat: Apple only guarantees this behavior while macOS 26 and iOS 26 are current. With the next major OS releases, this mode may no longer be available, so it’s a temporary solution.</p>



<p>The upside: At the time of writing, Apple is still refining these OS versions with point releases. If you need your app to run on macOS 26 or iOS 26 with full compatibility, you can enable UI Compatibility Mode in the Inspector Panel under Build Settings &gt; macOS and Build Settings &gt; iOS.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="441" src="https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-1024x441.png" alt="" class="wp-image-15606" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-1024x441.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-300x129.png 300w, https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-768x331.png 768w, https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch.png 1234w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>When enabled, both your debugged apps and the built versions (including those submitted to Apple via Publish) will look and behave on macOS 26 and iOS 26 as if they were compiled with the previous SDK. In fact, the behavior is even more consistent than if they had been compiled using the prior Xojo release.</p>



<p>Below, you can see how the same app appears when running on macOS 26 and iOS 26 with UI Compatibility Mode turned off (showing Liquid Glass and all the new UI effects), compared to how it looks when the switch is turned on:</p>



<figure class="wp-block-image size-full"><img decoding="async" src="https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeMacOS.png" alt="" class="wp-image-15601"/></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="970" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-970x1024.png" alt="" class="wp-image-15603" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-970x1024.png 970w, https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-284x300.png 284w, https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-768x811.png 768w, https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS.png 1697w" sizes="auto, (max-width: 970px) 100vw, 970px" /></figure>



<h2 class="wp-block-heading">The Last Word</h2>



<p>All in all, macOS 26 and iOS 26 introduce a major UI overhaul, which can change the appearance of existing layouts. To help developers, Apple has added UI Compatibility Mode, which lets your apps appear on these new OS versions just as they did on previous releases—no Liquid Glass effects or layout changes. Technically, enabling this mode makes your app behave as if it were compiled with an earlier SDK. While Apple only guarantees this behavior for macOS 26 and iOS 26, it ensures consistency for both debugged and built apps, including those submitted via Publish.</p>



<p>UI Compatibility Mode gives you a choice: enable it to preserve your exact layouts across all OS versions, or leave it off to adopt the new macOS 26 and iOS 26 look and feel, which may require adjusting your UI for some quirks.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Welcome to the Grid</title>
		<link>https://blog.xojo.com/2025/12/09/welcome-to-the-grid/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:29:53 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Grid Control]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15663</guid>

					<description><![CDATA[Xojo 2025r3 introduces the first iteration of the DesktopGrid control. This long-awaited control allows you to display as many rows and columns as needed, making&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2025r3 introduces the first iteration of the DesktopGrid control. This long-awaited control allows you to display as many rows and columns as needed, making it ideal for complex data layouts. Let’s take a closer look at some of its features.</p>



<p>Like other controls in the Xojo framework, DesktopGrid is a data-source-based control. Instead of manually adding cells, rows, or columns as you would with a ListBox, the DesktopGrid itself requests the data it needs when it needs it. This approach brings several benefits:</p>



<p><strong>ContainerControl-based cells:</strong> The cells in a DesktopGrid are full ContainerControls, just like the ones you’re already familiar with. You can use the same layout for all cells or customize different layouts for individual cells, rows, or columns. Each cell represents a live control and behaves accordingly.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="741" src="https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-1024x741.png" alt="" class="wp-image-15666" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-1024x741.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-300x217.png 300w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-768x556.png 768w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-1536x1112.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-2048x1483.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li><strong>Lower memory footprint:</strong> DesktopGrid keeps only the cells that are currently visible on screen “alive,” which significantly reduces memory usage, especially when working with very large data sets. For example, when you resize the containing window, the DesktopGrid will request additional content from its DataSource <strong>only if necessary</strong>. When cells move outside the visible area of the DesktopGrid, their corresponding ContainerControl instances are “closed,” triggering an event you can handle, and freeing the memory they were using.</li>



<li><strong>Faster execution</strong>: Large data sets are not preloaded into the control. This means that opening a window with a DesktopGrid or running an app with many cells happens almost instantly, providing a smooth and responsive experience even with extensive data.</li>
</ul>



<figure class="wp-block-video"><video height="1080" style="aspect-ratio: 1920 / 1080;" width="1920" controls src="https://blog.xojo.com/wp-content/uploads/2025/12/FastExecution.mp4"></video></figure>



<ul class="wp-block-list">
<li><strong>Layout Flexibility</strong>: Since the number of rows and columns is determined by the DataSource, a DesktopGrid instance can have a flexible layout rather than a rigid, static one. For example, you can adjust the number of columns based on the available width of the DesktopGrid. You can also set different widths for individual columns, while the row height remains fixed.</li>
</ul>



<figure class="wp-block-video"><video height="1080" style="aspect-ratio: 1920 / 1080;" width="1920" controls src="https://blog.xojo.com/wp-content/uploads/2025/12/FlexibleGridLayout.mp4"></video></figure>



<ul class="wp-block-list">
<li><strong>Data representation changes &#8220;on the fly&#8221;</strong>: Because the DataSource provides the content for each cell, you can dynamically change the data representation (the ContainerControl layout) at runtime or even pull data from a completely different source.</li>



<li><strong>A better separation of responsibilities</strong>: While you can implement the GridDataSource interface directly on the DesktopGrid or in its containing Window, using a dedicated DataSource class is the cleaner approach. This ensures a clearer separation between the view (the DesktopGrid), the model (the data feeding the cells), and the controller (which manages interactions between the two). A single DataSource can also feed multiple DesktopGrid instances, making your code more reusable.</li>



<li><strong>Headers everywhere:</strong> By default, DesktopGrid displays column and row headers. You can modify this in the Inspector Panel or via code. Depending on your scenario, you might choose to show both headers, just one, or hide them entirely. By default, the headers display simple numbering for each column and row. However, you can fully customize their content using the PaintHeaderContentForColumn and PaintHeaderContentForRow methods of your GridDataSource implementation, giving you complete control over how headers appear.</li>
</ul>



<h2 class="wp-block-heading">Is the DesktopGrid a replacement for DesktopListBox?</h2>



<p>While you can use DesktopGrid for many purposes, it is not a direct replacement for DesktopListBox in all scenarios. If your data is primarily textual (like simple labels) or relies on features specific to DesktopListBox, such as hierarchical data representation, then DesktopListBox is still the better choice.</p>



<p>DesktopGrid shines in scenarios where you need complex layouts in each cell using live controls rather than temporary pictures or workarounds. Each cell can have its own layout, including interactive controls such as ListBoxes, buttons, or other reactive elements that respond to user interactions. This makes DesktopGrid ideal for rich, interactive, and highly customizable grid layouts.</p>



<h2 class="wp-block-heading">Performance Caveats to Consider</h2>



<p>Although the first iteration of DesktopGrid was designed with performance in mind, there are some factors that may affect its redraw speed. The most significant is that each cell uses live controls, so performance will be similar to placing the same number of controls directly on a Window. While alternative approaches—such as reusable cells or backing picture representations—could improve speed, they come with their own trade-offs.</p>



<p>As a general rule, performance depends on cell size and the number of visible cells at any given time. A large DesktopGrid with many rows and columns, even if each cell contains just a simple label, may experience slower refresh rates. Additionally, actual performance can vary depending on the operating system and its version, as these affect the underlying drawing and refresh processes.</p>



<h2 class="wp-block-heading">Wiring the Grid</h2>



<p>Although this is just the first iteration of the DesktopGrid control, we are already working on the next set of features while further refining the existing ones. You can read more about this control in the <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopgrid.html" target="_blank" rel="noreferrer noopener">Xojo Documentation</a>. We want to extend a big <strong>THANK YOU</strong> to everyone who provided feedback and dedicated their time testing the Grid during the beta cycle, you know who you are! Your input is invaluable, and the feature requests you submitted (combined with others already on our roadmap) will help shape a DesktopGrid that better fits your needs.</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>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/12/FastExecution.mp4" length="432356" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/12/FlexibleGridLayout.mp4" length="2560805" type="video/mp4" />

			</item>
		<item>
		<title>Xojo 2025r2.1: Publishing macOS Apps Under Tahoe</title>
		<link>https://blog.xojo.com/2025/10/14/xojo-2025r2-1-publishing-macos-apps-under-tahoe/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 14 Oct 2025 21:20:03 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[macOS Tahoe]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15445</guid>

					<description><![CDATA[macOS 26 is in the wild, and many Xojo users have likely updated their Macs to the latest version. While Xojo 2025r2.1 is compatible and&#8230;]]></description>
										<content:encoded><![CDATA[
<p><a href="https://blog.xojo.com/2025/09/15/xojo-support-for-macos-26-and-ios-26/" target="_blank" rel="noreferrer noopener">macOS 26 is in the wild</a>, and many Xojo users have likely updated their Macs to the latest version. While Xojo 2025r2.1 is compatible and can build apps that run under the latest macOS, the <a href="https://blog.xojo.com/2025/03/25/how-to-publish-macos-and-ios-apps-to-the-app-store-directly-from-xojo/" target="_blank" rel="noreferrer noopener">Publish feature</a> depends on certain tools provided by Xcode. Unfortunately, one of these tools has undergone a significant change in the latest Xcode release, causing the Publish feature to no longer function correctly.</p>



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



<p>There are two possible solutions:</p>



<ul class="wp-block-list">
<li><strong>If your Mac still runs under macOS 15.7 Sequoia</strong> (or an earlier macOS version supported by Xojo&#8217;s Publish feature) with Xcode 26 installed,  you can restore Publish feature compatibility by installing Xcode 16.4.x and making that version the active one in your toolchain (especially if you have multiple Xcode versions installed).</li>



<li><strong>If your Mac is running macOS 26.x Tahoe</strong> with Xcode 26 installed, Xojo&#8217;s Publish feature for macOS apps won&#8217;t work as expected, specifically when it attempts to retrieve the AppID from the App Store Connect. The good news is that by the time this error occurs, your app has already been successfully compiled and the .pkg file created. You can use Apple’s <a href="https://www.google.com/url?sa=t&amp;source=web&amp;rct=j&amp;opi=89978449&amp;url=https://apps.apple.com/us/app/transporter/id1450874784%3Fmt%3D12&amp;ved=2ahUKEwiitNb4mo-QAxWphv0HHc48DjQQFnoECBcQAQ&amp;usg=AOvVaw2lhxdNCd0mHUPXUYrhF8U_" target="_blank" rel="noreferrer noopener">Transporter app</a> to complete the final step of uploading the .pkg file to App Store Connect.</li>
</ul>



<p>This issue has been fixed and the solution will be included in Xojo 2025r3. The update also improves how the App ID is retrieved by relying on the available provider listing. This rare issue could affect users whose Apple ID is associated with multiple publishing services, for example, if the same Apple ID is used for both app development and podcast publishing.</p>



<p>Once Xojo 2025r3 is released, the Publish feature will work as before on macOS Sequoia (and previous supported macOS versions), and it will also function properly with the new Xcode 26 toolchain &#8211; whether installed on Sequoia or on the latest macOS 26. Read more about Xojo Support for macOS 26 and iOS 26 on the <a href="https://blog.xojo.com/2025/09/15/xojo-support-for-macos-26-and-ios-26/" target="_blank" rel="noreferrer noopener">Xojo Blog</a>.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>DesktopTextArea Without Soft Wrapping Lines on macOS</title>
		<link>https://blog.xojo.com/2025/09/09/desktoptextarea-without-soft-wrapping-lines-on-macos/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 09 Sep 2025 19:31:26 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15083</guid>

					<description><![CDATA[When adding a DesktopTextArea to your macOS app, just drag it from the Library into a Window (or Container) in the layout editor of the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>When adding a DesktopTextArea to your macOS app, just drag it from the Library into a Window (or Container) in the layout editor of the Xojo IDE. It works out of the box with native macOS behavior. But what if you want to change that native behavior, like, for example, disabling soft wrapping? Keep reading to learn how.</p>



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



<p>On macOS, <a href="https://documentation.xojo.com/api/user_interface/desktop/desktoptextarea.html#desktoptextarea">DesktopTextArea</a> uses the native macOS control. When you need to tweak its behavior, <a href="https://documentation.xojo.com/api/language/declare.html#declare">Declares</a> can help. For example, by default text lines are soft-wrapped to the control’s width. But sometimes you may want to turn that off so each line displays in full, making the text easier to read line by line.</p>



<p>If you need to do just that, without resorting to other options because the use of a DesktopTextArea is what you really need to use, then put the following snippet of code into the Opening event handler for the DesktopTextArea instance:</p>



<p>If that’s exactly what you need to do and you want to stick with DesktopTextArea, just add the following code to the Opening event of your DesktopTextArea:</p>



<pre class="wp-block-code"><code>#If TargetMacOS Then
  // At this point we are getting really the handle to
  // the wrapping object: NSScrollView
  Var tAObj As Ptr = Me.Handle
  
  Declare Function Subviews Lib "AppKit" Selector "subviews" (obj As Ptr) As Ptr
  Declare Function ObjectAtIndex Lib "AppKit" Selector "objectAtIndex:" (obj As Ptr, index As Integer) As Ptr
  
  // We need to get the real NSTextView view that is set
  // inside the clip view set inside the NSScrollView
  Var subViewsFromScroll As Ptr = Subviews(tAObj)
  Var clipView As Ptr = ObjectAtIndex(subViewsFromScroll, 1)
  Var subViewsFromClipView As Ptr = Subviews(clipView)
  
  //…and here it is
  Var textAreaView As Ptr = ObjectAtIndex(subViewsFromClipView, 2)
  
  // At this point we have the real NSTextView from the wrapping NSScrollerView!
  
  Declare Function TextContainer Lib "AppKit" Selector "textContainer" (obj As Ptr) As Ptr
  Declare Sub SetWidthTracksTextView Lib "AppKit" Selector "setWidthTracksTextView:" (obj As Ptr, value As Boolean)
  Declare Sub SetContainerSize Lib "AppKit" Selector "setContainerSize:" (obj As Ptr, size As CGSize)
  Declare Sub SetMaxSize Lib "AppKit" Selector "setMaxSize:" (obj As Ptr, size As CGSize)
  
  // Retrieving the NSTextContainer
  Var tcObj As Ptr = TextContainer(textAreaView)
  SetWidthTracksTextView(tcObj, False)
  
  Var newSize As CGSize
  newSize.Width = 100000 // Arbitrary value… we only need to set it to a really high value!
  newSize.Height = 100000
  
  // And setting a new max width size to it.
  SetMaxSize(tAObj, newSize)
  
  // …and also using the same value for the size of the NSTextContainer
  SetContainerSize(tcObj, newSize)
#Endif</code></pre>



<p>The code above uses the <a href="https://developer.apple.com/documentation/corefoundation/cgsize?language=objc">CGSize</a> data type, a Struct added to the Window (though you’ll likely want to place it in a Module instead). It has two members:</p>



<ul class="wp-block-list">
<li>Width As Integer</li>



<li>Height As Integer</li>
</ul>



<p>We need to use this Data Type / Struct because some macOS framework methods from <a href="https://developer.apple.com/documentation/appkit/nsscrollview?language=objc">NSScrollView</a> and <a href="https://developer.apple.com/documentation/uikit/nstextcontainer?language=objc">NSTextContainer</a> expect it.</p>



<p>After adding the code, enable the &#8216;Has Horizontal Scrollbar&#8217; property in the Inspector for your DesktopTextArea. Run the app and you’ll see that soft wrapping is no longer applied!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1424" height="1082" src="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM.png" alt="" class="wp-image-15084" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM.png 1424w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM-1024x778.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-07-at-3.17.46 PM-768x584.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>



<p>What other customized behaviors have you added to macOS DesktopTextArea instances via Declares? Go ahead and <a href="https://forum.xojo.com/c/code-sharing/">share the code</a> so other users can benefit from them.</p>



<p>Happy 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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>4 Setting the Badge Color for Tabs on iOS</title>
		<link>https://blog.xojo.com/2025/08/20/4-setting-the-badge-color-for-tabs-on-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 20 Aug 2025 14:00:00 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<category><![CDATA[TabBar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15208</guid>

					<description><![CDATA[This is the final article in our series on customizing the appearance of the NavigationBar and TabBar. In this post, we’ll go a step further&#8230;]]></description>
										<content:encoded><![CDATA[
<p>This is the final article in our series on customizing the appearance of the <code>NavigationBar</code> and <code>TabBar</code>. In this post, we’ll go a step further and show how to change the default color of the tab badge which is red by default.</p>



<p>As you might expect, we’ll need a few more Declares to accomplish this. Continue reading to learn how!</p>



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



<p>Since we’re building on the example project from the first blog post in this series, I strongly recommend completing that post if you haven’t already, then continuing with the second and third articles before proceeding here.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="706" height="202" src="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-29-at-2.33.33-PM.png" alt="" class="wp-image-15209" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-29-at-2.33.33-PM.png 706w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-29-at-2.33.33-PM-300x86.png 300w" sizes="auto, (max-width: 706px) 100vw, 706px" /></figure>
</div>


<p>Select the &#8220;DeclaresForiOS&#8221; module and add a new method to it, using the following values for its signature in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarBadgeColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And put the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Var appearance As Ptr = BarAppearance(tabBar)

Declare Function StackedLayout Lib "UIKit" Selector "stackedLayoutAppearance" (obj As Ptr) As Ptr
Declare Function InlineLayout Lib "UIKit" Selector "compactInlineLayoutAppearance" (obj As Ptr) As Ptr
Declare Function NormalState Lib "UIKit" Selector "normal" (obj As Ptr) As Ptr

Var stackLayout As Ptr = StackedLayout(appearance)
Var inLayout As Ptr = InlineLayout(appearance)
Var normalState As Ptr = NormalState(stackLayout)
Var normalInlineState As Ptr = NormalState(inLayout)

Declare Sub SetBadgeColor Lib "UIKit" Selector "setBadgeBackgroundColor:" (obj As Ptr, value As Ptr)

SetBadgeColor(normalState, colorPtr)
SetBadgeColor(normalInlineState, colorPtr)

SetAppearance(tabBar, appearance)

If System.Version.MajorVersion &gt;= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<p>Next, select the Screen1 item in the Navigator and add a new property to it using the following values in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyTabBadgeColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<h3 class="wp-block-heading">Setting the Badge Text Color</h3>



<p>What’s next? I’m sure you guessed it! Now that we can customize the badge color, the default white text color on the badge may not always provide the best contrast.</p>



<p>Let’s add a new method to our &#8220;DeclaresForiOS&#8221; module with the following signature values in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>TabBarBadgeTextColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And type (or paste) the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Var appearance As Ptr = BarAppearance(tabBar)

Declare Function StackedLayout Lib "UIKit" Selector "stackedLayoutAppearance" (obj As Ptr) As Ptr
Declare Function InlineLayout Lib "UIKit" Selector "compactInlineLayoutAppearance" (obj As Ptr) As Ptr
Declare Function NormalState Lib "UIKit" Selector "normal" (obj As Ptr) As Ptr

Var stackLayout As Ptr = StackedLayout(appearance)
Var inLayout As Ptr = InlineLayout(appearance)

Var normalState As Ptr = NormalState(stackLayout)
Var normalInlineState As Ptr = NormalState(inLayout)

Declare Sub SetBadgeTextAttr Lib "UIKit" Selector "setBadgeTextAttributes:" (obj As Ptr, value As Ptr)

Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
Declare Function DictionaryWithObjectForKey Lib "UIKit" Selector "dictionaryWithObject:forKey:" (obj As Ptr, value As Ptr, key As CFStringRef) As Ptr

Var dict As Ptr = DictionaryWithObjectForKey( NSClassFromString("NSMutableDictionary") , colorPtr, "NSColor")

SetBadgeTextAttr(normalState, dict)
SetBadgeTextAttr(normalInlineState, dict)

SetAppearance(tabBar, appearance)

If System.Version.MajorVersion >= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<p>Next, select the <code>Screen1</code> item in the Navigator and add a new property to it using the following values in the Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyTabBadgeTextColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>Then, select the <code>Screen1.Opening</code> event handler and add these lines of code to it:</p>



<pre class="wp-block-code"><code>MyTabBadgeColor = New ColorGroup(Color.Green, Color.Blue)
MyTabBadgeTextColor = New ColorGroup(Color.Black, Color.Yellow)

Me.ParentTabBar.BadgeAt(0) = "33"
Me.ParentTabBar.BadgeAt(1) = "42"</code></pre>



<p>Lastly, select the <code>Screen1.AppearanceChanged</code> event handler and add this line of code at the end:</p>



<pre class="wp-block-code"><code>Me.ParentTabBar.TabBarBadgeColor = MyTabBadgeColor
Me.ParentTabBar.TabBarBadgeTextColor = MyTabBadgeTextColor</code></pre>



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



<p>Everything is set! Run the app on your iPhone or in the Simulator, and you’ll see each tab in the <code>TabBar</code> displaying its own badge with the custom background and text colors we configured in the Opening Event.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/1NJ7A3JHf60Fzo23AoY8dLA6m6phFSvpT/view?usp=sharing">this link</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></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 Coloring the Tab Bar on iOS</title>
		<link>https://blog.xojo.com/2025/08/19/3-coloring-the-tab-bar-on-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 19 Aug 2025 15:37:37 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<category><![CDATA[TabBar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15195</guid>

					<description><![CDATA[In the first two blog posts, we saw how important it is to customize the NavigationBar when theming your iOS app. However, that’s only part&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In the first two blog posts, we saw how important it is to customize the <code>NavigationBar</code> when theming your iOS app. However, that’s only part of the equation, especially if your app also uses a <code>TabBar</code>. In that case, you&#8217;ll likely want to customize not only the background color of the <code>TabBar</code>, but also the text color of the selected tab and the color used for the unselected tabs.</p>



<p>Continue reading to learn how to do all of this thanks to the powerful flexibility of Declares!</p>



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



<p>Before we dive in, keep in mind that we&#8217;re building on the example project introduced in the first blog post of this series. If you haven’t read it yet, I encourage you to start there. Then, follow up with the second post to make sure you&#8217;re fully up to speed and ready to continue adding even more color customization to your iOS screens!</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="704" height="220" src="https://blog.xojo.com/wp-content/uploads/2025/07/TabBar.png" alt="" class="wp-image-15196" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/TabBar.png 704w, https://blog.xojo.com/wp-content/uploads/2025/07/TabBar-300x94.png 300w" sizes="auto, (max-width: 704px) 100vw, 704px" /></figure>
</div>


<h3 class="wp-block-heading">Background Color for the TabBar</h3>



<p>In order to colorize the <code>TabBar</code> background, we need to add a new method to the &#8220;DeclaresForiOS&#8221; Module using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarBackgroundColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>Add the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub ConfigureWithOpaqueBackground Lib "UIKit" Selector "configureWithOpaqueBackground" (obj As Ptr)
Declare Sub SetBackgroundColor Lib "UIKit" Selector "setBackgroundColor:" (obj As Ptr, value As Ptr)
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Var appearance As Ptr = BarAppearance(tabBar)
SetBackgroundColor(appearance, colorPtr)

SetAppearance(tabBar, appearance)

If System.Version.MajorVersion >= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<p>Essentially, we’re setting the color by assigning it to the <code>backgroundColor</code> property of the <code>appearance</code> object associated with the <code>TabBar</code>.</p>



<h3 class="wp-block-heading">Setting the Text Color</h3>



<p>Now let’s add the code responsible for setting the text color of the selected tab in the <code>TabBar</code>. To do this, we just need to set the <code>tintColor</code> property. So, go ahead and add a new method to the &#8220;DeclaresForiOS&#8221; module with the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarTextColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And put the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Sub SetTintColor Lib "UIKit" Selector "setTintColor:" (obj As Ptr, value As Ptr)

SetTintColor(tabBar, colorPtr)</code></pre>



<h3 class="wp-block-heading">Setting Unselected Tabs Text Color</h3>



<p>To set the text color for unselected tabs, we’ll need to use a few additional Declares. This is because the color must be applied to the <em>normal</em> state of the <code>stackedLayoutAppearance</code> object from the TabBar’s appearance. Additionally, we need to set the same value for the <code>compactInlineLayoutAppearance</code>, which is used when the device is in landscape orientation.</p>



<p>Add a new method to the &#8220;DeclaresForiOS&#8221; Module using the following values for its signature:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>TabBarUnselectedTextColor</code></li>



<li><strong>Parameters:</strong> Extends tab As <code>iOSTabBar</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And add the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>Var tabController As Ptr = tab.ViewControllerHandle

If value = Nil Then Return

Declare Function GetTabBar Lib "UIKit" Selector "tabBar" (obj As Ptr) As Ptr
Var tabBar As Ptr = GetTabBar(tabController)

Var colorPtr As Ptr = ColorGroupToUIColor(value)

Declare Function BarAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

Declare Function StackedLayout Lib "UIKit" Selector "stackedLayoutAppearance" (obj As Ptr) As Ptr
Declare Function InlineLayout Lib "UIKit" Selector "compactInlineLayoutAppearance" (obj As Ptr) As Ptr
Declare Function NormalState Lib "UIKit" Selector "normal" (obj As Ptr) As Ptr

Var appearance As Ptr = BarAppearance(tabBar)
Var stackLayout As Ptr = StackedLayout(appearance)
Var inLayout As Ptr = InlineLayout(appearance)

Var normalState As Ptr = normalState(stackLayout)
Var normalInlineState As Ptr = NormalState(inLayout)

Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
Declare Function DictionaryWithObjectForKey Lib "UIKit" Selector "dictionaryWithObject:forKey:" (obj As Ptr, value As Ptr, key As CFStringRef) As Ptr

Var dict As Ptr = DictionaryWithObjectForKey( NSClassFromString("NSMutableDictionary") , colorPtr, "NSColor")

Declare Sub SetTextAttributes Lib "UIKit" Selector "setTitleTextAttributes:" (obj As Ptr, value As Ptr)

SetTextAttributes(normalState, dict)
SetTextAttributes(normalInlineState, dict)
SetAppearance(tabBar, appearance)

If System.Version.MajorVersion >= 15 Then
  Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)
  SetScrollEdgeAppearance(tabBar, appearance)
End If</code></pre>



<h3 class="wp-block-heading">Testing the TabBar Color</h3>



<p>Add a new screen to the project so that our example app includes at least two screens. You can do this by selecting Insert &gt; Screen from the IDE toolbar.</p>



<p>To test the new methods, we need the app to use a <code>TabBar</code>. To enable that, select the iPhoneLayout item in the Navigator. Then, in the Inspector Panel, locate the Content label and choose Tabs from the associated popup menu. Finally, set <code>Screen1</code> as the content for Tab 0 using the &#8220;Tab 0 Content&#8221; popup menu.</p>


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


<p>Next, with <code>Screen1</code> still selected in the Navigator, click on the &#8220;Tab 1&#8221; label in the Layout Editor. Then, in the Inspector<strong> </strong>Panel, use the popup menu next to the &#8220;Tab 1 Content&#8221; label to select <code>Screen2</code>.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1890" height="1262" src="https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1.png" alt="" class="wp-image-15198" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1.png 1890w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-300x200.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-1024x684.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-768x513.png 768w, https://blog.xojo.com/wp-content/uploads/2025/07/settingTab1-1536x1026.png 1536w" sizes="auto, (max-width: 1890px) 100vw, 1890px" /></figure>
</div>


<p>With <code>Screen1</code> still selected in the Navigator, add a new property to it using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyTabBarUnselectedTextColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>Now select the <code>Screen1.Opening</code> event handler and add this line of code:</p>



<pre class="wp-block-code"><code>MyTabBarUnselectedTextColor = New ColorGroup(Color.White, Color.LightGray)</code></pre>



<p>As the last step, select the <code>Screen1.AppearanceChanged</code> event handler and add this line of code:</p>



<pre class="wp-block-code"><code>Me.ParentTabBar.TabBarBackgroundColor = mNavigationBarColor
Me.ParentTabBar.TabBarTextColor = MyNavigationBarTextColor
Me.ParentTabBar.TabBarUnselectedTextColor = MyTabBarUnselectedTextColor</code></pre>



<p>All set! Now it’s time to run the example project in the Simulator or on your iPhone. You’ll see that the <code>TabBar</code> background color matches the one set for the <code>NavigationBar</code>, and the selected tab text color is consistent as well. The unselected tab text appears white in Light Mode and light gray in Dark Mode, reflecting the <code>ColorGroup</code> settings.</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationAndTabBar.mp4"></video></figure>



<p>As we’ve seen, Declares are a powerful way to tap into native iOS framework functions and routines. The most challenging part is often figuring out which ones to use since that requires digging into Apple’s developer documentation.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/1dN6mIe55FkUPEUl-_fanCMvXX3fdarr1/view?usp=sharing">this link</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></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationAndTabBar.mp4" length="145232" type="video/mp4" />

			</item>
		<item>
		<title>2 Coloring the Navigation Bar Text on iOS</title>
		<link>https://blog.xojo.com/2025/08/18/2-coloring-the-navigation-bar-text-on-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 18 Aug 2025 21:53:11 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15184</guid>

					<description><![CDATA[In a previous blog post, we covered how to set the color of the NavigationBar on a MobileScreen in iOS projects. However, if you&#8217;re customizing&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In a previous blog post, we covered how to set the color of the <code>NavigationBar</code> on a <code>MobileScreen</code> in iOS projects. However, if you&#8217;re customizing the Navigation Bar’s background, you&#8217;ll likely want control over the title text color and the color of any buttons added to it as well.</p>



<p>Continue reading to learn how to customize those elements too.</p>



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



<p>Just like in the previous blog post, we’ll need to use several Declares to access the necessary iOS framework functions and retrieve the underlying objects we want to modify.</p>



<p>If you haven’t followed the previous post yet, be sure to check it out first—we’ll be building on the same example project to add these new customizations.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="714" height="480" src="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-28-at-3.54.32-PM.png" alt="" class="wp-image-15188" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-28-at-3.54.32-PM.png 714w, https://blog.xojo.com/wp-content/uploads/2025/07/Screenshot-2025-07-28-at-3.54.32-PM-300x202.png 300w" sizes="auto, (max-width: 714px) 100vw, 714px" /></figure>
</div>


<p>Let&#8217;s add a new method to our previously created &#8220;DeclaresForiOS&#8221; Module using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>NavigationBarTextColor</code></li>



<li><strong>Parameters:</strong> Extends screen As <code>MobileScreen</code>, Assigns value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And add the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-code"><code>If value = Nil Then Return

Var controller As Ptr = screen.ViewControllerHandle

Declare Function NavigationController Lib "UIKit" Selector "navigationController" (controller As Ptr) As Ptr
Declare Function NavigationBar Lib "UIKit" Selector "navigationBar" (controller As Ptr) As Ptr

Var nc As Ptr = NavigationController(controller)
Var nv As Ptr = NavigationBar(nc)

Var colPtr As Ptr
colPtr = ColorGroupToUIColor(value)

Declare Function DictionaryWithObjectForKey Lib "UIKit" Selector "dictionaryWithObject:forKey:" (obj As Ptr, value As Ptr, key As CFStringRef) As Ptr

// https://developer.apple.com/documentation/foundation/nsclassfromstring(_:)?language=objc
Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr

Declare Function StandardAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetStandardAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)
Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)

Declare Sub SetTitleTextAttributedText Lib "UIKit" Selector "setTitleTextAttributes:" (obj As Ptr, value As Ptr)
Declare Sub SetLargeTitleTextAttributedText Lib "UIKit" Selector "setLargeTitleTextAttributes:" (obj As Ptr, value As Ptr)

Declare Sub SetTintColor Lib "UIKit" Selector "setTintColor:" (obj As Ptr, value As Ptr)

// We need to create a NSDictionary with the attribute we want to set on text for the NavigationBar Appearance
Var dict As Ptr = DictionaryWithObjectForKey(NSClassFromString("NSMutableDictionary"), colPtr, "NSColor")

Var appear As Ptr = StandardAppearance(nv)

// Setting the new appearance settings both for the regular-sized title
// and the Large one
SetTitleTextAttributedText(appear, dict)
SetLargeTitleTextAttributedText(appear, dict)

// And we apply the modified appearance to the StandardAppearance
SetStandardAppearance(nv, appear)

// And to the scrollEdgeAppearance if the app is run on iOS 15+
If (System.Version.MajorVersion >= 15.0) Then
   SetScrollEdgeAppearance(nv, appear)
End If

// The TintColor is applied on the text of the added buttons to the NavigationBar
// So we need to use the same color for them!
SetTintColor(nv, colPtr)</code></pre>



<p>And that&#8217;s all the code we need.</p>



<h3 class="wp-block-heading">Colorizing!</h3>



<p>Select the <code>Screen1</code> item in the Navigator and add a new property to it using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyNavigationBarTextColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>Now select the <code>Screen1.Opening</code> event and add the following line of code:</p>



<pre class="wp-block-code"><code>MyNavigationBarTextColor = New ColorGroup(Color.Yellow, Color.Red)</code></pre>



<p>Finally, select the <code>Screen1.AppearanceChanged</code> event handler and add the following line:</p>



<pre class="wp-block-code"><code>Me.NavigationBarTextColor = MyNavigationBarTextColor</code></pre>



<p>Run the example project, and you’ll see that the title text remains correctly displayed, even when switching between Light and Dark modes.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/1nLqY6Vaq2eeUr-qeTGpxA-LmMERYOSEk/view?usp=sharing">this link</a>.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>1 Coloring Your iOS App Navigation Bar</title>
		<link>https://blog.xojo.com/2025/08/11/1-coloring-your-ios-app-navigation-bar/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 11 Aug 2025 18:08:31 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<category><![CDATA[Navigation Bar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15175</guid>

					<description><![CDATA[This is the first of a series of 4 posts about customizing the Navigation and Tab Bars. One of the best ways to give your&#8230;]]></description>
										<content:encoded><![CDATA[
<p>This is the first of a series of 4 posts about customizing the Navigation and Tab Bars. One of the best ways to give your iOS app a custom look is by theming the Navigation Bar. While it’s possible to do this using a <code>ContainerControl</code> or a <code>Rectangle</code> with carefully applied constraints, there’s a better and more direct approach—using Declares.</p>



<p>Keep reading to learn how to style your Navigation Bar.</p>



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



<p>Declares in Xojo allow you to access functions and constants from compiled libraries and system frameworks such as those provided by iOS or third-party developers. They’re a powerful way to extend your app’s capabilities beyond what is available in the Xojo framework.</p>



<p>In this case, we’ll use Declares to tap into the native iOS APIs and customize the appearance of a <code>MobileScreen</code>&#8216;s <code>NavigationBar</code>, specifically to set its background color.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2411" height="940" src="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp.png" alt="" class="wp-image-15181" srcset="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp.png 2411w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-300x117.png 300w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-1024x399.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-768x299.png 768w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-1536x599.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBarComp-2048x798.png 2048w" sizes="auto, (max-width: 2411px) 100vw, 2411px" /></figure>



<p>Start by adding a new module to your existing or empty iOS project. I&#8217;ve named this <code>DeclaresForiOS</code>. Within this module, add a new method using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>NavigationBarColor</code></li>



<li><strong>Parameters:</strong> Extends Screen As <code>MobileScreen</code>, Assigns Value As <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>Add the following snippet of code in the Associated Code Editor:</p>



<pre class="wp-block-code"><code>// Getting the ViewController for the received Screen
Var controller As Ptr = Screen.ViewControllerHandle

// https://developer.apple.com/documentation/uikit/uiviewcontroller/navigationcontroller?language=objc
Declare Function NavigationController Lib "UIKit" Selector "navigationController" (controller As Ptr) As Ptr

// https://developer.apple.com/documentation/uikit/uinavigationcontroller/navigationbar?language=objc
Declare Function NavigationBar Lib "UIKit" Selector "navigationBar" (controller As Ptr) As Ptr

// Getting the NavigationBarController associated with the ViewController
Var nc As Ptr = NavigationController(controller)

// …and the NavigationBar itself from the NavigationBarController
Var nv As Ptr = NavigationBar(nc)

Var colPtr As Ptr
If value &lt;> Nil Then
  colPtr = ColorGroupToUIColor(value)
End If

// https://developer.apple.com/documentation/uikit/uinavigationbar/standardappearance?language=objc
Declare Function StandardAppearance Lib "UIKit" Selector "standardAppearance" (obj As Ptr) As Ptr
Declare Sub SetStandardAppearance Lib "UIKit" Selector "setStandardAppearance:" (obj As Ptr, value As Ptr)

// https://developer.apple.com/documentation/uikit/uinavigationbar/scrolledgeappearance?language=objc
Declare Sub SetScrollEdgeAppearance Lib "UIKit" Selector "setScrollEdgeAppearance:" (obj As Ptr, value As Ptr)

// https://developer.apple.com/documentation/uikit/uibarappearance/backgroundcolor?language=objc
Declare Sub SetBackgroundColor Lib "UIKit" Selector "setBackgroundColor:" (obj As Ptr, value As Ptr)

// Getting the StandardAppearance object from the NavigationBar
Var appear As Ptr = StandardAppearance(nv)

// Setting the BackgroundColor to the StandardAppearance…
SetBackgroundColor(appear, colPtr)

// …and assigning the Standard Appearance again to the NavigationBar
SetStandardAppearance(nv, appear)

// If our app is running on iOS >= 15.0, then we need to set
// the same appearance to the scrollEdgeAppearance attribute on the NavigationBar
if (System.Version.MajorVersion >= 15.0) then
  SetScrollEdgeAppearance(nv, appear)
end if</code></pre>



<p>As shown in the previous code, we’re calling the <code>ColorGroupToUIColor</code> method to convert a <code>ColorGroup</code> instance into a pointer to a valid <code>UIColor</code>. To support this, let’s add that helper method to our <code>DeclaresForiOS</code> module using the following values:</p>



<ul class="wp-block-list">
<li><strong>Method Name:</strong> <code>ColorGroupToUIColor</code></li>



<li><strong>Parameters:</strong> value As <code>ColorGroup</code></li>



<li><strong>Return Type:</strong> Ptr</li>



<li><strong>Scope:</strong> Global</li>
</ul>



<p>And type (or paste) the following snippet of code:</p>



<pre class="wp-block-code"><code>Var colorPtr As Ptr
Var c As Color

Select Case value.Mode
  
Case ColorGroup.Modes.Dual
  Var valueColors() As Color = value.Values
  If Color.IsDarkMode And valueColors.LastIndex > 0 Then
    c = valueColors(1)
  Else
    c = valueColors(0)
  End If
Case ColorGroup.Modes.Single
  Var valueColors() As Color = value.Values
  c = valueColors(0)
End Select

If colorPtr = Nil Then
  
  // https://developer.apple.com/documentation/foundation/nsclassfromstring(_:)?language=objc
  Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
  
  // https://developer.apple.com/documentation/uikit/uicolor/1621930-colorwithred
  Declare Function RGBA Lib "UIKit" selector "colorWithRed:green:blue:alpha:" (cls As Ptr, r As Double, g As Double, b As Double, a As Double) As Ptr
  
  colorPtr = RGBA(NSClassFromString("UIColor"), c.Red/255, c.Green/255, c.Blue/255, 1-(c.Alpha/255))
  
End If

return colorPtr</code></pre>



<h3 class="wp-block-heading">Let&#8217;s Color That!</h3>



<p>And that is all the code we need! Now select the <code>Screen1</code> item in the Navigator for the iOS project and add the following property to it:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> <code>MyNavigationBarColor</code></li>



<li><strong>Type:</strong> <code>ColorGroup</code></li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>With the Screen1 still selected in the Navigator, add the Opening event to it and add the following line of code:</p>



<pre class="wp-block-code"><code>MyNavigationBarColor = New ColorGroup( color.Red, color.Yellow )</code></pre>



<p>As the last step, add the <code>AppearanceChanged</code> event to the <code>Screen1</code> item; and add the following line of code to it:</p>



<pre class="wp-block-code"><code>me.NavigationBarColor = MyNavigationBarColor</code></pre>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBariOSSwitchingColor.mp4"></video></figure>



<p>Make sure the &#8220;Has Navigation Bar&#8221; attribute is enabled in the Inspector for <code>Screen1</code>, then run the project. If your Simulator or device is set to Light Mode, the Navigation Bar will appear red; if it’s in Dark Mode, it will appear yellow. You can switch between Light and Dark modes to see the Navigation Bar color transition between the two colors defined in your <code>ColorGroup</code>.</p>



<p>Download the example project from <a href="https://drive.google.com/file/d/15Seqvo8FKx_nYiMSHc5tecS2OC-HcnI7/view?usp=sharing">this link</a>.</p>



<p>Happy 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>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/07/NavigationBariOSSwitchingColor.mp4" length="133233" type="video/mp4" />

			</item>
		<item>
		<title>Year of Code 2025: July Project, Charting</title>
		<link>https://blog.xojo.com/2025/07/10/year-of-code-2025-july-project-charting/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 10 Jul 2025 18:32:31 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Charts]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15070</guid>

					<description><![CDATA[July&#8217;s Year of Code theme is charting.&#160;Charting uses the DesktopChart, WebChart or MobileChart controls to make your data stand out with visualizations like Bar, Bubble,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>July&#8217;s Year of Code theme is charting.&nbsp;Charting uses the DesktopChart, WebChart or MobileChart controls to make your data stand out with visualizations like Bar, Bubble, Pie, Scatter charts and more.</p>



<p>For this project, I created a small iPhone app to track my expenses &#8211; something I personally needed.  While it&#8217;s designed for tracking holiday and travel spending, it works just as well for managing general monthly expenses.</p>



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



<p>Far from perfect, but useful for the described scenarios, this iPhone app lets the user set a trip location, add a description and even define a budget. That way, they can check in at any time to see how things are going during a trip or when tracking general monthly expenses. (It doesn’t make much sense to offer this kind of app for iPad.)</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1195" height="2387" src="https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen.png" alt="" class="wp-image-15071" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen.png 1195w, https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen-150x300.png 150w, https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen-513x1024.png 513w, https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen-768x1534.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen-769x1536.png 769w, https://blog.xojo.com/wp-content/uploads/2025/06/1-MainScreen-1025x2048.png 1025w" sizes="auto, (max-width: 1195px) 100vw, 1195px" /></figure>



<p>When it comes to entering new expenses, I wanted to keep it as simple as possible with minimal input and just a few taps.  So, aside from entering the amount and the place where the expense occurred, the app automatically captures the geolocation. This helps me better remember places like restaurants, gas stations or points of interest I might want to stop at or visit again when traveling the same route.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1191" height="2371" src="https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense.png" alt="" class="wp-image-15072" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense.png 1191w, https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense-151x300.png 151w, https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense-514x1024.png 514w, https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense-768x1529.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense-772x1536.png 772w, https://blog.xojo.com/wp-content/uploads/2025/06/2-AddingTripExpense-1029x2048.png 1029w" sizes="auto, (max-width: 1191px) 100vw, 1191px" /></figure>



<p>When tracking monthly expenses, the app lets you duplicate existing entries so details like the expense location remain the same, and you only need to enter the new amount. This is especially handy if you tend to refuel at the same gas station or do your weekly grocery shopping at the same store.</p>



<p>So, what about charts? Honestly, this area has plenty of room for improvement and could eventually include a wide range of stats and visualizations. But for this initial release, I kept it simple to meet my own needs. In addition to the basic &#8216;Total Budget vs. Current Expenses&#8217; stats, the app includes a Pie chart that breaks down spending by category.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1217" height="2365" src="https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed.png" alt="" class="wp-image-15073" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed.png 1217w, https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed-154x300.png 154w, https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed-527x1024.png 527w, https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed-768x1492.png 768w, https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed-790x1536.png 790w, https://blog.xojo.com/wp-content/uploads/2025/06/4-Stats-Displayed-1054x2048.png 1054w" sizes="auto, (max-width: 1217px) 100vw, 1217px" /></figure>



<p>Of course, you can <a href="https://github.com/aprendexojo/VoyageExpenses" target="_blank" rel="noreferrer noopener">download the full source code here</a> and adapt or improve it so it suits your own needs.</p>



<p>Want to give it a try? The iOS app is available for free on the App Store: <a href="https://apple.co/3EGL33r" target="_blank" rel="noreferrer noopener">https://apple.co/3EGL33r</a></p>



<p>VoyageExpenses is built entirely with Xojo. It&#8217;s 100% Xojo code, with only two small exceptions where Declares were needed. It was published to the App Store using the Publish feature introduced in Xojo 2025r1.</p>



<p>Visit the <a href="https://documentation.xojo.com/api/user_interface/controls/chart.html" target="_blank" rel="noreferrer noopener">Xojo Docs</a> to learn more about using charts in Xojo. Visual elements like charts can make the data in your apps more memorable and impactful.&nbsp;We&#8217;ve written extensively on charting throughout the <a href="https://blog.xojo.com/tag/charts/" target="_blank" rel="noreferrer noopener">Xojo Blog.</a></p>



<p><strong>Year of Code Project</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/">Year of Code: Kickoff</a></li>



<li><a href="https://blog.xojo.com/2025/01/15/year-of-code-2025-january-project/" target="_blank" rel="noreferrer noopener">January Project: Desktop Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/year-of-code-2025-january-project-sharing/83927" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/02/11/year-of-code-2025-february-project/">February Project: Database Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/2025-year-of-code-february" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/03/05/year-of-code-2025-march-project-web-apps/">March Project: Web Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-march/84474?u=alyssa_foley">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/04/08/year-of-code-2025-april-project-user-interface/">April Project: User Interface</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-april-user-interface/84926">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/05/07/year-of-code-2025-may-project-mobile-apps/">May Project: Mobile Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-may-is-mobile/85272">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/06/10/year-of-code-2025-june-project-cross-platform-code-class/">June Project: Code Sharing</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-june-is-code-sharing/85612">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/07/10/year-of-code-2025-july-project-charting/">July Project: Charting</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-july-is-charting/85896">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/08/07/year-of-code-2025-august-project-console-apps/">August Project: Console Apps</a> | <a href="https://forum.xojo.com/t/august-2025-year-of-code-console-apps/86203">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/09/08/year-of-code-2025-september-project-games/">September Project: Games</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-septgamer">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/10/13/year-of-code-2025-october-project-multi-platform-communication/">October Project: Multi-Platform</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-october-multi-platform-communication/86717">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/">November Project: PDF</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-november-pdf/86969">Forum Discussion</a></li>
</ul>



<p><strong>How to Play:</strong></p>



<p>Each month we&#8217;ll announce a new theme and share an example project of our own. Share your projects to the Xojo Forum thread for that month via GitHub (all the links you need are posted above ↑ ). Learn how to use <a href="https://blog.xojo.com/2024/04/02/using-xojo-and-github/">Xojo and GitHub</a>.</p>



<p><strong>The Prizes:</strong></p>



<p>Monthly winners get $100 at the Xojo store. Every month you submit a project is another chance to win the grand prize. The grand prize is $250 cash plus a Xojo Pro license and a year of GraffitiSuite and will be announce in December. Learn more about the <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/#prizes">prizes</a>.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>MobileImagePicker Gets More Flexible</title>
		<link>https://blog.xojo.com/2025/07/08/mobileimagepicker-gets-more-flexible/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 18:01:00 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r2]]></category>
		<category><![CDATA[MobileImagePicker]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14938</guid>

					<description><![CDATA[For years, the MobileImagePicker control has allowed users to choose between the Camera and Photos as the source. So far, so good—but there was one&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For years, the MobileImagePicker control has allowed users to choose between the Camera and Photos as the source. So far, so good—but there was one major limitation: when the source was set to Photos, users could only select one photo at a time from an album. Not anymore.</p>



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



<h3 class="wp-block-heading">Select Multiple Images</h3>



<p>Starting with Xojo 2025r2, we’ve updated the MobileImagePicker for iOS to use a more modern controller under the hood. As a result, users can now select multiple photos at once (depending on the needs of your app) and also take advantage of additional features available in the new image selector.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1179" height="2556" src="https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker.png" alt="" class="wp-image-14940" srcset="https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker.png 1179w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker-138x300.png 138w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker-472x1024.png 472w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker-768x1665.png 768w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker-709x1536.png 709w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePicker-945x2048.png 945w" sizes="auto, (max-width: 1179px) 100vw, 1179px" /></figure>



<p>In addition, as a result of this change, we’re now able to capture and provide more complete EXIF metadata for each selected image.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1002" height="962" src="https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePickerMetadata.png" alt="" class="wp-image-14939" srcset="https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePickerMetadata.png 1002w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePickerMetadata-300x288.png 300w, https://blog.xojo.com/wp-content/uploads/2025/05/MobileImagePickerMetadata-768x737.png 768w" sizes="auto, (max-width: 1002px) 100vw, 1002px" /></figure>



<p>The best part is, you don’t need to change a single line of code to take advantage of these new capabilities. However, due to the asynchronous nature of iOS, the <code>Selected</code> event handler of the MobileImagePicker will now fire once for each image the user selects. Be sure to account for that in your app’s logic. You may want to check out the updated &#8220;MobilePicture-Metadata&#8221; example project for guidance.</p>



<h3 class="wp-block-heading">Choose Your Camera Source</h3>



<p>When <code>MobileImagePicker.Source</code> was set to <code>Camera</code>, it defaulted to the device’s rear camera, which works well for most scenarios. However, some apps may need to use the front camera by default. While users could always switch cameras with a tap, it’s even better if your app can save them that extra step.</p>



<p>Now, if your app requires the front camera by default, you can set the source to the new enum value: <code>Source.FrontCamera</code>.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Share More with the Improved MobileSharingPanel</title>
		<link>https://blog.xojo.com/2025/07/08/share-more-with-the-improved-mobilesharingpanel/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 18:01:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r2]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14943</guid>

					<description><![CDATA[Starting with Xojo 2025r2, you can share more than ever before using the MobileSharingPanel. Keep reading to discover the exciting improvements waiting for you! In&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2025r2, you can share more than ever before using the MobileSharingPanel. Keep reading to discover the exciting improvements waiting for you!</p>



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



<p>In previous releases, the MobileSharingPanel control allowed your app to share a single picture, a URL, or text with any registered iOS system service or app. Now, you can share multiple pictures at once and also share as many files as you want (including entire folders)!</p>



<p>To share multiple pictures, we’ve overloaded the <code>SharingPanel.SharePicture</code> method so its first parameter can accept an array of pictures. It’s that simple. When the panel appears, the same action will apply to the whole group.</p>



<p>For sharing files, you now have two methods available:</p>



<pre class="wp-block-preformatted">MobileSharingPanel.ShareFile(file As FolderItem, parentScreen As MobileScreen = Nil, parentControl As MobileUIControl = Nil)<br><br>MobileSharingPanel.ShareFile(files() As FolderItem, parentScreen As MobileScreen = Nil, parentControl As MobileUIControl = Nil)</pre>



<p>The first method is designed to share a single <code>FolderItem</code> instance. If that <code>FolderItem</code> points to a folder, the entire contents of the folder will be shared.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1179" height="2556" src="https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles.png" alt="" class="wp-image-14944" srcset="https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles.png 1179w, https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles-138x300.png 138w, https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles-472x1024.png 472w, https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles-768x1665.png 768w, https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles-709x1536.png 709w, https://blog.xojo.com/wp-content/uploads/2025/05/SharingFiles-945x2048.png 945w" sizes="auto, (max-width: 1179px) 100vw, 1179px" /></figure>



<p>The second method accepts an array of <code>FolderItem</code> instances as its first parameter. This is likely the best choice when your app needs to share a group of items from different sources, offering greater flexibility.</p>



<p>Overall, the enhanced SharingPanel is now more powerful and versatile. We’re excited to see how you’ll put it to use in your mobile apps!</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>iOSLayoutConstraints … Less Constrained</title>
		<link>https://blog.xojo.com/2025/07/08/ioslayoutconstraints-less-constrained/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 18:01:00 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r2]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14948</guid>

					<description><![CDATA[Until now, the only way to work with named iOSLayoutConstraint instances was by assigning a name in the Inspector Panel. This allowed you to reference&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Until now, the only way to work with named <code>iOSLayoutConstraint</code> instances was by assigning a name in the Inspector Panel. This allowed you to reference them later in code, for example, to deactivate, reactivate, or remove them from a <code>MobileScreen</code> or <code>MobileUIControl</code>. Very handy!</p>



<p>But what about <code>iOSLayoutConstraint</code> instances created in code? Starting with Xojo 2025r2, that’s been improved! Keep reading to learn how.</p>



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



<p>Of course, there have always been ways to manage <code>iOSLayoutConstraint</code> instances created in code (for example, by storing references to them) so you could interact with them just like the named constraints created at design time. But with Xojo 2025r2, we’ve made that even easier.</p>



<p>The <code>MobileScreen.AddConstraint</code> and <code>MobileUIControl.AddConstraint</code> methods now include an optional name parameter. This means you can assign a name to constraints added in code and later activate, deactivate, or remove them by name, just like design-time constraints!</p>



<p>Of course, you can’t assign the same name to multiple constraint instances on the same screen or UI control. If you try to do so, an <code>UnsupportedOperationException</code> will be raised.</p>



<p>We’ve also overloaded the <code>MobileScreen.RemoveConstraint</code> method to accept a <code>String</code> parameter, allowing you to remove a named constraint directly. No need to keep track of <code>iOSLayoutConstraint</code> instances using property references or other custom methods.</p>



<p>All in all, starting with Xojo 2025r2, you no longer need to implement your own logic to manage constraint instances. This makes it much easier to build responsive, polished UIs that adapt well across platforms and device orientations.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>A Guide to Managing Multiple Apple Developer Accounts in Xojo 2025r2</title>
		<link>https://blog.xojo.com/2025/07/08/a-guide-to-managing-multiple-apple-developer-accounts-in-xojo-2025r1/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 18:01:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r2]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Mac App Store]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15064</guid>

					<description><![CDATA[Usually, you only need to manage one Apple Developer Account when publishing your macOS or iOS apps. However, as many Xojo users have pointed out,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Usually, you only need to manage one Apple Developer Account when publishing your macOS or iOS apps. However, as many Xojo users have pointed out, there are situations where you need to work with multiple Apple Developer Accounts &#8211; perhaps you are publishing macOS apps for different companies (with different Team IDs). So, how do you handle this using the App Specific Password setup introduced in Xojo 2025r1?</p>



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



<p>The good news is that starting with Xojo 2025r2, you’ll be able to manage multiple Apple Developer Accounts! By default, everything will work just as it did in Xojo 2025r1. That means Xojo uses a global App Specific Password tied to the Apple Developer Account login (usually an email), the Team ID, and the password generated at <a class="" href="http://appleid.apple.com">appleid.apple.com</a>.</p>



<p>So, if you don’t make any changes, everything will continue to work as before for your existing and new macOS projects published to the Mac App Store. But if you need to publish other macOS projects under a different Apple Developer Account or Team ID, you’ll need to create a new App Specific Password at <a class="" href="http://appleid.apple.com">appleid.apple.com</a> (giving it a unique name), enter the new credentials in Xojo’s App Specific Password setup dialog, and then enable the “Save with Project” checkbox.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1524" height="940" src="https://blog.xojo.com/wp-content/uploads/2025/06/SpecificPasswordSetup.png" alt="" class="wp-image-15065" srcset="https://blog.xojo.com/wp-content/uploads/2025/06/SpecificPasswordSetup.png 1524w, https://blog.xojo.com/wp-content/uploads/2025/06/SpecificPasswordSetup-300x185.png 300w, https://blog.xojo.com/wp-content/uploads/2025/06/SpecificPasswordSetup-1024x632.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/06/SpecificPasswordSetup-768x474.png 768w" sizes="auto, (max-width: 1524px) 100vw, 1524px" /></figure>



<p>When you do this, the App Specific Password will be saved with the project itself, and its settings will be used whenever you click the Publish button.</p>



<p>If you ever need to switch back to using the Global App Specific Password for that project, select the “Global” option from the popup menu at the top of the same dialog.</p>



<p>And of course, don’t forget: if you’re publishing macOS apps using multiple Apple Developer Accounts, make sure all the necessary certificates for those accounts are installed in your Mac Keychain!</p>



<p>Thank you to everyone who provided feedback and suggestions about this feature!</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Build Your First iOS App with Xojo: 10 Practical Steps</title>
		<link>https://blog.xojo.com/2025/05/16/build-your-first-ios-app-with-xojo-10-practical-steps/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 16 May 2025 15:45:00 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[App Marketing]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[App Store Connect]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Developer Marketing]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Mobile]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14876</guid>

					<description><![CDATA[Xojo is an extremely useful, fast and fun development environment for building your first (or next) iOS app. In this article, I offer a series&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo is an extremely useful, fast and fun development environment for building your first (or next) iOS app. In this article, I offer a series of practical steps to guide you from idea to app.</p>



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



<h2 class="wp-block-heading">1. Define Your Idea</h2>



<p>Start by summarizing your app’s purpose in a single, clear sentence. The more concise it is, the better defined your objective will be. This clarity will help guide your screen designs, navigation structure and code architecture.</p>



<p>This sentence can also double as your app’s short description in App Store Connect.</p>



<p>Focus on the essential features that form your app’s <a href="https://en.wikipedia.org/wiki/Minimum_viable_product">Minimum Viable Product</a> (MVP). It’s easy to get sidetracked by new ideas during development. Resist the urge! Instead, keep a list of potential features for future updates and base priorities on user feedback.</p>



<h2 class="wp-block-heading">2. Choose The Platform(s)</h2>



<p>Xojo supports both iPhone and iPad, but your app doesn’t have to. Choose the device type that best fits your app’s use case.</p>



<ul class="wp-block-list">
<li>iPhone apps often support quick, task-based interactions.</li>



<li>iPad apps are better suited to immersive, content-rich experiences.</li>
</ul>



<p>To target a specific device only, set the unused layout (iPhone or iPad) to “None” in the App item’s Inspector Panel.</p>



<p>You’ll also need to decide the minimum iOS version to support. Xojo currently defaults to iOS 14.0, but as of writing, over 60% of users are on iOS 18 or later.</p>



<h2 class="wp-block-heading">3. Prototyping</h2>



<p>Xojo’s visual layout editor makes it easy to dive in designing your app. But take time to prototype your app first, especially if it has more than basic functionality.</p>



<p>Use tools like Figma or MockUp, or simply sketch your ideas with pencil and paper. Choose whatever helps you plan best and clearly.</p>



<p>Also, review Apple’s <a href="https://developer.apple.com/design/human-interface-guidelines/">Human Interface Guidelines</a> to align your app with native iOS expectations.</p>



<p>When designing in Xojo, you can fine-tune layout behavior using the <a href="https://documentation.xojo.com/api/ios/ioslayoutconstraint.html#ioslayoutconstraint">iOSLayoutConstraint</a> class to adapt to orientation and screen size changes at runtime.</p>



<h2 class="wp-block-heading">4. Database Design</h2>



<p>Most apps use a database. For local storage on iOS, use <a href="https://documentation.xojo.com/api/databases/sqlitedatabase.html#methods">SQLiteDatabase</a>, and save your database file in <a href="https://documentation.xojo.com/api/files/specialfolder.html#specialfolder">SpecialFolder.Documents</a>.</p>



<p>Two key best practices:</p>



<ul class="wp-block-list">
<li>Add a Metadata table to track the database schema version. </li>



<li>Create a custom <a href="https://blog.xojo.com/2025/02/05/customize-and-extend-core-databases-functionality/">SQLiteDatabase subclass</a> to manage all read/write operations in one place.</li>
</ul>



<p>This setup allows you to always know which version is installed on the user&#8217;s device and to react accordingly as your app evolves.</p>



<h2 class="wp-block-heading">5. Graphic Resources</h2>



<p>For icons, buttons and tab bar images, use <a href="https://documentation.xojo.com/api/graphics/picture.html#picture-systemimage">Picture.SystemImage</a> with symbols from Apple’s <a href="https://developer.apple.com/sf-symbols/">SF Symbols</a> app. These scale beautifully across devices and adapt to light/dark mode. Just ensure compatibility with your minimum iOS version.</p>



<p>When using custom images, add them at multiple resolutions for optimal display across all screen sizes.</p>



<p>Typography also matters. Use system <a href="http://www.iosfont.com">fonts</a> thoughtfully, ideally no more than two font families. Vary sizes and weights to establish content hierarchy. Keep text readable with a minimum font size of 11pt.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Tip: When testing in the Simulator, set the window to physical size (Simulator &gt; Window &gt; Physical Size) to preview real-world readability.</p>
</blockquote>



<h2 class="wp-block-heading">6. Localization and Accessibility</h2>



<p>Nothing prevents you from publishing an app in a single language, whether it&#8217;s your native language or English; but supporting multiple languages can increase downloads by over 100x.</p>



<p>Start localizing early to avoid design issues later. Add a module to your Xojo project with localized String constants for all app text, and enable the “Localized” option for each one.</p>



<p>Suggested languages (in order of impact):</p>



<p>Core: English</p>



<p>High-impact additions: Chinese, Spanish, German, French, Japanese, Italian, Portuguese, Russian, Korean</p>



<p>Also, localize accessibility labels and App Store listings, including screenshots and descriptions, for each supported language.</p>



<h2 class="wp-block-heading">7. Testing the App</h2>



<p>Xojo provides multiple ways to test your app, both from a design and user experience perspective, as well as from a functionality perspective:</p>



<ul class="wp-block-list">
<li><strong>Simulators</strong>: Ideal for design, layout and localization testing. You can also use them to take App Store screenshots.</li>



<li><strong>On-device Debugging</strong>: Offers realistic input experience and access to hardware-only features.</li>



<li><strong>Build to Device</strong>: Lets you run the app outside the debugger, simulating real-world use.</li>
</ul>



<p>Once you’ve finished fixing bugs in your code and app design, move on to testing in the real world by compiling your app and using Xcode to copy that bundle to a physical device. Testing like this, you&#8217;ll likely find some optimizations, especially around design and usability.</p>



<p>TestFlight is your gateway to external beta testers. After uploading a build to App Store Connect, create a public link to invite testers. Remember to increment the version number with each new build.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Tip: Add <code>ITSAppUsesNonExemptEncryption = False</code> in your Property List to streamline build approvals.</p>
</blockquote>



<h2 class="wp-block-heading">8. Publish it!</h2>



<p>Publishing with Xojo is straightforward. The most time-consuming step is preparing your App Store Connect listing including text, artwork, screenshots, keywords and possibly localized pages. Read more about this in my earlier post <em><a href="https://blog.xojo.com/2025/03/25/how-to-publish-macos-and-ios-apps-to-the-app-store-directly-from-xojo/">How to Publish macOS and iOS Apps to the App Store Directly from Xojo</a></em>.</p>



<p>Make sure you select the correct build when submitting your app for review.</p>



<h2 class="wp-block-heading">9. Marketing</h2>



<p>Something you should be doing simultaneously is preparing the related materials to introduce your app to the world. Start your marketing efforts early. A simple website can significantly boost discoverability. Use it to:</p>



<ul class="wp-block-list">
<li>Provide tutorials and FAQs</li>



<li>Link to App Store and social media</li>



<li>Highlight features and updates</li>
</ul>



<p>Consider creating a YouTube channel for app demos and support videos, and maintain active social media profiles to stay visible.</p>



<p>Don&#8217;t forget to take advantage of the <a href="https://toolbox.marketingtools.apple.com">Marketing tools provided by Apple</a> to help you create badges, assets, links and even QR codes to promote your app.</p>



<h2 class="wp-block-heading">10. The Next Steps …</h2>



<p>After launch, gather user feedback and track any bugs that slipped through. At this stage, it’s common to manage:</p>



<ul class="wp-block-list">
<li>A public release (on the App Store)</li>



<li>A development version (next major update)</li>
</ul>



<p>Save your Xojo iOS project in text format and use a version control system. This helps you manage multiple branches and collaborate efficiently.</p>



<h2 class="wp-block-heading">To Summarize</h2>



<p>Even the simplest iOS apps require a fair amount of time and effort, but thanks to Xojo, both aspects are significantly reduced.</p>



<p>What iOS apps have you created with Xojo? What&#8217;s your methodology or any tips you&#8217;d like to share? Feel free to comment on the <a href="http://forum.xojo.com">Xojo forum</a>!</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Updating macOS Keychain Passwords</title>
		<link>https://blog.xojo.com/2025/04/24/updating-macos-keychain-passwords/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Thu, 24 Apr 2025 15:00:00 +0000</pubDate>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[macOS]]></category>
		<category><![CDATA[Passwords]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14820</guid>

					<description><![CDATA[The Keychain is a system-wide feature on macOS that securely stores account passwords for applications. Until Xojo 2025r1, updating the password for an existing KeychainItem—that&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The Keychain is a system-wide feature on macOS that securely stores account passwords for applications. Until Xojo 2025r1, updating the password for an existing KeychainItem—that is, for a given Service Name—required first removing the item from the Keychain and then recreating it from scratch. Not exactly the most efficient process. But with the introduction of the KeychainItem.UpdatePassword method in 2025r1, things have gotten much easier. Read on to see how you can take advantage of this new functionality.</p>



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



<p>Starting with 2025r1, there’s no longer any need to delete an existing Keychain item just to update its password. All you need is a <a href="https://documentation.xojo.com/api/macos/keychainitem.html#keychainitem">KeychainItem</a> instance with a non-zero Handle, in other words, a properly initialized item. And the best way to get a reference to an existing KeychainItem is by using the System.Keychain.FindPassword method. For example, the following code snippet from a method with the signature FindPassword(serviceName As String) As KeychainItem:</p>



<pre class="wp-block-code"><code>Var itemToFind As New KeychainItem
Var password As String

// Name to find
ItemToFind.ServiceName = serviceName

// Get the password
password = System.Keychain.FindPassword(itemToFind)

Return itemToFind

Catch e As KeychainException
  Return Nil</code></pre>



<p>This retrieves the password for a given Keychain item stored under the Service Name passed as the serviceName parameter. If the call to System.Keychain.FindPassword raises a KeychainException, it means there&#8217;s no password stored in the Keychain for that Service Name so we return Nil. But if the method successfully retrieves a password, it means we have a valid, properly initialized KeychainItem we can use to call UpdatePassword.</p>



<p>For example, create a new method with the following signature:</p>



<pre class="wp-block-code"><code>Public Sub CreatePassword(pass As String, label As string, serviceName As String)
  // Let's see if we have a password for the item already.
  // If that is the case, we need to update it instead of
  // creating it!
  
  Var itemToFind As KeychainItem = FindPassword(serviceName)
  
  // If we don't get a Nil KeychainItem, that means that we should
  // update the password for such KeychainItem, instead of creating a new one!
  
  If itemToFind &lt;> Nil Then
     itemToFind.UpdatePassword(pass)
  Else
    // We got a Nil KeychainItem… what means that there is not
    // such item in the user Keychain yet, so let's create it.
    
    itemToFind = New KeychainItem
    itemToFind.Label = label
    itemToFind.ServiceName = serviceName
    System.Keychain.AddPassword(itemToFind, pass)
  End If
  
  Catch e As KeychainException
    MessageBox("Keychain error: " + e.Message)
    
End Sub</code></pre>



<p>As you can see, this method takes three string parameters: the password you want to set or update, the label to use for the Keychain item (particularly useful when adding a new password for a given Service Name) and the Service Name itself, which is associated with the password.</p>



<p>The first thing this method does is call the FindPassword method we saw earlier. If it returns a non-nil object, we simply update the password. However, if the FindPassword method returns a nil object, we create a new KeychainItem from scratch using the provided label and serviceName parameters, then add the new password to the user&#8217;s Keychain.</p>



<p><a href="https://drive.google.com/file/d/18CvvlDvNi0mFRqCscrxmfklpZo3lYKY3/view?usp=share_link">Download this example project</a> to experiment adding, deleting and/or updating passwords to your macOS Keychain.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The MobileColorPicker Control Now Available for iOS Projects</title>
		<link>https://blog.xojo.com/2025/03/25/the-mobilecolorpicker-control-now-available-for-ios-projects/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:34:19 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[Color]]></category>
		<category><![CDATA[Mobile]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14550</guid>

					<description><![CDATA[Starting with Xojo 2025r1, you&#8217;ll find a new control in the iOS Library panel: MobileColorPicker. This control brings a native color-picking experience to your projects,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2025r1, you&#8217;ll find a new control in the iOS Library panel: MobileColorPicker. This control brings a native color-picking experience to your projects, allowing users to choose from a wide range of colors, save their favorites, or use a &#8216;<a href="https://en.wikipedia.org/wiki/Loupe">loupe</a>&#8216; to select a color directly from the screen.</p>



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



<p>Using the new control is similar to how you would use the same type of control in Desktop projects. For example, drag the control from the Library panel and drop it onto the Layout Editor of a Screen, where it will be added to the Tray area.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2500" height="1592" src="https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM.png" alt="" class="wp-image-14551" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM.png 2500w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM-300x191.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM-1024x652.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM-768x489.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM-1536x978.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.07.11 PM-2048x1304.png 2048w" sizes="auto, (max-width: 2500px) 100vw, 2500px" /></figure>
</div>


<p>Next, you need to call the Show method on the MobileColorPicker instance to display it to the user, and implement the ColorSelected event handler to capture the selected color.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> This control&#8217;s functionality is available only when the app is run on devices with iOS 14 or later (the minimum recommended version for iOS projects starting with Xojo 2025r1).</p>
</blockquote>



<h2 class="wp-block-heading">Modal vs Popover</h2>



<p>When calling the Show method without parameters on the MobileColorPicker instance, it will be displayed as a modal panel on both iPhone and iPad devices. If you provide the ParentControl parameter, the MobileColorPicker will be shown as a popover panel on iPad devices. However, on iPhone devices, it will still be displayed as a modal dialog, regardless of the ParentControl parameter.</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/02/Simulator-Screen-Recording-iPad-Air-5th-generation-2025-02-26-at-12.10.40.mp4"></video></figure>



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



<p>The addition of the MobileColorPicker control in Xojo 2025r1 simplifies color selection in iOS apps, providing a native and intuitive experience for your users. This control makes it easier than ever to implement color pickers in your iOS projects. So, give it a try in your next app, and enhance the user experience!</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>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/02/Simulator-Screen-Recording-iPad-Air-5th-generation-2025-02-26-at-12.10.40.mp4" length="321491" type="video/mp4" />

			</item>
		<item>
		<title>Property List Editor, Integrated in the IDE</title>
		<link>https://blog.xojo.com/2025/03/25/property-list-editor-integrated-in-the-ide/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:34:12 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r1]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[App Store Connect]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac App Store]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14554</guid>

					<description><![CDATA[Starting with Xojo 2025r1, a new Property List Editor is available for both Desktop (macOS) and iOS projects under Build Settings &#62; macOS and Build&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2025r1, a new Property List Editor is available for both Desktop (macOS) and iOS projects under Build Settings &gt; macOS and Build Settings &gt; iOS. This editor simplifies the process of adding custom entries that your app may require, beyond those automatically included by Xojo.</p>



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



<p>Some projects require additional entries in the generated Info.plist file. Previously, the only way to include these entries was to create the file manually using an external text editor, then drag and drop it into the project’s Navigation area. This allowed its contents to be merged with the entries automatically generated by Xojo in the final Info.plist file within the app bundle.</p>



<p>Now, the Property List Editor in the Xojo IDE provides a simpler way to add these entries. Once added, you can even export the contents to an external file, making it easy to reload them later for other projects that require the same set of entries. This saves time by eliminating the need to manually re-enter them.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1424" height="1082" src="https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.18.28 PM.png" alt="" class="wp-image-14555" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.18.28 PM.png 1424w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.18.28 PM-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.18.28 PM-1024x778.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-26-at-12.18.28 PM-768x584.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>
</div>


<p>What about projects that already reference an external Info.plist file? No worries—Xojo will automatically merge its contents with the entries added via the Property List Editor. If the same key exists in both the external file and the Property List Editor, the value from the Property List Editor will take precedence, overriding the one in the external file.</p>



<p>As for the types of data that can be added to the Property List Editor, the expected options are offered:</p>



<p><strong>For collections:</strong></p>



<ul class="wp-block-list">
<li>Dictionary</li>



<li>Array</li>
</ul>



<p><strong>For primitive values:</strong></p>



<ul class="wp-block-list">
<li>Number</li>



<li>String</li>



<li>Boolean</li>
</ul>



<p>For primitive value entries, the Editor allows you to convert them to any of the other two supported primitive types. For example, if you add a Number entry, you can later select it and convert it to a String or Boolean type as needed.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1208" height="862" src="https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-18-at-1.00.05 PM.png" alt="" class="wp-image-14556" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-18-at-1.00.05 PM.png 1208w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-18-at-1.00.05 PM-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-18-at-1.00.05 PM-1024x731.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/Screenshot-2025-02-18-at-1.00.05 PM-768x548.png 768w" sizes="auto, (max-width: 1208px) 100vw, 1208px" /></figure>
</div>


<p>Of course, the entries added through the Property List Editor are applied and saved to the project file in addition to any changes made using the Property List Editor. The next time you open the project in Xojo, you&#8217;ll find the previously applied Info.plist entries already in place.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Tip:</strong> If you&#8217;re using the new Publish feature to send your macOS apps to App Store Connect, you can simplify Apple&#8217;s encryption compliance process by adding a new Boolean entry in the Property List Editor with the following values:</p>
</blockquote>



<p><strong>Key:</strong> ITSAppUsesNonExemptEncryption<br><strong>Value:</strong> False</p>



<p>By doing this, you won&#8217;t need to manually go through the &#8220;Manage&#8221; option for Apple&#8217;s encryption compliance on the App Store Connect website—provided your app does not actually use encryption that requires disclosure.</p>



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



<p>Whether you&#8217;re developing macOS or iOS projects, the integration of the Property List Editor in the Xojo IDE streamlines the process of managing additional Info.plist entries. You no longer need to manually create and import external files —now, you can add, edit, and reuse entries directly within the IDE. This not only saves time but also ensures consistency across multiple projects!</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Publish macOS and iOS Apps to the App Store Directly from Xojo</title>
		<link>https://blog.xojo.com/2025/03/25/how-to-publish-macos-and-ios-apps-to-the-app-store-directly-from-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 15:34:03 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2025r1]]></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>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14558</guid>

					<description><![CDATA[Starting with Xojo 2025r1, you can publish macOS and iOS apps to App Store Connect directly from the Xojo IDE. Keep reading to learn how!&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2025r1, you can publish macOS and iOS apps to App Store Connect directly from the Xojo IDE. Keep reading to learn how!</p>



<p><a href="http://Starting with Xojo 2025r1, you can publish macOS and iOS apps to the App Store Connect website directly from the Xojo IDE. Keep reading to learn how!  App Store Connect is where developers create app records as part of the process to make their apps available on the Mac App Store and/or iOS App Store. All apps must go through Apple’s review process for approval. Once an app record exists in App Store Connect, every new app build uploaded from the Xojo IDE will be available there!">App Store Connect</a> is where developers create app records as part of the process to make their apps available on the Mac App Store and/or iOS App Store. All apps must go through Apple’s review process for approval. Once an app record exists in App Store Connect, every new app build uploaded from the Xojo IDE will be available there!</p>



<h2 class="wp-block-heading">First Things, First</h2>



<p>Before exploring how to use Xojo&#8217;s new Publish feature, let&#8217;s review the requirements and previous processes to better understand how it works.</p>



<p>You may have already met these requirements, but it&#8217;s always a good idea to review them.</p>



<ul class="wp-block-list">
<li>A paid Apple Developer membership (approximately US $99/yr).</li>



<li>Xcode installed on your Mac, preferably the latest version (Xcode 16.2 at the time of writing, which requires macOS Sequoia 15.2). However, Xojo also works with Xcode 13 or later, such as on macOS Ventura.</li>



<li>The following certificates are present in your Mac&#8217;s Keychain:
<ul class="wp-block-list">
<li>Developer ID Application</li>



<li>Apple Distribution</li>



<li>3rd Party Mac Developer Installer</li>
</ul>
</li>



<li>An explicit App ID (Identifier) has been created for your app at developer.apple.com.</li>



<li>A Provisioning Profile has been created at developer.apple.com to ensure the uploaded build is available for testing via TestFlight.</li>



<li>No pending agreements are waiting for your approval at both developer.apple.com and appstoreconnect.apple.com.</li>
</ul>



<h2 class="wp-block-heading">Handling Certificates</h2>



<p>The best way to ensure you have the correct certificates installed in your Mac’s Keychain is to manage them directly from Xcode. Open Xcode, go to Preferences &gt; Accounts, and make sure you are signed in with your developer.apple.com credentials.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1884" height="1328" src="https://blog.xojo.com/wp-content/uploads/2025/02/1-Certificates-A.png" alt="" class="wp-image-14559" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/1-Certificates-A.png 1884w, https://blog.xojo.com/wp-content/uploads/2025/02/1-Certificates-A-300x211.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/1-Certificates-A-1024x722.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/1-Certificates-A-768x541.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/1-Certificates-A-1536x1083.png 1536w" sizes="auto, (max-width: 1884px) 100vw, 1884px" /></figure>
</div>


<p>Next, click the &#8220;Manage Certificates…&#8221; button. A new window will appear, displaying the installed certificates—including expired ones or those missing a private key. From here, you can also download any missing certificates.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1884" height="1328" src="https://blog.xojo.com/wp-content/uploads/2025/02/2-Certificates-B.png" alt="" class="wp-image-14560" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/2-Certificates-B.png 1884w, https://blog.xojo.com/wp-content/uploads/2025/02/2-Certificates-B-300x211.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/2-Certificates-B-1024x722.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/2-Certificates-B-768x541.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/2-Certificates-B-1536x1083.png 1536w" sizes="auto, (max-width: 1884px) 100vw, 1884px" /></figure>
</div>


<p>Once the required certificates are installed on your Mac, I recommend opening the Keychain app to remove any revoked, expired, or incomplete certificates (those missing a private key) to keep your Keychain clean and organized.</p>



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



<p>The App ID, Identifier, or &#8216;Bundle Identifier&#8217; is something you should be familiar with whenever you create a new macOS or iOS app in the Xojo IDE.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1764" height="1334" src="https://blog.xojo.com/wp-content/uploads/2025/02/3-App-Identifier.png" alt="" class="wp-image-14561" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/3-App-Identifier.png 1764w, https://blog.xojo.com/wp-content/uploads/2025/02/3-App-Identifier-300x227.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/3-App-Identifier-1024x774.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/3-App-Identifier-768x581.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/3-App-Identifier-1536x1162.png 1536w" sizes="auto, (max-width: 1764px) 100vw, 1764px" /></figure>
</div>


<p>You also need to create the same App ID at developer.apple.com. Log in to the Apple Developer portal using your Apple Developer credentials, then click &#8220;Identifiers&#8221; under the &#8220;Certificates, IDs &amp; Profiles&#8221; section.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2100" height="1312" src="https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers.png" alt="" class="wp-image-14562" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers.png 2100w, https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers-300x187.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers-1024x640.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers-768x480.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers-1536x960.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/02/5-Identifiers-2048x1280.png 2048w" sizes="auto, (max-width: 2100px) 100vw, 2100px" /></figure>
</div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> Keep in mind that you must create a new App ID and follow these steps for each macOS or iOS app you want to distribute through the Mac or iOS App Store.</p>
</blockquote>



<ul class="wp-block-list">
<li>On the page displayed after the previous step, click the <strong>&#8220;+&#8221;</strong> button next to the &#8220;Identifiers&#8221; header to register a new Identifier. </li>



<li>On the next page, ensure that &#8220;App IDs&#8221; is selected, then click &#8220;Continue&#8221;. </li>



<li>On the following page, select &#8220;App&#8221;, then click &#8220;Continue&#8221; again.</li>



<li>Now, you’ll reach the most important step—entering the explicit Bundle ID. Make sure it exactly matches the &#8220;Application Identifier&#8221; used when creating the project in the Xojo IDE. </li>



<li>Also, verify that the App ID Prefix matches the Team ID of the certificates installed in your Mac’s Keychain via Xcode.</li>



<li>Select any Capabilities and/or App Services your app requires. (For this example, none are selected.) </li>



<li>Click &#8220;Continue&#8221; to proceed to the summary page, where you can review all the entered details and selected Capabilities/App Services. </li>



<li>If everything looks correct, click &#8220;Register&#8221; to finalize the process.</li>
</ul>



<p>Once registered, the new Identifier will appear in the list under the &#8220;Identifiers&#8221; section.</p>



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



<p>TestFlight is an Apple service that allows developers to gather feedback from users and teammates while an app is still in development, before it becomes publicly available on the Mac or iOS App Store. When a new app build (version) is published from the Xojo IDE, it will also become available through TestFlight.</p>



<p>However, for this to work, the app must have a &#8220;Provisioning Profile&#8221; embedded. This profile needs to be created on the &#8220;developer.apple.com&#8221; website, as we did in the previous &#8220;App ID&#8221; section.</p>



<p>There are two main types of provisioning profiles: &#8220;Development&#8221; and &#8220;Distribution.&#8221; The key difference is:</p>



<ul class="wp-block-list">
<li>&#8220;Development&#8221; profiles specify which devices an app can be installed on. They are primarily used for internal testing on user devices or, in the case of iOS apps, for running tests on a physical device using the &#8220;Run On Device&#8221; option in the Xojo IDE.</li>



<li>&#8220;Distribution&#8221; profiles are used for submitting apps to the App Store or making them available for TestFlight testing.</li>
</ul>



<p>In this example, we will focus on creating a &#8220;Distribution Provisioning Profile&#8221; to ensure that apps published from the Xojo IDE are eligible for TestFlight testing.</p>



<ul class="wp-block-list">
<li>Log in to &#8220;developer.apple.com&#8221; and navigate to the &#8220;Certificates, IDs &amp; Profiles&#8221; section.</li>



<li>Select &#8220;Profiles&#8221; and click the &#8220;+&#8221; button next to the &#8220;Profiles&#8221; header.</li>



<li>On the next page, under the &#8220;Distribution&#8221; section, select &#8220;Mac App Store Connect&#8221; if you are creating a profile for a macOS app. For iOS apps, choose &#8220;App Store Connect&#8221; instead. Click &#8220;Continue.&#8221;</li>



<li>Select the &#8220;App ID&#8221; you previously created. Notice that the App ID is prefixed with the &#8220;Team ID&#8221; from when the App ID was created (e.g., &#8220;BW7PU32485&#8221;).</li>



<li>Under &#8220;Profile Type,&#8221; make sure the &#8220;Mac&#8221; option is selected instead of &#8220;Mac Catalyst.&#8221; Click &#8220;Continue.&#8221;</li>



<li>On the next page, select the same &#8220;Distribution&#8221; certificate that will be used when building the Xojo app (i.e., the &#8220;Apple Distribution&#8221; certificate installed on your Mac). Click &#8220;Continue.&#8221;</li>



<li>Give the Provisioning Profile a meaningful name so you can easily distinguish it later from other profiles. Click &#8220;Generate.&#8221;</li>



<li>After a few seconds, the Provisioning Profile summary page will appear with a &#8220;Download&#8221; button. Click it to download the profile.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>NOTE:</strong> Provisioning Profiles for iOS<br>For iOS apps, you need to create both &#8220;Development&#8221; and &#8220;Distribution&#8221; provisioning profiles.</p>



<ul class="wp-block-list">
<li>When creating the &#8220;Development&#8221; provisioning profile, be sure to include all registered devices you want to use for installing and testing the app directly from Xojo (using the &#8220;Run On Device&#8221; option in the IDE).</li>



<li>Once these provisioning profiles are downloaded to your Mac, double-click on them to ensure Xcode installs them in the correct location (as of this writing: &#8220;Library &gt; Developer &gt; Xcode &gt; User Data &gt; Provisioning Profiles&#8221;).</li>
</ul>
</blockquote>



<h2 class="wp-block-heading">Adding the Distribution Provision Profile to your Xojo Project</h2>



<p>Move the downloaded macOS Distribution Provisioning Profile to a more convenient location related to your Xojo project, and rename it to &#8220;embedded.provisionprofile&#8221;.</p>



<p>Next, open your Xojo project and add a new &#8220;Copy Files&#8221; step:</p>



<ul class="wp-block-list">
<li>Right-click (or use the contextual menu) and choose &#8220;Add to &#8216;Build Settings&#8217; &gt; Build Step &gt; Copy Files&#8221;.</li>



<li>Select the &#8220;macOS&#8221; item under &#8220;Build Settings.&#8221;</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1126" height="434" src="https://blog.xojo.com/wp-content/uploads/2025/02/16-CopyFiles.png" alt="" class="wp-image-14563" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/16-CopyFiles.png 1126w, https://blog.xojo.com/wp-content/uploads/2025/02/16-CopyFiles-300x116.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/16-CopyFiles-1024x395.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/16-CopyFiles-768x296.png 768w" sizes="auto, (max-width: 1126px) 100vw, 1126px" /></figure>
</div>


<p>Next, click the &#8220;Add File&#8221; button in the &#8220;Copy Files&#8221; toolbar and select your &#8220;embedded.provisionprofile&#8221; file.</p>



<p>In the associated &#8220;Inspector&#8221; panel, use the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> Distribution Profile</li>



<li><strong>Applies To:</strong> Release</li>



<li><strong>Architecture:</strong> Any</li>



<li><strong>Destination:</strong> Contents Folder</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>NOTE:</strong> For Xojo iOS projects, provisioning profiles are applied automatically when building or publishing the app. This happens based on the profiles installed by Xcode when you double-click them after downloading from developer.apple.com.</p>
</blockquote>



<h2 class="wp-block-heading">App Store Connect: Creating the Record for the App</h2>



<p>You need to create an App Record for every macOS or iOS app that will be distributed through the Mac or iOS App Store. To upload an app from the Xojo IDE, it is not necessary to complete every required field in the various sections right away—you can do that at your own pace. However, you must at least have an App Record created for the app.</p>



<p>To do this, log in to &#8220;appstoreconnect.apple.com&#8221; using your developer credentials. Once logged in, select the &#8220;Apps&#8221; icon. On the next page, click the &#8220;+&#8221; button and choose &#8220;New App&#8221; to create a new App Record. The previous action will open a dialog where you need to enter the essential app information required to create the record.</p>



<ul class="wp-block-list">
<li><strong>Platforms:</strong> Select &#8220;macOS.&#8221;</li>



<li><strong>Name:</strong> Enter the same name used in your Xojo project for the app (Build Settings &gt; macOS &gt; Mac App Name). Apple can be strict about this during the app review process if the names differ, as this will also be the name displayed in the App Store listing.</li>



<li><strong>Bundle ID:</strong> Select the App ID you created for the app by following the steps in the &#8220;Handling App ID&#8221; section.</li>



<li><strong>SKU:</strong> Enter any arbitrary SKU value that makes sense to you for uniquely tracking this app.</li>



<li><strong>User Access:</strong> If you are a solo developer, the choice doesn’t make much difference. However, if you are part of a team, selecting &#8220;Limited Access&#8221; allows more control over which team members can access the app.</li>
</ul>



<p>Once you are confident with the information provided, click the &#8220;Create&#8221; button to generate the new app record.</p>



<p>If you receive an error stating that another app has already been registered with the same name, you will need to choose a different name for your app.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>NOTE:</strong> Values such as the App Name and Bundle ID can be changed later, if needed, from the &#8220;General &gt; App Information&#8221; section on the App Record page.</p>
</blockquote>



<p>Once the App Record has been created, there will be a lot of required information to fill in before the app can go through the App Store Review Process and be publicly listed in the Mac/iOS App Store upon approval. However, as mentioned earlier, you can add this information at your own pace. The most important thing right now is that, once the record is created, you have everything set up to start uploading your app builds (versions) from the Xojo IDE.</p>



<h2 class="wp-block-heading">Publishing Mac Apps From Xojo</h2>



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



<h4 class="wp-block-heading">General Information</h4>



<p>Open your Xojo project in the IDE and go to Build Settings &gt; macOS. Then, make sure the correct values are set in the associated Inspector Panel for the following fields:</p>



<ul class="wp-block-list">
<li><strong>Mac App Name:</strong> This should match the name entered for the App Record on appstoreconnect.apple.com.</li>



<li><strong>Bundle Identifier:</strong> This should match the App ID created for the app.</li>



<li><strong>Category:</strong> Select the category that best fits your app from the available options.</li>
</ul>



<h4 class="wp-block-heading">App Store Connect Setup</h4>



<p>To allow the IDE to upload the app to App Store Connect, you need an app-specific password. You can add it by clicking the App Store Connect &gt; Setup button. If you have already created this app-specific password in a previous version of Xojo (under Build Settings &gt; Sign &gt; Notarization &gt; Setup), you don&#8217;t need to do it again. Also, keep in mind that this setup only needs to be done once for all your Desktop (macOS) and iOS projects.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="556" height="774" src="https://blog.xojo.com/wp-content/uploads/2025/02/AppStoreConnectSetup.png" alt="" class="wp-image-14574" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/AppStoreConnectSetup.png 556w, https://blog.xojo.com/wp-content/uploads/2025/02/AppStoreConnectSetup-216x300.png 216w" sizes="auto, (max-width: 556px) 100vw, 556px" /></figure>
</div>


<h4 class="wp-block-heading">Signing and Sandboxing</h4>



<p>Select Build Settings &gt; macOS &gt; Sign in the project browser in order to access the associated Inspector Panel:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1004" height="638" src="https://blog.xojo.com/wp-content/uploads/2025/02/21-XojoPublish-B.png" alt="" class="wp-image-14570" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/21-XojoPublish-B.png 1004w, https://blog.xojo.com/wp-content/uploads/2025/02/21-XojoPublish-B-300x191.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/21-XojoPublish-B-768x488.png 768w" sizes="auto, (max-width: 1004px) 100vw, 1004px" /></figure>
</div>


<ul class="wp-block-list">
<li><strong>Developer ID:</strong> Type (or paste) the full string from the Apple Distribution certificate installed on your Mac. In this example, it is: &#8220;Apple Distribution: Francisco Javier Rodriguez Menendez (BW7PU32485)&#8221;. This certificate should match the one selected when the Distribution Provisioning Profile was created, and the Team ID (the value in parentheses) should match the one used when the App ID (Identifier) was created for the app at developer.apple.com.</li>



<li><strong>Sandboxing:</strong> Apps uploaded to App Store Connect require Sandboxing to be enabled. Turn on this option and click the associated &#8220;Edit&#8221; button to enable the necessary sandboxed features for your app. In our example, we only enabled the ability to read/write the selected user files.</li>
</ul>



<h4 class="wp-block-heading">Shared Settings</h4>



<p>Select Build Settings &gt; Shared in the project browser to access the associated Inspector Panel:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="550" height="634" src="https://blog.xojo.com/wp-content/uploads/2025/02/23-XojoPublish-D.png" alt="" class="wp-image-14564" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/23-XojoPublish-D.png 550w, https://blog.xojo.com/wp-content/uploads/2025/02/23-XojoPublish-D-260x300.png 260w" sizes="auto, (max-width: 550px) 100vw, 550px" /></figure>
</div>


<p>If you are going to publish the final (release) version of your app after it has been thoroughly tested, you will likely want to set the Stage Code value to &#8220;Final.&#8221; Additionally, make sure to enter the short version string in the Version field and the copyright information for the app in the Copyright field.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>NOTE:</strong> Did you forget something? Every time you click the Publish button (or select the equivalent &#8220;Build and Publish to App Store Connect&#8221; menu item from the Project menu), the IDE will run a &#8220;checklist.&#8221; If something needs to be set in the IDE before uploading the app to App Store Connect, any errors will be shown in the IDE&#8217;s Error Panel, pointing out &#8220;what&#8221; needs to be fixed and &#8220;where&#8221; to make the changes.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2110" height="472" src="https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel.png" alt="" class="wp-image-14565" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel.png 2110w, https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel-300x67.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel-1024x229.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel-768x172.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel-1536x344.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/02/macOS-Error-Panel-2048x458.png 2048w" sizes="auto, (max-width: 2110px) 100vw, 2110px" /></figure>
</div></blockquote>



<h4 class="wp-block-heading">App Icon</h4>



<p>Nothing new here, apart from building your macOS app for regular or &#8220;web-based&#8221; distribution. Your app needs an icon in the required sizes. However, when it comes to publishing to the Mac/iOS App Store, this requirement is even more strict. Xojo will catch this before starting the app building process to save you time spent on compilation and uploading. So, make sure you add all the required icon sizes by selecting the App item in the project browser, then clicking the Appearance &gt; Icon option in the associated Inspector Panel.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1162" height="838" src="https://blog.xojo.com/wp-content/uploads/2025/02/24-XojoPublish-E.png" alt="" class="wp-image-14571" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/24-XojoPublish-E.png 1162w, https://blog.xojo.com/wp-content/uploads/2025/02/24-XojoPublish-E-300x216.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/24-XojoPublish-E-1024x738.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/24-XojoPublish-E-768x554.png 768w" sizes="auto, (max-width: 1162px) 100vw, 1162px" /></figure>
</div>


<p>That action will open the Icon Editor, where you can drag and drop the different icon files for each size or paste them directly from your preferred image editor.</p>



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



<p>Click the Publish button. Once the &#8220;checklist&#8221; passes without any errors, a confirmation dialog will appear. Click the &#8220;OK&#8221; button to begin the process and upload your app&#8217;s new build to App Store Connect.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="558" height="140" src="https://blog.xojo.com/wp-content/uploads/2025/02/PublishButton.png" alt="" class="wp-image-14566" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/PublishButton.png 558w, https://blog.xojo.com/wp-content/uploads/2025/02/PublishButton-300x75.png 300w" sizes="auto, (max-width: 558px) 100vw, 558px" /></figure>
</div>


<p>If everything goes smoothly, you will see a &#8220;Success&#8221; dialog at the end of the process. However, if there is an error during any of the steps, an error message dialog will provide more details about the issue, and the process will be interrupted, returning you to the IDE.</p>



<p>In either case—whether your new app build was successfully uploaded to App Store Connect or not—you can find the generated Log file in the same folder as the built app. If there are errors, you can open the Log file to review the information about the issue(s), which will help you resolve them before trying again. For example:</p>



<pre class="wp-block-preformatted">2025-01-23 12:54:35.030 *** Error: [ContentDelivery.Uploader.6000028E01C0] The provided entity includes an attribute with a value that has already been used (-19232) The bundle version must be higher than the previously uploaded version: ‘1.0.6’. (ID: d422b9bf-049f-4263-af43-8357c2fe5f00)</pre>



<p>In this case, the Log file entry indicates that we tried to publish a build with the same version number as an already uploaded build on App Store Connect. If this new build includes changes or new features, the way to fix this issue is simply by increasing the version number (and the short version string) before publishing it.</p>



<h2 class="wp-block-heading">Testing with TestFlight</h2>



<p>When you create a new app record in App Store Connect and access it, one of the tabs at the top of the page is named &#8220;TestFlight.&#8221; Click on it, and you will see all the uploaded builds of your app that are eligible for testing.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2348" height="1164" src="https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight.png" alt="" class="wp-image-14567" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight.png 2348w, https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight-300x149.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight-1024x508.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight-768x381.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight-1536x761.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/02/25-TestFlight-2048x1015.png 2048w" sizes="auto, (max-width: 2348px) 100vw, 2348px" /></figure>



<p>As you can see, there is a warning icon next to the app build we just uploaded (A). This is because Apple requires additional information from you regarding the app&#8217;s compliance with Encryption Export Regulations. To provide this information, click the associated &#8220;Manage&#8221; link to access the dialog where you can make your choice about it.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1406" height="964" src="https://blog.xojo.com/wp-content/uploads/2025/02/26-TestFlight-B.png" alt="" class="wp-image-14568" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/26-TestFlight-B.png 1406w, https://blog.xojo.com/wp-content/uploads/2025/02/26-TestFlight-B-300x206.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/26-TestFlight-B-1024x702.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/26-TestFlight-B-768x527.png 768w" sizes="auto, (max-width: 1406px) 100vw, 1406px" /></figure>
</div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>TIP</strong>: Use the new Property List Editor in Xojo’s IDE and add the following Key/Value pair to avoid manually going through the Encryption Export Regulations compliance process:</p>



<ul class="wp-block-list">
<li><strong>Key:</strong> ITSAppUsesNonExemptEncryption</li>



<li><strong>Value:</strong> False</li>
</ul>
</blockquote>



<p>Once the requirement has been completed, the build status will change to &#8220;Ready to Submit.&#8221; As you can see, it also indicates that this build will be available to your testers for the next 90 days before expiring. This should be enough time before you send new test builds to them, anyway.</p>



<p>For each of your apps, you can create as many tester groups as needed. By default, there is only one entry: &#8220;Internal Testing.&#8221; You can create additional groups and add any members of your Apple Development Team to the groups you create. Click on the &#8220;+&#8221; icon to create your first group.</p>



<ul class="wp-block-list">
<li>Give the new group a name and uncheck the &#8220;Enable automatic distribution&#8221; checkbox. Then, click the &#8220;Create&#8221; button.</li>



<li>Once the new internal testing group is created, you will be able to assign any uploaded (and not expired) builds of your app to it. You can also add members to the group (remember, these should be members of your Apple Developer Team!).</li>
</ul>



<p>However, having internal testing groups might not be very helpful if you are a solo developer or part of a small team. The good news is that once you create the first, mandatory internal group, a new option will be added to the TestFlight sidebar.</p>



<h4 class="wp-block-heading">External Testing</h4>



<p>In this case, you will be able to invite up to 10,000 members to test your app. The main difference compared to internal groups is that once you select a build to be tested in any of the external groups, it must go through the Beta App Review process. This means the build won&#8217;t be immediately available to your testers until the review is complete. However, this process is only required for the first build—subsequent builds will be available immediately, just like in internal groups.</p>



<p>When inviting members to an external group, you have several options: you can create and share a public link, manually add testers, or even import them from a .csv file.</p>



<p>In any case, your testers will be able to download, install, and begin testing your app, as well as provide feedback!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2024" height="1386" src="https://blog.xojo.com/wp-content/uploads/2025/02/TestFlightInstallApp.png" alt="" class="wp-image-14569" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/TestFlightInstallApp.png 2024w, https://blog.xojo.com/wp-content/uploads/2025/02/TestFlightInstallApp-300x205.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/TestFlightInstallApp-1024x701.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/TestFlightInstallApp-768x526.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/TestFlightInstallApp-1536x1052.png 1536w" sizes="auto, (max-width: 2024px) 100vw, 2024px" /></figure>



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



<p>The new Publish feature simplifies the process of submitting your macOS and iOS apps to App Store Connect, making them available on the Mac App Store and iOS App Store directly from the IDE, without needing any external apps (such as Transporter).</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>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
