Truco: Cómo saber si una app macOS tiene habilitado el Modo de Compatibilidad IU

Como probablemente ya sepas, desde Xojo 2025r34 las apps desarrolladas y compiladas para macOS pueden elegir entre activar el Modo de Compatibilidad de IU o no. Pongamos por caso que estás desarrollando una Librería que se usará en otros proyectos y que, como parte de su funcionalidad de IU, dicha Librería necesita saber en tiempo de ejecución si la app está funcionando con el Modo de Compatibilidad de IU activado o no. ¿Cómo podemos saberlo? Continúa leyendo y te mostraré como.

Para saber si una app macOS está funcionando con el Modo de Compatibilidad de IU activado o no utilizaremos varios Declare en un método incluido en un Módulo. Por tanto, crea un nuevo proyecto de escritorio y añádele un nuevo Módulo (en nuestro ejemplo, con el nombre “Module1”). A continuación, añade un nuevo método sobre dicho módulo utilizando la siguiente signatura:

IsCompatibilityModeEnabled As Boolean

Y añade el siguiente fragmento de código en el Editor de Código asociado con dicho método:

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

Básicamente, lo que hace el código anterior es obtener el contenido del archivo Info.Plist correspondiente a la app de macOS (su Bundle) en un objeto NSDictionary (similar al Dictionary de Xojo). Luego intenta recuperar el objeto asociado con la clave “UIDesignRequiresCompatibility” del diccionario. Si el objeto devuelto es igual a Nil, entonces significará que el archivo Info.Plist no contiene dicha clave y, por tanto, la app está funcionando en el modo nativo de Tahoe. Pero si se encuentra dicha clave en el archivo Info.Plist asociado con la app, entonces dicha clave devuelve el valor Booleano asociado con dicha clave; de modo que si el valor devuelto es igual a True entonces indicará que la app en ejecución está funcionando con el Modo de Compatibilidad de IU activado bajo macOS Tahoe. ¡Así de simple!

Probando el Método

Añade un DesktopButton a la ventana por defecto del proyecto (Window1) y añade el evento Pressed a dicho botón. Luego, añade la siguiente línea de código en el Editor de Código asociado con el evento:

MessageBox( "Compatibility Mode Enabled: " +  IsCompatibilityModeEnabled.ToString )

Para el propósito de nuestra prueba, haz clic en el elemento Build Settings > macOS en el Navegador de Proyecto y activa la opción UI Compatibility Mode bajo la sección Build en el Panel Inspector. Ejecuta la app y, si la versión macOS de tu ordenador es macOS 26 o posterior, entonces verás el siguiente mensaje:

Sal de la aplicación y vuelve a Build Settings > macOS para desactivar la opción UI Compatibility Mode. Ejecuta la app de nuevo y, ahora, obtendrás el siguiente mensaje:

En resumen

Como puedes ver, el uso de Declare es una característica realmente potente de entre las extensas capacidades ofrecidas por Xojo, permitiendo que el desarrollador puede acceder y usar directamente las API proporcionadas por el sistema operativo; en este caso para recuperar el contenido del archivo Info.Plist correspondiente al Bundle de la app, leer dicho contenido en un diccionario y recuperar el valor asociado con una clave determinada.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *