@Sam R You've added a solution to help you know what the current theme is, in order for your application to function correctly it relies upon Apple not changing something somewhere and not breaking your solution
I haven't added anything. I'm just using what Apple has provided and suggested for this situation. (rather than Xojo's solution)
Apps can also use key-value observing (KVO) to monitor changes to the effectiveAppearance property of a view or window and make custom changes.-Apple docs
I'm just trying to convey these concepts to Xojo in hopes that they'll rethink the AppearanceChanged event and isDarkMode. I wouldn't use it in its current state as it seems fragile/unpredictable. currentAppearance is not set for the AppearanceChanged event, so your NSColor stuff will give wrong results, and isDarkMode is just inefficient as it stands.
@Sam R If you use the NSColor constants; you don't need to worry about the theme.
Unless you do any themed drawing outside of the paint event (or caching of color values). NSColor relies on NSAppearance.currentAppearance being set. AppKit only sets it during drawRect:, updateLayer, layout and updateConstraints. That means that you (and Xojo) should set it to either NSView.effectiveAppearance or NSApplication.effectiveAppearance if you intend on doing anything that might pull themed colors (NSColor).
I just checked and currentAppearance always returns the appearance an app was launched under during app.AppearanceChanged, regardless of the actual appearance (Dark/not Dark). That is just going to lead to a bunch of confusion and issues for other users when they think they can update their nice NSColor values in response to that event.
@Greg OLone The problem (in Xojo and in objective-c) is that checking this property before an on-screen paint has occurred is just too early
That's the thing. Don't check the property (well, maybe once at open), let the OS tell you about it. Add an observer to sharedApplication.effectiveAppearance. 100% reliable. Just be sure to set currentAppearance to effectiveAppearance before you raise the AppearanceChanged event and everything works as expected.