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

<channel>
	<title>iOS &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/category/cross-platform/ios/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 07 May 2026 18:58:07 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>FAQ: iOS Development with Xojo</title>
		<link>https://blog.xojo.com/2026/05/08/faq-ios-development-with-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 08 May 2026 13:15:00 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[App Store]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Xcode]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16238</guid>

					<description><![CDATA[In recent weeks I received several questions regarding Xojo iOS, many from users who already use Xojo for desktop or web development and want to&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In recent weeks I received several questions regarding Xojo iOS, many from users who already use Xojo for desktop or web development and want to start using Xojo for mobile, particularly iOS, development. I&#8217;ve compiled some of their questions together with some other tips into this mini-FAQ.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>I&#8217;ll update this FAQ from time to time, so you may want to bookmark it and revisit! In addition, the <a href="https://forum.xojo.com/c/targets/ios/37" target="_blank" rel="noreferrer noopener">Xojo Forum</a> is a great place to keep the conversation about this and other iOS Xojo-related topics!</p>
</blockquote>



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



<h2 class="wp-block-heading">Can I develop iOS apps on Windows?</h2>



<p>No. Running, testing, or debugging an iOS project in Xojo requires the iOS Simulator which is provided only with Apple&#8217;s Xcode and is only available on macOS. We advise using ARM processor based Macs that are updated to the latest version of macOS. You can review the <a href="https://documentation.xojo.com/resources/system_requirements_for_current_release.html#ios-apps" target="_blank" rel="noreferrer noopener">system requirements</a> for building iOS apps with the latest Xojo release.</p>



<h2 class="wp-block-heading">Do I need to install anything besides Xojo?</h2>



<p>In addition to Xojo, you&#8217;ll need to install <a href="https://xcodereleases.com" target="_blank" rel="noreferrer noopener">Xcode</a> and run it at least once in order to accept to the provided agreements and to get logged-in into your developer account from the Xcode preferences (mostly in order to install the Developer Certificates).</p>



<p>Make sure there is, at least, an iOS SDK installed &#8211; it should already be there because it is done automatically during Xcode&#8217;s first installation (and subsequent Xcode updates).</p>


<div class="wp-block-image">
<figure class="aligncenter"><img fetchpriority="high" decoding="async" width="833" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.16.37-833x1024.png" alt="" class="wp-image-16240" srcset="https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.16.37-833x1024.png 833w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.16.37-244x300.png 244w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.16.37-768x944.png 768w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.16.37.png 1224w" sizes="(max-width: 833px) 100vw, 833px" /></figure>
</div>


<p>In addition, if needed, you can download additional iOS SDKs from Xcode &gt; Preferences &gt; Components.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="1024" height="703" src="https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.32.56-1024x703.png" alt="" class="wp-image-16239" srcset="https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.32.56-1024x703.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.32.56-300x206.png 300w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.32.56-768x527.png 768w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.32.56-1536x1054.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.32.56.png 1644w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Also, make sure that the Xcode CLI tools are installed, because Xojo needs these in order to create the package during the build process. You can set these under Xcode &gt; Preferences &gt; Locations.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="1024" height="703" src="https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.19.10-1024x703.png" alt="" class="wp-image-16241" srcset="https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.19.10-1024x703.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.19.10-300x206.png 300w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.19.10-768x527.png 768w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.19.10-1536x1054.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/05/Screenshot-2026-05-05-at-13.19.10.png 1644w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h2 class="wp-block-heading">Why are the Run and Build buttons disabled for my iOS projects in Xojo?</h2>



<p>There could be a few reasons for this. </p>



<ul class="wp-block-list">
<li>Check that the CLI tools are selected in Xcode. See previous point.</li>



<li>Launch Xcode to make sure you have agreed to the license agreement and that there are no Xcode issues that jump out.</li>



<li>Are you signed into the Xojo IDE with the account that holds your Xojo Mobile license? Open the license key window in the Xojo app and verify your license is there. If not, sign in to the IDE to automatically add your license. Check <a href="https://documentation.xojo.com/getting_started/introduction/activating_your_xojo_license_and_building_apps.html#troubleshooting">Troubleshooting</a> tips for licenses.</li>
</ul>



<h2 class="wp-block-heading">I don&#8217;t see a Simulator under Xojo Project &gt; Run On menu… what can I do about that?</h2>



<p>Quit Xojo and re-open it. You should now see the same Simulators installed on Xcode under that Xojo submenu.</p>



<h2 class="wp-block-heading">Do I need to keep Xcode open while using Xojo?</h2>



<p>No. That is not necessary at all!</p>



<h2 class="wp-block-heading">Everything was working fine… but now I can&#8217;t run or build iOS apps. Why?</h2>



<p>It&#8217;s likely there is a new agreement you need to accept from Apple. Go to the <a href="https://appstoreconnect.apple.com/login">Apple Developer Portal log-in</a> using your developer credentials and check if there are new or updated agreements.</p>



<p>Another thing to check for are expired provisioning profiles or missing or expired Developer Certificates. If so, you need to create new ones.</p>



<p>And of course make sure your Xojo license is listed in the license key window. Are you signed into the Xojo IDE with the account that holds your Xojo Mobile license? Open the license key window in the Xojo app and verify your license is there. If not, sign in to the IDE to automatically add your license. Check <a href="https://documentation.xojo.com/getting_started/introduction/activating_your_xojo_license_and_building_apps.html#troubleshooting">Troubleshooting</a> tips for licenses.</p>



<h2 class="wp-block-heading">Can I use Xojo iOS if I have a free Apple Developer Account?</h2>



<p>In short: yes. Free Apple Developer Accounts are those you can create using an Apple Account. That is, the same you use in order to access other Apple services. But, even if it is possible to use a free developer account, these have some limitations compared with the paid Apple Developer account. The following table summarizes these:</p>



<figure class="wp-block-table tg"><table class="has-fixed-layout"><thead><tr><th>&nbsp;</th><th><span style="font-weight: bold; font-style: normal;">Apple Account</span></th><th><span style="font-weight: bold; font-style: normal;">Apple Developer Program</span></th></tr></thead><tbody><tr><td><span style="font-weight: normal; font-style: normal;">Xcode developer tools</span></td><td><span style="font-weight: normal; font-style: normal;">●</span></td><td>●</td></tr><tr><td><span style="font-weight: normal; font-style: normal;">Xcode beta releases</span></td><td>●</td><td>●</td></tr><tr><td><span style="font-weight: normal; font-style: normal;">On-device testing</span></td><td>●</td><td>●</td></tr><tr><td><span style="font-weight: normal; font-style: normal;">Advanced app capabilities and services</span></td><td>&nbsp;</td><td>●</td></tr><tr><td><span style="font-weight: normal; font-style: normal;">App distribution</span></td><td>&nbsp;</td><td>●</td></tr><tr><td><span style="font-weight: normal; font-style: normal;">Ad hoc distribution for testing and internal use</span></td><td>&nbsp;</td><td>●</td></tr></tbody></table></figure>



<p>In addition, you need to also consider the following limitations:</p>



<ul class="wp-block-list">
<li>The number of App IDs that can be registered is limited to 10 and each expires after 7 days.</li>



<li>The number of test devices that can be registered to the account is limited to 3, and each expires after 7 days.</li>



<li>Provisioning profiles will expire 7 days from issuance, which may require you to rebuild and re-install your app to your device after expiration.</li>
</ul>



<p>There are some free tools you can use to skip these limitations, but they are not officially supported, for example <a href="https://sideloadly.io/index.html" target="_blank" rel="noreferrer noopener">Sideloadly</a> (in fact this one can be used even on Windows).</p>



<h2 class="wp-block-heading">I have a free Apple Developer account and I followed all the previous steps and I still can&#8217;t run my app from Xojo.</h2>



<p>In order for an iOS app to run it requires a provisioning profile. These can be created from the Apple Developer website or you can let Xcode handle them. If you don&#8217;t have a lot of experience with iOS development (or Apple platforms development in general), then the easiest way forward is to use the following steps which allow Xcode to create the provisioning profile for your specific app. These steps are for the most basic provisioning profile; one that doesn&#8217;t include the use of any of specific Apple services or technologies that require being included in such provisioning profile:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="556" src="https://blog.xojo.com/wp-content/uploads/2026/05/ManagedProvisionProfile-1024x556.png" alt="" class="wp-image-16245" srcset="https://blog.xojo.com/wp-content/uploads/2026/05/ManagedProvisionProfile-1024x556.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/05/ManagedProvisionProfile-300x163.png 300w, https://blog.xojo.com/wp-content/uploads/2026/05/ManagedProvisionProfile-768x417.png 768w, https://blog.xojo.com/wp-content/uploads/2026/05/ManagedProvisionProfile-1536x834.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/05/ManagedProvisionProfile.png 2012w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<ol class="wp-block-list">
<li>Open Xcode and create a new iOS project.</li>



<li>Give the project the same Bundle Identifier as the one you are going to use in your Xojo project.</li>



<li>In the main area of the Xcode window, select the item for the project root (A).</li>



<li>Then, select the target item from the Targets section (B).</li>



<li>Next, select the Signing &amp; Capabilities tab. Make sure your Team is selected and the Bundle Identifier is the same one you are using for your Xojo app (C).</li>



<li>As result of the selections made, you will see the area corresponding to the (Xcode managed) provisioning profile that is going to be created.</li>



<li>Make sure a Simulator is selected and then run the App from Xcode. That action will open the selected Simulator and will run the blank app into it.</li>



<li>Because a provisioning profile has already been created, go back to Xojo and you will be able to run your Xojo app. If that is not the case, quit Xojo and reopen it so the IDE can find the just generated provisioning profile from Xcode.</li>
</ol>



<h2 class="wp-block-heading">Are there other ways to install my iOS apps to my registered devices without going through the App Store?</h2>



<p>Yes. You can install built iOS apps on the devices previously registered in your developer account through what is called <em>sideloading</em> using Xcode.</p>



<p>Once the app has been built using Xojo (it creates a package &#8211; IPA file), go to Xcode &gt; Devices and Simulator, select the device and drop the package onto the area showing the apps installed on that device. That action will initiate the copy (installation) of your iOS app on that specific device.</p>



<p>Take into consideration that this kind of installation allows the app to run for one year; that is, the timespan the provisioning profile lasts for that particular app. Once the provisioning profile expires, you will need to repeat the process: build the app with a new provisioning profile, and copy it again into the device.</p>



<h2 class="wp-block-heading">Is it possible to distribute Xojo-created iOS Apps through the App Store?</h2>



<p>Of course! In fact <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">the Xojo IDE greatly simplifies the process</a> of building and uploading directly your iOS apps to the App Store Connect portal, both for starting the required Apple review process previous for the app being available through the App Store, or if you simply want to distribute your betas to your beta-testers using Testflight.</p>



<p>In order to distribute iOS apps through the App Store you will need a paid Apple Developer membership.</p>



<h2 class="wp-block-heading">Helpful Resources</h2>



<p>As always, Xojo provides resources for free, no license needed to access our user forum, documentation, videos and other resources. </p>



<ul class="wp-block-list">
<li>Xojo iOS <a href="https://documentation.xojo.com/getting_started/quickstarts/ios_quickstart.html#" target="_blank" rel="noreferrer noopener">Quickstart</a></li>



<li>Xojo iOS <a href="https://documentation.xojo.com/getting_started/tutorials/ios_tutorial.html" target="_blank" rel="noreferrer noopener">Tutorial</a></li>



<li><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">How to Publish macOS and iOS Apps to the App Store Directly from Xojo</a></li>



<li><a href="https://documentation.xojo.com/topics/android/android_ios_diffs.html" target="_blank" rel="noreferrer noopener">Differences between iOS and Android</a></li>



<li><a href="https://documentation.xojo.com/topics/ios/getting_the_user%27s_location_from_their_mobile_device.html" target="_blank" rel="noreferrer noopener">Getting the user&#8217;s location from their mobile device</a></li>



<li><a href="https://documentation.xojo.com/topics/ios/how_to_apply_a_blur_effect_on_ios.html" target="_blank" rel="noreferrer noopener">How to apply a blur effect on iOS</a></li>



<li><a href="https://documentation.xojo.com/topics/ios/sending_and_receiving_mobile_notifications.html" target="_blank" rel="noreferrer noopener">Sending and receiving mobile notifications</a></li>



<li><a href="https://documentation.xojo.com/topics/ios/loading_third_party_frameworks_in_xojo_ios.html" target="_blank" rel="noreferrer noopener">Loading 3rd Party Frameworks in Xojo iOS</a></li>



<li><a href="https://blog.xojo.com/category/cross-platform/ios/" target="_blank" rel="noreferrer noopener">iOS related posts on the Xojo Blog</a></li>
</ul>



<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>Quick Tip: Font Properties in DrawControlInLayoutEditor for Mobile Projects</title>
		<link>https://blog.xojo.com/2026/04/22/quick-tip-font-properties-in-drawcontrolinlayouteditor-for-mobile-projects/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 20:30:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Tips]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16193</guid>

					<description><![CDATA[In the new DrawControlInLayoutEditor event of Xojo, which is available for MobileCanvas, AndroidMobileUserControl, and iOSMobileUserControl, there are properties available that otherwise do not exist in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In the new DrawControlInLayoutEditor event of Xojo, which is available for <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilecanvas.html#mobilecanvas">MobileCanvas</a>, AndroidMobileUserControl, and iOSMobileUserControl, there are properties available that otherwise do not exist in the Graphics class for mobile projects.</p>



<p>Specifically, the following properties can be used there:</p>



<ul class="wp-block-list">
<li>Graphics.FontName</li>



<li>Graphics.FontSize</li>



<li>Graphics.FontAscent</li>
</ul>



<p>These properties are known from other Xojo targets (e.g. Desktop), but are not part of the official mobile API and are not shown in Autocomplete. They cannot be used outside of this event. </p>



<p>In contrast, the mobile API property Graphics.Font cannot be used within the DrawControlInLayoutEditor event. The usage is strictly limited to the DrawControlInLayoutEditor event. Using these properties in runtime code will result in errors.</p>



<p>These properties allow for more accurate text rendering in the layout editor, for example in custom controls where font metrics need to be considered. </p>



<p>Although these properties are not part of the mobile API, they can be used selectively within the layout editor context.</p>



<p>This code will work fine in your mobile control’s DrawControlInLayoutEditor event:</p>



<pre class="wp-block-code"><code>Var s As String = "Happy coding!"
Var x As Double = g.Width / 2 - g.TextWidth(s) / 2
Var y As Double = g.Height / 2 - g.TextHeight / 2 + g.FontAscent

g.DrawingColor = Color.Red
g.DrawOval(0, 0, g.Width, g.Height)

g.DrawingColor = TextColor
g.Bold = True
g.FontName = "Times New Roman"
g.FontSize = 16
g.DrawText(s, x, y)</code></pre>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="571" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/04/Bildschirmfoto-2026-04-15-um-02.17.17-571x1024.png" alt="" class="wp-image-16194" style="aspect-ratio:0.557587099017292;width:325px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Bildschirmfoto-2026-04-15-um-02.17.17-571x1024.png 571w, https://blog.xojo.com/wp-content/uploads/2026/04/Bildschirmfoto-2026-04-15-um-02.17.17-167x300.png 167w, https://blog.xojo.com/wp-content/uploads/2026/04/Bildschirmfoto-2026-04-15-um-02.17.17-768x1377.png 768w, https://blog.xojo.com/wp-content/uploads/2026/04/Bildschirmfoto-2026-04-15-um-02.17.17.png 852w" sizes="auto, (max-width: 571px) 100vw, 571px" /></figure>



<p>Happy coding!</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</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>Custom Control Rendering with DrawControlInLayoutEditor</title>
		<link>https://blog.xojo.com/2026/03/31/custom-control-rendering-with-drawcontrolinlayouteditor/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 15:22:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[DrawControlInLayoutEditor]]></category>
		<category><![CDATA[IDE]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16045</guid>

					<description><![CDATA[One of the notable additions in Xojo 2026 Release 1 is that the&#160;DrawControlInLayoutEditor&#160;event is now available for Desktop and iOS/Android projects, giving you more possibilities&#8230;]]></description>
										<content:encoded><![CDATA[
<p>One of the notable additions in Xojo 2026 Release 1 is that the&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event is now available for Desktop and iOS/Android projects, giving you more possibilities over how your controls appear in the layout editor.</p>



<p>With this feature you can provide custom drawing for a control at design time, making it easier to visualize your UI without running the project.</p>



<p>If this sounds familiar, it&#8217;s because it brings Desktop and iOS/Android projects closer to what&#8217;s already possible in Web projects with&nbsp;<code>WebSDKUIControl</code>, where custom layout rendering has been available for some time.</p>



<h4 class="wp-block-heading">Why this matters</h4>



<p>Previously your custom Canvas controls would appear as generic placeholders, making it difficult to understand how they would look at runtime. Now you can:</p>



<ul class="wp-block-list">
<li>Render a preview of your control directly in the layout editor</li>



<li>Display dynamic or state-based visuals</li>



<li>Make custom controls much easier to work with at design time</li>
</ul>



<h4 class="wp-block-heading">How it works</h4>



<p>For Desktop projects, you can subclass&nbsp;<code>DesktopUIControl</code>&nbsp;and implement the&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event. Your drawing code is executed by the IDE as it renders the control in the layout. For iOS and Android projects, this event is available on&nbsp;<code>MobileUIControl</code>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> You can also use this event directly with&nbsp;<code>DesktopCanvas</code>&nbsp;and&nbsp;<code>MobileCanvas</code>&nbsp;controls, so you can start drawing in&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;without needing to subclass anything.</p>



<p>This event gives you the flexibility to draw whatever you need—shapes, text, or even simplified representations of runtime content. For example, a custom media player control could display a play button and timeline, or a chart control could render a sample graph.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="661" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1024x661.png" alt="" class="wp-image-16049" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1024x661.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-768x496.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1536x991.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-2048x1322.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading">A note about XojoScript limitations</h4>



<p>One important detail to keep in mind is that&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;runs using XojoScript. This allows the IDE to safely execute your drawing code at design time, but it also means not everything you&#8217;d typically expect to use in Xojo is available, especially when it comes to the graphics APIs.</p>



<p>In practice, most common drawing operations—such as shapes, lines, and text—work as expected. However, in some cases these graphics calls use a slightly different API, as is the case with <code>LinearGradientBrush</code>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Also, because this runs as XojoScript, you cannot call other methods from within your <code>DrawControlInLayoutEditor</code>code. To access your control&#8217;s properties, you&#8217;ll need to use the built-in  <code>ColorProperty</code>, <code>BooleanProperty</code>, <code>IntegerProperty</code>, <code>DoubleProperty</code>, and <code>StringProperty</code> methods.</p>



<h4 class="wp-block-heading">Support for more Graphics</h4>



<p>In 2026r1, we&#8217;ve expanded the graphics capabilities available to&nbsp;<code>DrawControlInLayoutEditor</code>, building on what was previously supported for&nbsp;<code>WebSDKUIControl</code>. New additions include support for:</p>



<ul class="wp-block-list">
<li>LinearGradientBrush, PictureBrush, and ShadowBrush</li>



<li>LineDash, LineDashOffset, LineCap, LineJoin, and MiterLimit</li>



<li>Outline</li>



<li>Scale, Rotate, and Translate</li>



<li>SaveState, RestoreState</li>



<li>Color constants (Red, Green, Blue, Yellow etc.)</li>
</ul>



<p>Since XojoScript does not support the&nbsp;<code>Pair</code>&nbsp;type, the&nbsp;<code>LinearGradientBrush</code>&nbsp;API was adapted slightly:</p>



<pre class="wp-block-code"><code>Class LinearGradientBrush

  Sub Constructor()

  Sub AddStop(stop As Double, c As Color)

  Property StartPoint As Point
  Property EndPoint As Point

End Class</code></pre>



<p>The main difference is how the brush is constructed and how stops are added, without needing&nbsp;<code>Pair</code>. With this new API, you can turn a basic graph into something much more visually appealing.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="661" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1024x661.png" alt="" class="wp-image-16075" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1024x661.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-768x496.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1536x991.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-2048x1322.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading">Turning off this feature</h4>



<p>While many may prefer custom rendering for custom controls, it can become a bottleneck when a large number of controls are rendering content. If you prefer a less resource-intensive experience, you can disable this behavior in Settings → Layout by enabling the Static Rendering option.</p>



<h4 class="wp-block-heading">Finally</h4>



<p>With&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;now available for Desktop and Mobile projects, you can take advantage of the same benefits Web projects have enjoyed for years. Be sure to check out the new DrawControlInLayoutEditor example project, adapted from the WebSDK → CustomButton example. We hope you enjoy designing and previewing your custom controls with this new event—and yes, it also works in Libraries!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></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>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>Modern and Evolving: macOS and iOS 26 and WinUI in Xojo</title>
		<link>https://blog.xojo.com/2025/12/09/modern-and-evolving-macos-and-ios-26-and-winui-in-xojo/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:30:56 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[macOS 26]]></category>
		<category><![CDATA[macOS Tahoe]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[WinUI]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15650</guid>

					<description><![CDATA[As the platforms we develop for continue to evolve, so does Xojo. Each year brings new design directions, updated frameworks and refreshed user experience standards&#8230;]]></description>
										<content:encoded><![CDATA[
<p>As the platforms we develop for continue to evolve, so does Xojo. Each year brings new design directions, updated frameworks and refreshed user experience standards across macOS, iOS and Windows. Staying aligned with these changes is essential, not just to keep apps looking modern, but to ensure they feel right at home on every device. In this post, we’ll take a look at how Xojo is adapting to Apple’s latest updates and our ongoing work to bring a modern Windows experience through WinUI.</p>



<h2 class="wp-block-heading">macOS 26 and iOS 26</h2>



<p>Over time, Apple has brought the user experiences of macOS and iOS closer together. macOS 26 and iOS 26, now aligned in version numbers, also share more similarities than ever in their user experience. These updates represent the most significant user experience changes from Apple since iOS was introduced in 2007 and Aqua for macOS seven years earlier. With such a big update, especially when designing elements to work on both large computers displays as well as small smartphone screens, it’s no surprise there’s some tweaking requiring after release. Clearly, Apple is still refining its platforms.</p>



<p>We continue to update Xojo as Apple defines its preferred user experience, ensuring that you can deliver the best possible experience to your users.</p>



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



<p>We are also hard at work upgrading our Windows framework to WinUI, providing a modern user experience for Windows apps. You can see our progress in each release by enabling the Use WinUI (Experimental) option on the Advanced tab in Windows build settings. The “Experimental” label is a reminder that the feature is still evolving, and it will be removed once WinUI is fully ready. Our goal has always been to keep Xojo on a steady path, prepared for whatever challenges lie ahead.</p>



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



<p>On behalf of the entire Xojo team, I can say that we love what we do and we appreciate your support in allowing us to do it. We are Xojo users ourselves (after all, we make Xojo with Xojo) and we enjoy seeing what you make with it. With that in mind, feel free to tell us about your creations. Send your screenshots, descriptions and your story to hello@xojo.com.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Checking Out Xojo Libraries</title>
		<link>https://blog.xojo.com/2025/12/09/checking-out-xojo-libraries/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:29:31 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15569</guid>

					<description><![CDATA[The ability to create a compiled Library with Xojo has been a long-requested feature. Starting with 2025 Release 3, Library support is now available as&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The ability to create a compiled Library with Xojo has been a long-requested feature. Starting with 2025 Release 3, Library support is now available as a preview. Here’s more information about what it is and how you can use it.</p>



<h2 class="wp-block-heading">What is a Library?</h2>



<p>A Library is a collection of pre-written, reusable code containing methods, classes and UI.&nbsp;Up until now, the way to distribute a Library for use with Xojo was to create a Plugin or to manually re-use project items across projects. Both have pros and cons.</p>



<p>Plugins are compiled and do not expose source code, but plugins cannot be created using Xojo itself and are typically created using C/C++ along with the Xojo Plugin SDK. Sharing project items is fine for internal projects or open-source projects, but less ideal for commercial libraries. They can be harder to manually add to a project and are recompiled along with the project, slowing the debug process.</p>



<p>With a Xojo Library, you can now create your own compiled Library using Xojo itself. This Library can contain nearly any Xojo project item and can be easily used in other Xojo projects because it is distributed as a single file.</p>



<p>At a high-level, you create your Library in Xojo, add your project items to it and built it into a Library package file. Other projects can then use this Library package, which gives them access to the items you included in the Library.</p>



<h2 class="wp-block-heading">Creating a Library</h2>



<p>Here is a brief overview of how you create a Xojo Library:</p>



<ol class="wp-block-list">
<li>In a Desktop, Web, Console or iOS project add a Library by choosing Insert-&gt;Library.</li>



<li>Add the project items you want to the Library. Any Xojo project item is supported, except for Worker.</li>



<li>Build the project. It will build the main app (which should serve as a test app for your Library) and a separate Library package file (with extension .xojo_library).</li>



<li>You can put this Library package alongside another project (on the drive) and it will be loaded when that project is opened by Xojo. You can then use the classes, methods and UI contained in the Library within your project. If you instead put the Library in the Plugins folder, then it will be available for all projects.</li>
</ol>



<p>This is all best demonstrated by a quick example. Go ahead and create a Desktop project and add a Library to it, which adds a Library1 project item to the Navigator. Change its name using the Inspector to LibHello.</p>



<p>While LibHello is selected, choose Insert-&gt;Class. This adds Class1 to it. This new class is now part of the Library. With Class1 selected, change its name to StringStuff.</p>



<p>You can now add whatever methods or properties you want to the class. For our example purposes here we will add a simple method that reverses a string.</p>



<pre class="wp-block-code"><code>Public Function ReverseString(s As String) As String
  Var newString As String
  
  For Each c As String In s.Characters
    newString = c + newString
  Next
  
  Return newString
End Function</code></pre>



<p>The Library could contain many other things of course, but to keep things simple this Library will have just the single class with its single method. Here&#8217;s what it looks like in the project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="311" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-1024x311.png" alt="" class="wp-image-15570" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-1024x311.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-300x91.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-768x233.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x.png 1382w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The first thing to do is to test this Library ReverseString method. Add a button to Window1 and have it call the function, verifying the result.</p>



<pre class="wp-block-code"><code>Var stuff As New StringStuff
Var result As String = stuff.ReverseString("Xojo")

MessageBox(result)</code></pre>



<p>When you run, you can see the output:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="744" height="584" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x.png" alt="" class="wp-image-15572" style="width:407px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x.png 744w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x-300x235.png 300w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>



<p>So far this is all not much different than you would normally be doing with a Xojo project. The next step is to create the Library package for use by other projects.</p>



<p>In the Build Settings area, select Shared. This is where you can enter some information about the Library that can be seen by those that use it.</p>



<ul class="wp-block-list">
<li>In the Version field, enter &#8220;1.0&#8221;.</li>



<li>In the Copyright field, enter &#8220;Acme, Inc.&#8221;</li>



<li>In the Description field, enter &#8220;A Xojo Library test.&#8221;</li>
</ul>



<p>Also in the Build Settings area, check the boxes for the platforms you want the Library to work on. In most situations, you will want to select macOS, Windows and Linux.</p>



<p>Now click Build. This builds the app as usual, but also creates a separate Library package file (LibHello.xojo_library for this example) that can be used with other projects.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="558" src="https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1024x558.png" alt="" class="wp-image-15577" style="width:590px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1024x558.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-300x163.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-768x418.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1536x837.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1.png 1542w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Using a Library</h2>



<p>Now that you&#8217;ve created your Library package, you can use it with other Xojo projects. The Library built above was created within a Desktop project, so it can only be used with other Desktop projects. So the first thing to do is to create a new Desktop project (call it MyTest), save it and close it.</p>



<p>Once it is saved, go to Finder or Explorer and place a copy of the LibHello.xojo_library file (from its build location) alongside this saved project file.</p>



<p>Go back to Xojo and open the MyTest project. The project will open normally, but the Library will also be loaded up as well. You can see this by showing the Xojo About window and going to the Plugins &amp; Libraries tab. There you will see the Library name along with the information you entered about it earlier. (Double-click on the Library row to show the description.)</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="726" src="https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-1024x726.png" alt="" class="wp-image-15578" style="width:664px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-1024x726.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-300x213.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-768x544.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow.png 1524w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Going back to the MyTest project, you can now use the Library with it. Add a button to the window and have it call the StringReverse function the same way you did before:</p>



<pre class="wp-block-code"><code>Var stuff As New StringStuff
Var result As String = stuff.ReverseString("Xojo")

MessageBox(result)</code></pre>



<p>Now run the project and it will use the class and its method just as if it is part of the project.</p>



<p>That&#8217;s the basics of how to create and use a Library. You can of course include whatever you want in the Library, but as with any library it is usually a good idea to keep things well-organized.</p>



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



<ul class="wp-block-list">
<li>A Library package (which uses ZIP) contains compiled code and definitions of the public API in that code.</li>



<li>Only a single Library project item can be added to a project when developing.</li>



<li>A project can use any number of Library packages.</li>



<li>For a built library to work on all OS platforms, then those platforms must be selected before building it.</li>



<li>Libraries only support 64-bit builds.</li>



<li>Library packages are placed alongside the project file and are loaded when the project is loaded.</li>



<li>Library packages can also be placed in the Plugins folder. These libraries will be loaded separately for each project.</li>



<li>If items in your Library have dependencies outside the Library, then the Library package will not be usable in another project without those dependencies. For example, if a Library class method references a class in the main project, then it will build without an error (because the main project is available), but if you use that Library in another project you will get linker errors.</li>
</ul>



<h2 class="wp-block-heading">Why a Preview?</h2>



<p>We are referring to this initial version of Xojo Libraries as a preview release because it is very new and we want to give more developers a chance to test with it so we can iron out issues. We encourage you to try moving your existing reusable code collections over to a Library to help test, while also improving your workflow. If you have any open-source projects that are essentially a Library, you might try building them into a Xojo Library package as well.</p>



<p>You can make Library packages available publicly, but you should probably tag them as a preview, beta or test version until we remove the preview label.</p>



<p>Read more about Libraries in the <a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">Xojo Documentation</a>. Check out these open-source projects on GitHub that have recently been updated for API 2.0 and now have a Library that you can download from the Releases section:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/xojo/VB" target="_blank" rel="noreferrer noopener">Visual Basic Library</a></li>



<li><a href="https://github.com/xojo/FM" target="_blank" rel="noreferrer noopener">FileMaker Library</a></li>



<li><a href="https://github.com/paullefebvre/winapilib" target="_blank" rel="noreferrer noopener">WinAPI Library</a></li>
</ul>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</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>Xojo Support for macOS 26 and iOS 26</title>
		<link>https://blog.xojo.com/2025/09/15/xojo-support-for-macos-26-and-ios-26/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Mon, 15 Sep 2025 17:56:25 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Liquid Glass]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15358</guid>

					<description><![CDATA[Apple is rolling out some of its biggest design changes in years and we want to update you on where Xojo stands. Apple released macOS&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>Apple is rolling out some of its biggest design changes in years and we want to update you on where Xojo stands.</em></p>



<p>Apple released <strong>macOS 26 and iOS 26</strong> today, the first versions to ship with Apple’s new&nbsp;Liquid Glass&nbsp;look and feel.</p>



<p>The current release of Xojo (2025r2.1) runs smoothly on macOS 26 and can build apps that run on both macOS 26 and iOS 26. However, because 2025r2.1 uses an older version of Apple&#8217;s SDKs, many controls in both the IDE and the apps you build will still use the previous look and feel when running on these new macOS and iOS versions.</p>



<p>We’ve been working throughout Apple’s beta cycle to bring full support for Liquid Glass to Xojo. As you might imagine, Apple made a lot of changes to the OSs along the way — changes that affected things like our layout editor, control sizing, and behavior. Some of these changes were still happening very late in the process. Now that macOS 26 and iOS 26 are officially shipping, we finally know what the end result looks like and how it behaves.</p>



<p>Supporting Liquid Glass and the underlying system changes is a big undertaking and we still have more work to do. Since we build Xojo with Xojo, this means updating not only the Xojo framework but also parts of the IDE itself so it looks and behaves correctly on macOS 26 with Liquid Glass. Our goal is to let you use Liquid Glass in both built-in Xojo controls and third-party party plugins as soon as possible. That&#8217;s why the next release of Xojo, 2025r3, will be built for macOS 26 and iOS 26, giving your apps the latest look and feel while still allowing them to run on older versions of macOS and iOS. This includes projects still using API 1 windows and controls.</p>



<p>Because of the scope of these changes — along with other big, exciting features in the works — the testing cycle for 2025r3 will be longer than usual. As a result, 2025r3 will likely be our last major release of the year, followed by any needed point releases. The good news is that 2025r3 will pack in everything you’d normally see across two releases, plus more. It’s shaping up to be one of the biggest Xojo releases in recent years, with plenty beyond just Liquid Glass to look forward to. Additionally, the updates for 2025r3 aren’t limited to macOS or iOS — there are improvements and new features coming for all platforms, so every Xojo user benefits.</p>



<p>If you have a current license and would like to get early access, we’d love your help testing 2025r3. Just reach out and we’ll be happy to add you to the beta program. We can’t wait to hear your feedback once testing begins!</p>



<p>If you are a long time Xojo user, you know we have been through a <em>lot</em> of big changes like this. Sometimes we get it all done in a single release and sometimes it takes a few to get to 100%. Regardless, our goal is to make the transition for you a smooth one.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</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>Year of Code 2025: May Project, Mobile Apps</title>
		<link>https://blog.xojo.com/2025/05/07/year-of-code-2025-may-project-mobile-apps/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 07 May 2025 16:00:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14805</guid>

					<description><![CDATA[One of the most common things I love to use my phone for is sharing pictures of my pets with others. We have two cats&#8230;]]></description>
										<content:encoded><![CDATA[
<p>One of the most common things I love to use my phone for is sharing pictures of my pets with others. We have two cats and a dog: Shawmut, Christofur and Lucy. To be honest, I’m not much a cat person as I find that cats are almost all <a href="https://24hrtees.net/shop/dont-be-a-richard/">Richards</a>, constantly causing and getting into trouble. I’m 100% a dog person.</p>



<p>But even though I have my own pets, I do love looking at pet pictures. It&#8217;s a simple pleasure, but there&#8217;s not much that I find more calming.</p>



<p>Years ago I made a Xojo app (CatsUp) that displayed random cat pictures and it was a lot of fun. And one thing that Xojo excels at is making it fun to create software! That’s what the Year of Code is all about, after all.</p>



<p>Speaking of that, here is the Year of Code topic for May: <strong>Mobile Apps</strong>.</p>



<p>You can already find CatsUp for iOS and Android included in the Xojo examples, but why stop at just cats? Being a dog guy, I want to see some dogs. All the dogs.</p>



<p>Since I’m not here to start a cats vs. dogs war, I thought, why not both? It turns out I’m not the only one that thinks this as there are actually public web services that serve up pictures of cats and dogs. Web services and mobile apps go together like peanuts butter and chocolate.</p>



<p>The web service for cats that I’ve previously used is called TheCatAPI and is available here: <a href="https://thecatapi.com">https://thecatapi.com</a></p>



<p>There is an equivalent dog one called, unsurprisingly, TheDogAPI: <a href="https://www.thedogapi.com">https://www.thedogapi.com</a></p>



<p>For my mobile app this month, I’ve created an all-new app that can show pictures of cats, dogs or both! I call it Pawz.</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="1024" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/04/Pawz.png" alt="" class="wp-image-14806" style="width:344px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/Pawz.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/04/Pawz-300x300.png 300w, https://blog.xojo.com/wp-content/uploads/2025/04/Pawz-150x150.png 150w, https://blog.xojo.com/wp-content/uploads/2025/04/Pawz-768x768.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Pawz app icon</figcaption></figure>



<p>Actually, it&#8217;s two apps since I made versions for iOS and Android. Here’s a look:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="497" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.44.54@2x-497x1024.png" alt="" class="wp-image-14810" style="width:309px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.44.54@2x-497x1024.png 497w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.44.54@2x-145x300.png 145w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.44.54@2x-768x1584.png 768w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.44.54@2x-745x1536.png 745w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.44.54@2x.png 867w" sizes="auto, (max-width: 497px) 100vw, 497px" /><figcaption class="wp-element-caption">Pawz on iOS</figcaption></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="480" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.41.34@2x-480x1024.png" alt="" class="wp-image-14809" style="width:298px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.41.34@2x-480x1024.png 480w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.41.34@2x-141x300.png 141w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.41.34@2x-768x1637.png 768w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.41.34@2x-721x1536.png 721w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.41.34@2x.png 915w" sizes="auto, (max-width: 480px) 100vw, 480px" /><figcaption class="wp-element-caption">Pawz on Android</figcaption></figure>
</div>
</div>



<p>Although they are separate projects, both use basically the same code. In fact there is only about 50 lines of code in each project! The UI itself is just a big ImageViewer that is used to show the picture and several toolbar buttons.</p>



<p>There are three buttons to request a cat picture, dog picture or a surprise picture that could be either. There is also an extra button that lets you share the picture, if you really like it.</p>



<p>You can find the source for the iOS and Android versions of Pawz on GitHub here:</p>



<p><a href="https://github.com/paullefebvre/pawz">https://github.com/paullefebvre/pawz</a></p>



<p>Year of Code is all about having some fun making an app. As you can see with Pawz, it doesn&#8217;t have to be anything extravagant. Even fun apps can be made quickly with very little code!</p>



<p>I can&#8217;t wait to see what great mobile apps you all create this month. <a href="https://forum.xojo.com/t/2025-year-of-code-may-is-mobile/85272">Share your creations in the Forum topic</a>.</p>



<h2 class="wp-block-heading"><strong>One More Thing</strong></h2>



<p>Although phones and tablets are what we usually think of when talking about Mobile Apps, you know what else is rather mobile? A vehicle! And it just so happens that many vehicle manufacturers, such as  Cadillac, Chevy, Ford, Honda, Polestar, Renault and Volvo are now using Android to run their infotainment systems. Technically it&#8217;s Android Automotive OS (AAOS), but it is very similar to regular Android.</p>



<p>Because Xojo builds standard Android Runtime (ART) apps, Xojo Android apps also work on Android Automotive OS as a &#8220;parked app&#8221;. You can test with this by using Android Studio to install an Android Automotive VM for the Emulator. Once you’ve added that you can run your Xojo Android projects on it just like any other device. Pawz works fine in an AAOS Emulator.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="1008" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.55.26@2x-1024x1008.png" alt="" class="wp-image-14813" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.55.26@2x-1024x1008.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.55.26@2x-300x295.png 300w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.55.26@2x-768x756.png 768w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.55.26@2x-1536x1512.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-16-at-13.55.26@2x-2048x2016.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Why do I bring this up? No reason, although I believe Xojo 2025 Release 2 pre-release testing might be starting soon&#8230;</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</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>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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Writing Drawing Code for Android, Desktop, iOS and Web</title>
		<link>https://blog.xojo.com/2025/04/21/writing-drawing-code-for-android-desktop-ios-and-web/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Mon, 21 Apr 2025 19:28:10 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Variants]]></category>
		<category><![CDATA[WebGraphics]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14826</guid>

					<description><![CDATA[When writing code it&#8217;s always a good idea to be thinking about the future. Today you are creating a desktop project but tomorrow you might&#8230;]]></description>
										<content:encoded><![CDATA[
<p>When writing code it&#8217;s always a good idea to be thinking about the future. Today you are creating a desktop project but tomorrow you might need to create an Android or iOS project. That code you&#8217;re writing might be code you could use for another project for another platform. </p>



<p>For the most part, writing drawing code will <em>just work</em> because you use Xojo&#8217;s <a href="https://documentation.xojo.com/api/graphics/graphics.html#graphics" target="_blank" rel="noreferrer noopener">Graphics</a> class for Android, Desktop and iOS projects. Web projects, however, don&#8217;t use the Graphics class. The <a href="https://documentation.xojo.com/api/user_interface/web/webcanvas.html#description" target="_blank" rel="noreferrer noopener">WebCanvas</a> control&#8217;s <a href="https://documentation.xojo.com/api/user_interface/web/webcanvas.html#webcanvas-paint" target="_blank" rel="noreferrer noopener">Paint</a> event is passed a <a href="https://documentation.xojo.com/api/graphics/webgraphics.html" target="_blank" rel="noreferrer noopener">WebGraphics</a> object. While the Graphics and WebGraphics classes have a lot in common, sharing many of the same methods with the same parameters, they are two distinctly different classes from the perspective of the Xojo compiler. That means that while the code you write will look almost identical, you still have to use a Graphics object for Android, Desktop and iOS projects and a WebGraphics object for Web projects. </p>



<p>Your instinct might be to simply write the code for one and then copy it to the other projects, changing Graphics to WebGraphics for Web projects. This will of course work, but then you have to remember to do this copy/paste/change operation every time you update your code. That&#8217;s not ideal.</p>



<h2 class="wp-block-heading">Graphics vs. WebGraphics</h2>



<p>With Xojo, the code can be written in such a way as to automatically handle the difference between Graphics/WebGraphics. Most often your graphics methods will be called from something that provides a Graphics or WebGraphics object for you to draw into such as a Canvas control&#8217;s Paint event. From there your code will call your methods that do the drawing. The problem is that your methods can&#8217;t use a Graphics or a WebGraphics type as a parameter because Graphics is not going to work for your Web projects and WebGraphics doesn&#8217;t exist in any framework except the Web framework. Thus using it anywhere else will result in a compiler error.</p>



<h3 class="wp-block-heading">Using a Variant</h3>



<p>Getting around this limitation is, fortunately, quite easy. Instead of using Graphics or WebGraphics as a parameter type, you use <a href="https://documentation.xojo.com/api/data_types/variant.html" target="_blank" rel="noreferrer noopener">Variant</a>. A Variant can hold any type of data from Strings to Integers, to Graphics to WebGraphics and more.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="560" height="466" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x.png" alt="" class="wp-image-14827" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x.png 560w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-14.46.40@2x-300x250.png 300w" sizes="auto, (max-width: 560px) 100vw, 560px" /></figure>



<p>Once your drawing method gets the Variant though, it can&#8217;t use it to draw. It can only use a Graphics or WebGraphics objects. The trick is to then copy it into a Graphics or WebGraphics class variable:</p>



<pre class="wp-block-code"><code><code>Var g As Graphics = context</code></code></pre>



<p>or</p>



<pre class="wp-block-code"><code><code>Var g As WebGraphics = context</code></code></pre>



<p>The problem you now face, as mentioned earlier, is that WebGraphics only exists in Web projects. That means you have to write your code in such a way that you will declare the variable g as a Graphics object in Android, Desktop and iOS projects and as a WebGraphics object in Web projects. This can be achieved via conditional compilation. This is a simple technique that tells the Xojo compiler to only compile code into your app if conditions you specify are met. In this case, if you&#8217;re targeting Desktop or Mobile, it should compile in the line that uses the Graphics type, and if you are targeting a Web app, the line that uses WebGraphics. To conditionally compile, you just need to add that conditional code around these two lines:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="wp-block-code"><code>#If TargetDesktop Or TargetMobile Then
   Var g As Graphics = context
#EndIf

#If TargetWeb Then
   Var g As WebGraphics = context
#EndIf</code></pre>
</div></div>
</div></div>



<p>Since a project must be only one of the above types, when you run or build your project, the appropriate line of code will be compiled in. From there, you now have a variable (g) of the right type can use this to draw whatever you like. For example, there are four identical example projects (one for each project type) that show off this technique. They can be found in the Xojo IDE by choosing File > New Project, clicking on Examples, choosing the Graphics folder in the list and then the Cross-Platform Drawing folder. The examples all draw a checkerboard that looks like this:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="912" height="916" src="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x.png" alt="" class="wp-image-14828" style="width:315px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x.png 912w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-300x300.png 300w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-150x150.png 150w, https://blog.xojo.com/wp-content/uploads/2025/04/CleanShot-2025-04-17-at-15.12.41@2x-768x771.png 768w" sizes="auto, (max-width: 912px) 100vw, 912px" /></figure>
</div>


<p>They all contain the an identical Checkerboard class that handles the drawing. This class has DrawBorder and DrawCheckers methods that both take a Variant as a parameter. In each project is a Canvas control whose Paint event calls these methods:</p>



<pre class="wp-block-code"><code>Var cb As New Checkerboard
cb.DrawBoard(g)
cb.DrawCheckers(g)</code></pre>



<p>The full DrawBoard method looks like this:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<pre class="wp-block-code"><code>#If TargetDesktop Or TargetMobile Then
  Var g As Graphics = context
#EndIf

#If TargetWeb Then
  Var g As WebGraphics = context
#EndIf 

Var boxSize As Integer = Min(g.Width/8, g.Height/8) 'The size of the box
'Draw the rows
For y As Integer = 0 To 7
  For x As Integer = 0 To 7
    'Switch colors for each box in the row
    If g.DrawingColor = Color.Black Then
      g.DrawingColor = Color.White
    Else
      g.DrawingColor = Color.Black
    End If
    'Draw a box
    g.FillRectangle(x * boxSize, y * boxSize, boxSize, boxSize)
  Next
  'Switch colors again for the beginning of the next row
  If g.DrawingColor = Color.Black Then
    g.DrawingColor = Color.White
  Else
    g.DrawingColor = Color.Black
  End If
Next</code></pre>
</div></div>



<p>In the example projects, check out the DrawCheckers method as well. It uses the same technique. What is great about this is that this class can be copied into any Android, Desktop, iOS or Web project and it will indeed <em>just work</em>.</p>



<h3 class="wp-block-heading">Checking Out the Examples</h3>



<p>There are four example projects (one for each project type &#8211; Android, Desktop, iOS and Web) that demonstrate the technique explained here. You can find them in the Xojo IDE by choosing File > New Project, clicking on Examples, choosing the Graphics folder in the list and then the Cross-Platform Drawing folder.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</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>
		<item>
		<title>More Control Over Your Charts</title>
		<link>https://blog.xojo.com/2024/12/10/more-control-over-your-charts/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 16:37:02 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r4]]></category>
		<category><![CDATA[Charts]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13985</guid>

					<description><![CDATA[Starting with Xojo 2024r4 the Chart feature provides even more control over how DataSets are drawn through new properties on Desktop, Web and iOS. Also,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2024r4 the Chart feature provides even more control over how DataSets are drawn through new properties on Desktop, Web and iOS. Also, for Desktop, the Chart control adds two new Event handlers to draw the datapoints of the chart in any way you want.</p>



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



<h2 class="wp-block-heading">Granular Control on DataSets</h2>



<p>The ChartDataset subclasses add three new properties. Now you can choose to allow the interaction from the user (for example when clicking or taping on data points or over a displayed legend in the Chart), you can also choose what legends are visible at the top area of the Chart, as well as choosing to display a Popover when the user moves the mouse over a given rendered datapoint for the associated ChartDataset.</p>



<ul class="wp-block-list">
<li><strong>AllowInteraction</strong>: When it is set to False, then the displayed legend for the ChartDataset doesn&#8217;t respond to interaction (that is enabling/disabling the associated data in the Chart) or raises the Pressed event for the Chart. Also, it doesn&#8217;t fire the Pressed event when the user clicks on any of the rendered data points in the Chart for that particular DataSet.</li>



<li><strong>IsLegendVisible</strong>: When it is set to False, the Legend for the associated ChartDataset is not displayed at the top area of the Chart (always that the Chart.HasLegend property is set to True). This allows a more granular control over the legends that are displayed, so you can have some of the rendered data sets with their legend displayed while others not.</li>



<li><strong>AllowPopover</strong>: When this property is set to False in the ChartDataset, then the Popover won&#8217;t be displayed when the user hovers the cursor over any of its rendered points in the Chart.</li>
</ul>



<h2 class="wp-block-heading">New Events for Chart on Desktop</h2>



<p>Starting with Xojo 2024r4 you can decide how the Chart should draw the data points for any of the rendered ChartDatasets on Desktop. This is done by implementing the two new Event Handlers on the Chart instance:</p>



<ul class="wp-block-list">
<li><strong>DrawPointAt(g As Graphics, x As Double, y As Double, data As ChartDataSet, index As Integer) As Boolean</strong>. This event receives from the &#8220;g&#8221; parameter the graphic context for the datapoint, so you can use any of the available methods and properties of the Graphics class to draw the datapoint. In order to know what datapoint and from what ChartDataset, these are given in the &#8220;index&#8221; and &#8220;data&#8221; parameters, respectively. Also, the &#8220;x&#8221; and &#8220;y&#8221; parameters receive the coordinates for the top-left corner of the data point to be drawn. These coordinates are relatives to the Chart control instance position. Returning True from this Event means that your code handled the datapoint drawing; otherwise the datapoint will be rendered as usual.</li>



<li><strong>DrawMouseOverPointAt(g As Graphics, x As Double, y As Double, data As ChartDataSet, index As Integer) As Boolean</strong>. This event behaves in the same way as the previous one, the only difference is that it will be raised when the user hovers the cursor over a given datapoint, so you have the chance to decide how to draw the highlighted version of the datapoint.</li>
</ul>



<p>You can learn more about the Chart control in the Xojo Documentation at: <a href="https://documentation.xojo.com/api/user_interface/controls/chart.html#chart">https://documentation.xojo.com/api/user_interface/controls/chart.html#chart</a><br>You can learn more about the ChartDataset class (and subclasses) in the Xojo Documentation at: <a href="https://documentation.xojo.com/api/user_interface/charts/chartdataset.html#chartdataset">https://documentation.xojo.com/api/user_interface/charts/chartdataset.html#chartdataset</a></p>



<p>A big thank you for all of you providing feedback and suggestions about how to improve Charts on Xojo! All of these new additions are a direct response from request made from you, so we are happy to make it work the way you need to adhere even more to 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>
					
		
		
			</item>
		<item>
		<title>Working with PDFTableDataSource from Sources Other Than RowSet</title>
		<link>https://blog.xojo.com/2024/11/25/working-with-pdftabledatasource-from-sources-other-than-rowset/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 25 Nov 2024 14:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[PDF]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14035</guid>

					<description><![CDATA[Some users on the Xojo Forum recently asked how to render tables on a PDFDocument using the PDFTableDataSource class interface when the dat source does&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Some users on the <a href="https://forum.xojo.com/t/pdftable-created-manually-not-from-rowset-web/83000">Xojo Forum recently</a> asked how to render tables on a PDFDocument using the <a href="https://documentation.xojo.com/api/pdf/pdftabledatasource.html#pdftabledatasource">PDFTableDataSource</a> class interface when the dat source does not comes from a RowSet. Well, the truth is that it doesn&#8217;t differ too much from when it does! Continue reading and I will show you how using a simple example.</p>



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



<p>The trick is to handle the data coming from any source with the right data structure, for example, an Array. This example uses a plain text file with several lines and columns separated by the Tab character as the source of the data.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>In order to follow this tutorial, <a href="https://drive.google.com/file/d/14Ve5TllFLGK2TE4MTr4fjutpI4aGV0UE/view?usp=sharing">download the example project</a>.</p>
</blockquote>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1816" height="2378" src="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22.png" alt="" class="wp-image-14041" srcset="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22.png 1816w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-229x300.png 229w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-782x1024.png 782w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-768x1006.png 768w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-1173x1536.png 1173w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-12.27.22-1564x2048.png 1564w" sizes="auto, (max-width: 1816px) 100vw, 1816px" /></figure>
</div>


<h2 class="wp-block-heading">Getting the Data</h2>



<p>As you can see in the example project, the text file has been added to the project using a Build > Copy Files Step (the file name is &#8220;Data.txt&#8221;), so it is copied to the Resources folder of the compiled app and available for both debugging and release builds.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2224" height="1464" src="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01.png" alt="" class="wp-image-14037" srcset="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01.png 2224w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-300x197.png 300w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-1024x674.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-768x506.png 768w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-1536x1011.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.18.01-2048x1348.png 2048w" sizes="auto, (max-width: 2224px) 100vw, 2224px" /></figure>
</div>


<p>Then, in the Pressed event of the Button1 control placed on the default Window1, we will access the contents of the file in order to store each of the lines in the Data Array of strings:</p>



<pre class="wp-block-code"><code>Var f As FolderItem = SpecialFolder.Resource("data.txt")
If f &lt;&gt; Nil And f.Exists Then
  Var tis As TextInputStream = TextInputStream.Open(f)
  Var s As String = tis.ReadAll
  data = s.ToArray(EndOfLine.macOS)
End If</code></pre>



<h2 class="wp-block-heading">PDFRenderer Subclass</h2>



<p>The next step is to create a custom class that will implement the methods provided by the PDFTableDataSource Class Interface. We will name the class &#8220;PDFRenderer&#8221;. Then, from the Inspector Panel, click on the Interfaces button, check the PDFTableDataSource interface and confirm the selection.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1076" height="1004" src="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21.png" alt="" class="wp-image-14036" srcset="https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21.png 1076w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21-300x280.png 300w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21-1024x955.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/11/Screenshot-2024-11-20-at-11.03.21-768x717.png 768w" sizes="auto, (max-width: 1076px) 100vw, 1076px" /></figure>
</div>


<p>Once done, the methods from the class interface will be automatically added to the class:</p>



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



<li>Completed</li>



<li>HeaderHeight</li>



<li>MergeCellsForRow</li>



<li>PaintCell</li>



<li>PaintHeaderContent</li>



<li>RowHeight</li>
</ul>



<p>Over these we will add three more methods:</p>



<h4 class="wp-block-heading">The class Constructor:</h4>



<pre class="wp-block-code"><code>Public Sub Constructor(document As PDFDocument)
  // Simple constructor… just assign the received object
  // to the "Document" property
  
  Self.document = document
  proxy = New Picture(document.Graphics.Width, document.Graphics.Height)
End Sub</code></pre>



<p>Assign the received PDFDocument instance to the document property. It also creates a graphics instance that will be used as a proxy for calculating the height of the processed text from the data (that won&#8217;t be necessary starting with Xojo 2024r4 where some PDFDocument bugs related with that are already fixed).</p>



<h4 class="wp-block-heading">DrawTable:</h4>



<p>This method is the one that will be called to start drawing the table. It will initialize some properties from the received Data (yeah, you can see a property named as &#8220;DrawingFromRowSet&#8221;, but I left that one on purpose because this project is based on the one dealing with the data coming from a RowSet, so you can see how similar all the process is):</p>



<pre class="wp-block-code"><code>Public Sub DrawTable(data() As String, headers() As String)
  // This is the method we call on the Class to draw
  // a table on a PDFDocument based on an Array of Strings
  
  If document &lt;> Nil And data.LastIndex &lt;> -1 Then
    
    // Assign the received Array to the "Data" property
    Self.data = data
    
    // Assign the received headers to the "Headers" property
    Self.Headers = Headers
    
    // Hey! We are going to create a table from an Array
    // so we use a Boolean property as a flag for that
    // (Yeah, we can do it using other techniques, but this
    // is easy enough for this purpose… while leave this
    // helper class "open" enough for drawing tables based on other
    // data sources).
    Self.DrawingFromRowSet = True
    
    // How many columns are we going to draw?
    // Well… as many as columns (TABs) in any of the Array items (for example, the first one).
    Var totalColumns As Integer = data(0).CountFields(Chr(9))
    
    // This is going to be the "drawable area" on the page
    // for the table = total page width less the left and right margins
    Var totalWidth As Double = document.Graphics.Width - 40 // 40 = 20 points left/right margins
    
    // Creating the PDFTable object here!
    Var table As New PDFTable
    
    // We want to repeat the headers on every page
    table.HasRepeatingHeader = True
    
    // Setting the column count for the table
    table.ColumnCount = totalColumns
    
    // …and the width for every column.
    table.ColumnWidths = CalculateColumnWidths(totalWidth, totalColumns)
    
    // The object from this class will be the responsible
    // of handling all the methods associated with the
    // PDFTableDataSouce Class Interface
    table.DataSource = Self
    
    // Setting the Top and Bottom margins for the drawing
    // of the table on every PDF page
    table.TopMargin = 20
    table.BottomMargin = 20
    
    // …and finally we instruct the PDFDocument object
    // to draw the table!
    document.AddTable(table, 20, 0)
    
    // Lastly, clearing the flag
    Self.DrawingFromRowSet = False
    
  End If
End Sub</code></pre>



<h4 class="wp-block-heading">CalculateColumnWidths Method</h4>



<p>This one will calculate the widths for each column to be rendered in the final PDF document.</p>



<pre class="wp-block-code"><code>Protected Function CalculateColumnWidths(TotalWidth As Double, NumberOfColumns As Double) As String
  // Helper method to get a string for the column widths
  
  ColumnWidth = TotalWidth / NumberOfColumns
  Var s() As String
  
  For n As Integer = 0 To NumberOfColumns - 1
    s.Add(Str(ColumnWidth))
  Next
  
  Return String.FromArray(s, ",")
End Function</code></pre>



<h3 class="wp-block-heading">Class Properties</h3>



<p>Because we need to track things like what the current row or column is to be rendered, the headers, etc., our class needs to add some properties:</p>



<ul class="wp-block-list">
<li>Protected Property ColumnWidth As Integer</li>



<li>Public Property CurrentColumn As Integer</li>



<li>Protected Property CurrentHeight As Integer</li>



<li>Protected Property CurrentRow As Integer</li>



<li>Protected Property data() As String</li>



<li>Protected Property document As PDFDocument</li>



<li>Protected Property DrawingFromRowSet As Boolean</li>



<li>Public Property Headers() As String</li>



<li>Protected Property LastRow As Integer</li>



<li>Protected Property proxy As Picture</li>
</ul>



<h3 class="wp-block-heading">PDFTableDataSouce Methods</h3>



<p>Time to visit the methods added by the PDFTableDataSouce class interface. These are the methods called by the <a href="https://documentation.xojo.com/api/pdf/pdftable.html#pdftable">PDFTable</a> object each time it needs to retrieve a piece of information during the rendering on the PDFDocument, as for example if it needs to add a new row, the height for the Header or the current row… and the painting of the row itself!</p>



<h4 class="wp-block-heading">AddNewRow Method</h4>



<p>This one is called by the PDFTable object in order to know if it needs to render a new row in the table:</p>



<pre class="wp-block-code"><code>Protected Function AddNewRow(rowCount As Integer) As Boolean
  // Part of the PDFTableDataSource interface.
  
  If DrawingFromRowSet And data.LastIndex &lt;> -1 then
    
    // We are going to draw as many rows as rows are in the
    // "data" array
    Return rowCount &lt;= data.LastIndex
    
  End If
End Function</code></pre>



<h4 class="wp-block-heading">Completed method</h4>



<p>This is the method invoked by the PDFTable object when it finished drawing the table, so it is your chance to take additional operations, for example, numbering every page of the PDFDocument (we can&#8217;t anticipate that before drawing the table itself):</p>



<pre class="wp-block-code"><code>Protected Sub Completed(x As Double, y As Double)
  // Part of the PDFTableDataSource interface.
  
  // This method is called once the table has been drawed
  // so let's "print" the page number on every page
  // of the PDF Document
  
  Static pageNumber As String = "Page: "
  
  If document &lt;> Nil Then
    Var g As Graphics = document.Graphics
    
    For n As Integer = 1 To document.PageCount
      document.CurrentPage = n
      g.DrawText(pageNumber + Str(n), g.Width - g.TextWidth(pageNumber + Str(n)) - 20, g.Height - g.FontAscent)
    Next
    
  End If
End Sub</code></pre>



<h4 class="wp-block-heading">HeaderHeight Method</h4>



<p>This is the method called by the PDFTable object the returns the height we want to use for rendering the header on the first page and, optionally, on every new page required (added to the document) by rendering the table. In this case we will return a fixed value:</p>



<pre class="wp-block-code"><code>Protected Function HeaderHeight() As Double
  // Part of the PDFTableDataSource interface.
  
  // Returning a fixed height value for the headers
  Return 20
End Function</code></pre>



<h4 class="wp-block-heading">MergeCellsForRow Method</h4>



<p>The PDFTableDataSouce class interface also has the ability to merge cells in the current row, so you can create more elaborated tables. We are not going to use that feature in this example project so it will be empty, no code to be executed.</p>



<h4 class="wp-block-heading">PaintHeaderContent Method</h4>



<p>This is the method in charge of rendering the header for the table, so it receives its own Graphic context with the provided height from the HeaderHeight method and the width calculated from the total of columns (headers) needed to be rendered:</p>



<pre class="wp-block-code"><code>Protected Sub PaintHeaderContent(g As Graphics, column As Integer)
  // Part of the PDFTableDataSource interface.
  
  // Painting the headers for the table
  If column &lt;= Self.Headers.LastIndex Then
    
    Var s As String = headers(column)
    g.DrawingColor = Color.Black
    g.FillRectangle(0, 0, g.Width, g.Height)
    g.DrawingColor = Color.White
    g.DrawText(s, g.Width / 2 - g.TextWidth(headers(column)) / 2, g.Height / 2 + g.FontAscent / 2)
    
  End If
End Sub</code></pre>



<h4 class="wp-block-heading">RowHeight Method</h4>



<p>As the class interface provides a method so we can provide the height for the header, we also have a RowHeight method that the PDFTable object will call before it calls the method in charge of doing the row drawing itself. That way we can have rows of different height based on the height of the own text to be rendered!</p>



<pre class="wp-block-code"><code>Protected Function RowHeight() As Double
  // Part of the PDFTableDataSource interface.
  
  // We need to calculate the height for every row in the Table
  // so let's calculate that based on the taller of the texts (columns)
  // based on text wrapping
  
  If CurrentRow &lt;= data.LastIndex Then
    CurrentHeight = 0
    Var s() As String = data(CurrentRow).Split(Chr(9))
    Var g As Graphics = proxy.Graphics
    Var itemHeight As Integer
    For Each item As String In s
      itemHeight = g.TextHeight(item, ColumnWidth - 40)
      If itemHeight > CurrentHeight Then
        CurrentHeight = itemHeight
      End If
    Next
    
    CurrentRow = CurrentRow  + 1 
    
    Return CurrentHeight + 20
  End If
End Function</code></pre>



<h4 class="wp-block-heading">PaintCell Method</h4>



<p>Lastly, this is the method called by the PDFTable object when it is time to render a given cell for the current row in the table. It receives as parameters both a <a href="https://documentation.xojo.com/api/pdf/pdfgraphics.html#notes">graphic context</a> with the width and height already suited for the data to be rendered, and also the row and column values so you can get the appropriate data for a given cell from the data source:</p>



<pre class="wp-block-code"><code>Protected Sub PaintCell(g As Graphics, row As Integer, column As Integer)
  // Part of the PDFTableDataSource interface.
  
  // Here is where we really do the drawing
  // the received "g" parameter is for a particula table cell
  // based on the row / column parameters
  // so the origin for X/Y coordinates is at 0,0
  
  If DrawingFromRowSet And data.LastIndex >= row Then
    // Drawing the outer rectangle for the cell
    g.DrawRectangle(0, 0, g.Width, g.Height)
    
    // retrieving the text to be drawn from the Array,
    // using the row and column parameters for that.
    Var s As String = data(row).NthField(Chr(9), column + 1)
    
    // Centering vertically the text on the table cell
    // while the X offset is fixed at 5 points.
    g.DrawText(s, 5, g.Height / 2 + g.FontAscent / 2, ColumnWidth - 20)
    
    // Let's keep track of the last row drawed
    LastRow = row
    
  End If
End Sub</code></pre>



<h2 class="wp-block-heading">Time to push the Start button!</h2>



<p>Everything is setup now in our PDFRenderer class, so let&#8217;s get back to the Pressed event of the Button1 control on the default Window1 window. You will remember from the beginning of this tutorial that this is the place where we retrieved the data from the text file. So let&#8217;s add the code to create a PDFDocument instance, a new PDFRenderer instance and do the rendering of the table itself from the data:</p>



<pre class="wp-block-code"><code>If data.LastIndex &lt;&gt; -1 Then
  
  // Creating a new PDFDocument Instance
  Var d As New PDFDocument
  
  // Creating the PDFTable renderer helper object (we pass the PDFDocument object to it in the Constructor)
  Var PDFRender As New PDFRenderer(d)
  
  // These will be the headers drawed in the Table
  Var headers() As String = Array("Name", "Surname", "Address", "City", "Email")
  
  // And let's instruct the PDFTable renderer helper to draw the table
  // based in the SQLite database rowset we got in the previous step
  PDFRender.DrawTable(data, headers)
  
  // …and save the resulting PDF File to the Desktop
  Var out As FolderItem = SpecialFolder.Desktop.Child("TableFromTextFile.pdf")
  
  If out &lt;&gt; Nil Then
    d.Save(out)
    out.Open
  End If
End If</code></pre>



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



<p>As you see, and if this tutorial is compared with <a href="https://blog.xojo.com/2023/01/17/pdftable-from-a-rowset/">PDFTable from a RowSet</a>, creating a PDFTable doesn&#8217;t differ too much when using a data source other than a RowSet. All you need, basically, is to keep track of the current row, know if you need to render more rows and a base data structure that can be used to retrieve the data to be rendered in a given Row/Column.</p>



<p>As always, you can learn more about other features provided by <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html#pdfdocument">PDFDocument in the Xojo Documentation</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>
					
		
		
			</item>
		<item>
		<title>Welcome to Mobile Orientation Orientation!</title>
		<link>https://blog.xojo.com/2024/10/07/welcome-to-mobile-orientation-orientation/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Mon, 07 Oct 2024 19:34:19 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[mobileScreen]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13840</guid>

					<description><![CDATA[Mobile apps sometimes have to adjust to the user rotating the device from portrait mode to landscape mode and the reverse. For the most part,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Mobile apps sometimes have to adjust to the user rotating the device from portrait mode to landscape mode and the reverse. For the most part, Xojo handles this for you. For Android projects, if you have locked controls properly and for iOS projects, if you have set the constraints properly, the controls will do the right thing when the device is rotated.</p>



<p>If there&#8217;s something you need to do in code when the orientation changes, you&#8217;re in luck. The <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilescreen.html#mobilescreen-methods">MobileScreen</a> class has an <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilescreen.html#mobilescreen-orientationchanged">OrientationChanged</a> event. When this event fires, that means the user has rotated their device and the orientation has changed. This is where your code would go should you need to respond to an orientation change.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: If you need to know when the screen has changed in size, that&#8217;s what the <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilescreen.html#mobilescreen-resized">Resized</a> event is for (at least on iOS &#8211; it&#8217;s not yet supported for Android).</p>
</blockquote>



<p>What might not be immediately intuitive or obvious is that rotating your device does not automatically mean the orientation has changed. Consider the following example project that displays the Resized and OrientationChanged events in a table when they occur. While this is on iOS, it works the same way (without the Resized event) on Android. The device is starting in portrait mode.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="513" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/10/1-1-513x1024.png" alt="" class="wp-image-13847" style="width:249px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/1-1-513x1024.png 513w, https://blog.xojo.com/wp-content/uploads/2024/10/1-1-150x300.png 150w, https://blog.xojo.com/wp-content/uploads/2024/10/1-1-768x1534.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/1-1-769x1536.png 769w, https://blog.xojo.com/wp-content/uploads/2024/10/1-1.png 806w" sizes="auto, (max-width: 513px) 100vw, 513px" /></figure>



<p>We will focus on just the OrientationChanged events for now. It gets an initial OrientationChanged event. Then the user rotates their phone clockwise enough that the orientation is changed from portrait to landscape.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1610" height="805" src="https://blog.xojo.com/wp-content/uploads/2024/10/2-1024x512.png" alt="" class="wp-image-13850" style="width:471px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/2-1024x512.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/10/2-300x150.png 300w, https://blog.xojo.com/wp-content/uploads/2024/10/2-768x384.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/2-1536x768.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/10/2.png 1610w" sizes="auto, (max-width: 1610px) 100vw, 1610px" /></figure>



<p>You can see that another OrientationChanged event has fired as you&#8217;d expect. Next the user rotates the phone clockwise again.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="512" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/10/3-512x1024.png" alt="" class="wp-image-13851" style="width:267px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/3-512x1024.png 512w, https://blog.xojo.com/wp-content/uploads/2024/10/3-150x300.png 150w, https://blog.xojo.com/wp-content/uploads/2024/10/3-768x1536.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/3.png 806w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>



<p>Now the phone is upside down. Notice, however, the orientation from the perspective of the OS has not changed. The layout is still in landscape orientation. This is not a bug. The device does not support portrait mode when the device is turned upside down. Thus the layout is still in landscape orientation and thus no OrientationChanged event has fired because there has been no orientation change.</p>



<p>Next the user rotates the phone clockwise yet again.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="513" src="https://blog.xojo.com/wp-content/uploads/2024/10/4-1024x513.png" alt="" class="wp-image-13852" style="width:537px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/4-1024x513.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/10/4-300x150.png 300w, https://blog.xojo.com/wp-content/uploads/2024/10/4-768x384.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/4-1536x769.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/10/4.png 1610w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You might think that an OrientationChanged event would fire, but it doesn&#8217;t. Why not? Because as far as the OS is concerned, the layout is still in landscape orientation. It has not changed its orientation. Finally, the user rotates the device clockwise once last time.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="512" height="1024" src="https://blog.xojo.com/wp-content/uploads/2024/10/5-512x1024.png" alt="" class="wp-image-13853" style="width:334px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2024/10/5-512x1024.png 512w, https://blog.xojo.com/wp-content/uploads/2024/10/5-150x300.png 150w, https://blog.xojo.com/wp-content/uploads/2024/10/5-768x1536.png 768w, https://blog.xojo.com/wp-content/uploads/2024/10/5.png 806w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>



<p>This time the orientation has changed from landscape to portrait and thus the OrientationChanged event fired. Given that the initial OrientationChanged event fired when the app launched, out of the four 90 degree clockwise rotations, only two orientation changes occurred and thus only two OrientationChanged events fired.</p>



<p>This is one of those cases where what is initially intuitive turns out to be wrong until you look more closely at what is really going on.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</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>
