« MBS Xojo Plugins, ver… | Home | MBS Xojo Plugins, ver… »

Xojo Tips and Tricks

We got a few tips and tricks collected for you in the last week.

1. App.Constructor

If you need code to run really first, you may go with the constructor of the Application object. This constructor runs before the Opening event, so it is your chance to do very early initialization before all other events run. But using Constructor can be tricky since you need to call the constructor on the super class and match the signature, which is not always easy to know. Let us show you how the constructors would like

Console and Desktop targets:

Sub Constructor()
System.DebugLog CurrentMethodName
End Sub

Web target:

Sub Constructor()
System.DebugLog CurrentMethodName

// Calling the overridden superclass constructor.
End Sub

iOS target:

Sub Constructor(launchOptions As ptr)
System.DebugLog CurrentMethodName

// Calling the overridden superclass constructor.
Super.Constructor launchOptions
End Sub

For some projects we use constructor to put in some logging or plugin based exception catching very early to catch issues before App.Open event runs. See NSExceptionHandlerMBS and GlobalExceptionHandlerMBS classes.

2. No sessions early on

If you call functions like SessionAt() or SessionWithIdentifier() too early, you may get a nil object exception as the session array is not yet initialized. Xojo keeps their sessions in some kind of storage and this gets initialized somewhere in the app initialization, but it is possible to have code run early enough, that the storage is not initialized yet.

3. Caps Lock state

You can figure out if user has caps lock pressed with Keyboard.AsyncKeyDown function. e.g. you may run a timer once a second to check it. The key to check on macOS is number 57.
And if it is pressed, you may show a warning in a dialog with a password field.

For Windows we recently added a new WinKeyIsCapsLock function for RemoteControlMBS module:

// check state in a timer
If RemoteControlMBS.WinKeyIsCapsLock Then
title = "caps lock on"
Title = "caps lock off"
end if

By default macOS shows caps lock state in password fields nowadays.

4. RowTag() checking performance

What is faster with using int64 for RowTag in a Listbox and checking them?

If RowTag(row) = SomeInt64 Then x
If RowTag(row) = VariantInt64 Then x

So either you compare RowTag to the value or to a variant including the value. The first one gets the variant from RowTag and then converts the value to an Int64. The int64 is then compared to the other value. In the second case the RowTag calls the VariantCompare function, which is a bit slower to do the Int64 compare as it is an extra step around it. So the first version is a bit faster.

5. Check string for empty performance

Which one is faster:

If SomeString = "" Then x
If SomeString.Length = 0 Then x
If SomeString.Bytes = 0 Then x
If SomeString.IsEmpty Then x

Technically Xojo's compiler should optimize all three to a nil check for the string variable, since in Xojo an empty string is just passed as nil value around internally.

Invoking .len or .length both starts counting characters for UTF-8 strings, which can take a while, so this is the slowest version. The call to .Bytes is taking a bit call since it invokes a few functions. Faster than Length as it just reads the byte count from the string structure. Now to our surprise the comparison to "" is the fastest, even as it invokes a function to compare strings. But this function is optimized with empty strings in mind and exists quickly, if one is nil and the other not.
Update: We added IsEmpty to our checks, which internally calls Length, so it's even slower than calling Length directly.

So if you need to check if a string is empty, please compare to "" to check for empty strings.
If Xojo improves in future to compare to nil without a function call (see #64074), you will benefit from all the changes. The biggest plugin in space...
31 10 23 - 09:17