Compartir vía


Arquitectura de Xamarin.Mac

En esta guía se explora Xamarin.Mac y su relación con Objective-C en un nivel bajo. Se explican conceptos como la compilación, los selectores, registrarsel inicio de la aplicación y el generador.

Información general

Las aplicaciones de Xamarin.Mac se ejecutan en el entorno de ejecución mono y usan el compilador de Xamarin para compilar hasta el lenguaje intermedio (IL), que luego se compila Just-In-Time (JIT) en código nativo en tiempo de ejecución. Esto se ejecuta en paralelo con el entorno de Objective-C ejecución. Ambos entornos de tiempo de ejecución se ejecutan sobre un kernel similar a UNIX, específicamente XNU, y exponen varias API al código de usuario, lo que permite a los desarrolladores acceder al sistema nativo o administrado subyacente.

En el diagrama siguiente se muestra información general básica de esta arquitectura:

Diagram showing a basic overview of the architecture

Código nativo y administrado

Al desarrollar para Xamarin, a menudo se usan los términos código nativo y administrado . El código administrado es código que tiene su ejecución administrada por Common Language Runtime de .NET Framework o, en el caso de Xamarin: Mono Runtime.

El código nativo es código que se ejecutará de forma nativa en la plataforma específica (por ejemplo, Objective-C o incluso código compilado AOT, en un chip ARM). En esta guía se explora cómo se compila el código administrado en código nativo y se explica cómo funciona una aplicación de Xamarin.Mac, haciendo uso completo de las API de Mac de Apple mediante el uso de enlaces, al tiempo que tiene acceso a . BCL de NET y un lenguaje sofisticado como C#.

Requisitos

Para desarrollar una aplicación maOS con Xamarin.Mac, se requiere lo siguiente:

  • Un equipo Mac que ejecute macOS Sierra (10.12) o superior.
  • La versión más reciente de Xcode (instalada desde App Store)
  • La versión más reciente de Xamarin.Mac y Visual Studio para Mac

La ejecución de aplicaciones de Mac creadas con Xamarin.Mac tiene los siguientes requisitos del sistema:

  • Un equipo Mac que ejecute Mac OS X 10.7 o superior.

Compilación

Al compilar cualquier aplicación de plataforma de Xamarin, el compilador de Mono C# (o F#) se ejecutará y compilará el código de C# y F# en lenguaje intermedio de Microsoft (MSIL o IL). Xamarin.Mac usa un compilador Just-In-Time (JIT) en tiempo de ejecución para compilar código nativo, lo que permite la ejecución en la arquitectura correcta según sea necesario.

Esto contrasta con Xamarin.iOS, que usa la compilación AOT. Cuando se usa el compilador AOT, todos los ensamblados y todos los métodos de ellos se compilan en tiempo de compilación. Con JIT, la compilación solo se produce a petición para los métodos que se ejecutan.

Con las aplicaciones de Xamarin.Mac, Mono normalmente se inserta en el lote de aplicaciones (y se conoce como Mono incrustado). Al usar la API de Xamarin.Mac clásica, la aplicación podría usar en su lugar System Mono, pero esto no se admite en la API unificada. El sistema Mono hace referencia a Mono que se ha instalado en el sistema operativo. En el inicio de la aplicación, la aplicación Xamarin.Mac lo usará.

Selectores

Con Xamarin, tenemos dos ecosistemas independientes, .NET y Apple, que necesitamos reunir para parecer lo más simplificado posible, para garantizar que el objetivo final sea una experiencia de usuario fluida. Hemos visto en la sección anterior cómo se comunican los dos entornos de ejecución y es posible que haya escuchado muy bien el término "enlaces", lo que permite que las API nativas de Mac se usen en Xamarin. Los enlaces se explican en profundidad en la Objective-C documentación de enlace, por lo que, por ahora, vamos a explorar cómo funciona Xamarin.Mac en segundo plano.

En primer lugar, debe haber una manera de exponer Objective-C a C#, que se realiza a través de selectores. Un selector es un mensaje que se envía a un objeto o clase. Con Objective-C esto se realiza a través de las funciones de objc_msgSend . Para obtener más información sobre el uso de selectores, consulte la guía selectores de iOS.Objective-C También debe haber una manera de exponer código administrado a Objective-C, lo que es más complicado debido al hecho de que Objective-C no sabe nada sobre el código administrado. Para desplazarse por esto, usamos un registrar. Esto se explica con más detalle en la sección siguiente.

Registrar

Como se mencionó anteriormente, registrar es el código que expone código administrado a Objective-C. Para ello, crea una lista de todas las clases administradas que derivan de NSObject:

  • Para todas las clases que no encapsulan una clase existente Objective-C , crea una nueva Objective-C clase con Objective-C miembros que reflejan todos los miembros administrados que tienen un [Export] atributo .
  • En las implementaciones de cada miembro Objective-C, el código se agrega automáticamente para llamar al miembro administrado reflejado.

El pseudocódigo siguiente muestra un ejemplo de cómo se hace esto:

C# (código administrado):

class MyViewController : UIViewController{
    [Export ("myFunc")]
    public void MyFunc ()
    {
    }
 }

Objective-C (código nativo):

@interface MyViewController : UIViewController
 - (void)myFunc;
@end

@implementation MyViewController
- (void)myFunc {
    // Code to call the managed C# MyFunc method in MyViewController
}
@end

El código administrado puede contener los atributos [Register] y [Export], que usa registrar para saber que el objeto debe exponerse a Objective-C. El atributo [Register] se usa para especificar el nombre de la clase generada Objective-C en caso de que el nombre generado predeterminado no sea adecuado. Todas las clases derivadas de NSObject se registran automáticamente con Objective-C. El atributo [Export] necesario contiene una cadena, que es el selector usado en la clase generada Objective-C .

Hay dos tipos de registrars uso en Xamarin.Mac: dinámicos y estáticos:

  • Dinámico registrars : es el valor predeterminado registrar para todas las compilaciones de Xamarin.Mac. La dinámica registrar realiza el registro de todos los tipos del ensamblado en tiempo de ejecución. Para ello, usa las funciones proporcionadas por Objective-Cla API en tiempo de ejecución. Por lo tanto, la dinámica registrar tiene un inicio más lento, pero un tiempo de compilación más rápido. Las funciones nativas (normalmente en C), llamadas trampolines, se usan como implementaciones de método cuando se usa el dinámico registrars. Varían entre diferentes arquitecturas.
  • Static registrars : el código estático registrar genera Objective-C código durante la compilación, que luego se compila en una biblioteca estática y se vincula al archivo ejecutable. Esto permite un inicio más rápido, pero tarda más tiempo durante el tiempo de compilación.

Inicio de la aplicación

La lógica de inicio de Xamarin.Mac variará en función de si se usa Mono incrustado o del sistema. Para ver el código y los pasos para el inicio de la aplicación Xamarin.Mac, consulte el archivo de encabezado launch en el repositorio público de xamarin-macios.

Generator

Xamarin.Mac contiene definiciones para cada API de Mac. Puede examinar cualquiera de estos elementos en el repositorio de GitHub de MaciOS. Estas definiciones contienen interfaces con atributos, así como cualquier método y propiedades necesarios. Por ejemplo, el código siguiente se usa para definir un NSBox en el espacio de nombres de AppKit. Observe que es una interfaz con varios métodos y propiedades:

[BaseType (typeof (NSView))]
public interface NSBox {

    …

    [Export ("borderRect")]
    CGRect BorderRect { get; }

    [Export ("titleRect")]
    CGRect TitleRect { get; }

    [Export ("titleCell")]
    NSObject TitleCell { get; }

    [Export ("sizeToFit")]
    void SizeToFit ();

    [Export ("contentViewMargins")]
    CGSize ContentViewMargins { get; set; }

    [Export ("setFrameFromContentFrame:")]
    void SetFrameFromContentFrame (CGRect contentFrame);

    …

}

El generador, llamado bmac en Xamarin.Mac, toma estos archivos de definición y usa herramientas de .NET para compilarlos en un ensamblado temporal. Sin embargo, este ensamblado temporal no se puede usar para llamar Objective-C al código. A continuación, el generador lee el ensamblado temporal y genera código de C# que se puede usar en tiempo de ejecución. Por este motivo, por ejemplo, si agrega un atributo aleatorio a la definición .cs archivo, no se mostrará en el código generado. El generador no lo sabe y, por tanto bmac , no sabe buscarlo en el ensamblado temporal para generarlo.

Una vez creado el Xamarin.Mac.dll, el empaquetador, mmp, agrupará todos los componentes juntos.

En un nivel alto, logra esto ejecutando las siguientes tareas:

  • Cree una estructura de agrupación de aplicaciones.
  • Copie en los ensamblados administrados.
  • Si la vinculación está habilitada, ejecute el enlazador administrado para optimizar los ensamblados mediante la eliminación de elementos sin usar.
  • Cree una aplicación de iniciador y vincule en el código del iniciador junto con el registrar código si está en modo estático.

A continuación, se ejecuta como parte del proceso de compilación de usuario que compila el código de usuario en un ensamblado que hace referencia a la Xamarin.Mac.dll y se ejecuta mmp para convertirlo en un paquete.

Para obtener información más detallada sobre el enlazador y cómo se usa, consulte la guía del vinculador de iOS.

Resumen

En esta guía se examinó la compilación de aplicaciones de Xamarin.Mac y se ha explorado Xamarin.Mac y su relación con Objective-C.