Funcionamiento de Xamarin.Mac
La mayoría de las veces, el desarrollador nunca tendrá que preocuparse por la "magia" interna de Xamarin.Mac, sin embargo, tener un conocimiento aproximado de cómo funcionan las cosas en el interior le ayudará a interpretar la documentación existente con una lente de C# y problemas de depuración cuando surjan.
En Xamarin.Mac, una aplicación se une a dos mundos: hay un entorno de ejecución basado que contiene instancias de clases nativas (, , etc.) y hay un entorno de ejecución de C# que contiene instancias de clases Objective-CNSStringNSApplication administradas System.String (, HttpClient , etc.). Entre estos dos mundos, Xamarin.Mac crea un puente de dos maneras para que una aplicación pueda llamar a métodos (selectores) en (como ) y pueda volver a llamar a los métodos de C# de la aplicación (como métodos en un delegado de Objective-CNSApplication.InitObjective-C aplicación). En general, las llamadas a Objective-C se controlan de forma transparente a través de Objective-C y algún código en tiempo de ejecución que proporciona Xamarin.
Exponer clases o métodos de C# a Objective-C
Sin embargo, para volver a llamar a los objetos de C# de una aplicación, deben exponerse de una Objective-C manera Objective-C que pueda entender. Esto se realiza a través de los Register atributos Export y . Tome el ejemplo siguiente:
[Register ("MyClass")]
public class MyClass : NSObject
{
[Export ("init")]
public MyClass ()
{
}
[Export ("run")]
public void Run ()
{
}
}
En este ejemplo, el Objective-C tiempo de ejecución ahora conocerá una clase denominada con MyClass selectores denominados init y run .
En la mayoría de los casos, se trata de un detalle de implementación que el desarrollador puede omitir, ya que la mayoría de las devoluciones de llamada que recibe una aplicación se realizarán a través de métodos invalidados en clases (como , , ) o en Acciones que se pasan a las baseAppDelegateDelegatesDataSources API. base En todos esos casos, Export los atributos no son necesarios en el código de C#.
Ejecución del constructor
En muchos casos, el desarrollador tendrá que exponer la API de construcción de clases de C# de la aplicación al tiempo de ejecución para que se puedan crear instancias desde lugares como cuando se llama en archivos storyboard o Objective-C XIB. Estos son los cinco constructores más comunes que se usan en las aplicaciones de Xamarin.Mac:
// Called when created from unmanaged code
public CustomView (IntPtr handle) : base (handle)
{
Initialize ();
}
// Called when created directly from a XIB file
[Export ("initWithCoder:")]
public CustomView (NSCoder coder) : base (coder)
{
Initialize ();
}
// Called from C# to instance NSView with a Frame (initWithFrame)
public CustomView (CGRect frame) : base (frame)
{
}
// Called from C# to instance NSView without setting the frame (init)
public CustomView () : base ()
{
}
// This is a special case constructor that you call on a derived class when the derived called has an [Export] constructor.
// For example, if you call init on NSString then you don’t want to call init on NSObject.
public CustomView () : base (NSObjectFlag.Empty)
{
}
En general, el desarrollador debe dejar solo los constructores y que se generan al crear algunos IntPtrNSCoder tipos, como NSViews personalizados. Si Xamarin.Mac necesita llamar a uno de estos constructores en respuesta a una solicitud en tiempo de ejecución y la ha quitado, la aplicación se bloqueará dentro del código nativo y puede ser difícil averiguar exactamente el Objective-C problema.
Administración de memoria y ciclos
La administración de memoria en Xamarin.Mac es de muchas maneras muy similar a Xamarin.iOS. También es un tema complejo, uno más allá del ámbito de este documento. Lea los procedimientos recomendados de memoria y rendimiento.
Compilación con antelación
Normalmente, las aplicaciones .NET no se compilan en el código de la máquina cuando se compilan, sino que se compilan en una capa intermedia denominada código IL que se compila Just-In-Time (JIT) en código de máquina cuando se inicia la aplicación.
El tiempo que tarda el tiempo de ejecución mono en compilar JIT este código de máquina puede ralentizar el inicio de una aplicación de Xamarin.Mac hasta en un 20 %, ya que se tarda tiempo en generar el código de máquina necesario.
Debido a las limitaciones impuestas por Apple en iOS, la compilación JIT del código IL no está disponible para Xamarin.iOS. Como resultado, todas las aplicaciones de Xamarin.iOS se compilan con antelación completo (AOT) en el código de la máquina durante el ciclo de compilación.
La novedad de Xamarin.Mac es la capacidad de AOT del código IL durante el ciclo de compilación de la aplicación, al igual que Xamarin.iOS. Xamarin.Mac usa un enfoque de AOT híbrido que compila la mayoría del código de máquina necesario, pero permite que el tiempo de ejecución compile las líneas necesarias y la flexibilidad para seguir siendo compatible con Reflection.Emit (y otros casos de uso que actualmente funcionan en Xamarin.Mac).
Hay dos áreas principales en las que AOT puede ayudar a una aplicación de Xamarin.Mac:
- Mejores registros de bloqueo "nativos": si una aplicación de Xamarin.Mac se bloquea en código nativo, lo que es habitual al realizar llamadas no válidas en las API de Cocoa (por ejemplo, enviar un a un método que no lo acepta), los registros de bloqueo nativos con fotogramas JIT son difíciles de analizar. Puesto que los fotogramas JIT no tienen información de depuración, habrá varias líneas con desplazamientos hexadecimales y sin pistas de lo que estaba ocurrindo. AOT genera fotogramas con nombre "reales" y los seguimientos son mucho más fáciles de leer. Esto también significa que la aplicación Xamarin.Mac interactuará mejor con herramientas nativas como lldb e Instruments.
- Mejor rendimiento de la hora de inicio: para aplicaciones de Xamarin.Mac de gran tamaño, con un tiempo de inicio de varios segundos, la compilación JIT de todo el código puede tardar una cantidad significativa de tiempo. AOT hace esto por adelantado.
Habilitación de la compilación de AOT
Para habilitar AOT en Xamarin.Mac, haga doble clic en el nombre de Project en Explorador de soluciones,vaya a Mac Build (Compilación de Mac) y agregue al campo Additional mmp arguments: (Argumentos de mmp adicionales): (donde es una o varias opciones para controlar el tipo AOT, consulte a continuación). Por ejemplo:

Importante
La habilitación de la compilación de AOT aumenta considerablemente el tiempo de compilación, a veces hasta varios minutos, pero puede mejorar los tiempos de inicio de la aplicación en un promedio del 20 %. Como resultado, la compilación de AOT solo debe habilitarse en las compilaciones de versión de una aplicación de Xamarin.Mac.
Opciones de compilación de Aot
Hay varias opciones diferentes que se pueden ajustar al habilitar la compilación de AOT en una aplicación de Xamarin.Mac:
none- Sin compilación de AOT. Esta es la configuración predeterminada.all- AOT compila todos los ensamblados de MonoBundle.core- AOT compila los ensambladosXamarin.Mac,Systemymscorlib.sdk- AOT compila los ensamblados y bibliotecas de clases baseXamarin.Mac(BCL).|hybrid- Si se agrega a una de las opciones anteriores, se habilita el AOT híbrido, que permite la extracción de IL, pero dará lugar a tiempos de compilación más largos.+: incluye un único archivo para la compilación de AOT.-: quita un único archivo de la compilación de AOT.
Por ejemplo, habilitaría la compilación de AOT en todos los ensamblados de MonoBundle, excepto y habilitaría híbrido, el código AOT incluye y --aot:all,-MyAssembly.dll--aot:all,-MyAssembly.dllMyAssembly.dll excluye --aot:core|hybrid,+MyOtherAssembly.dll,-mscorlib.dllMyOtherAssembly.dllmscorlib.dll .
estático parcial registrar
Al desarrollar una aplicación de Xamarin.Mac, minimizar el tiempo entre completar un cambio y probarlo puede ser importante para cumplir las fechas límite de desarrollo. Estrategias como la modularización de código base y pruebas unitarias pueden ayudar a reducir los tiempos de compilación, ya que reducen el número de veces que una aplicación requerirá una recompilación completa costosa.
Además, y como novedad de Xamarin.Mac, partial static (tal y como lo ha hecho Xamarin.iOS) puede reducir drásticamente los tiempos de inicio de una aplicación de Xamarin.Mac en la configuración de depuración. Comprender cómo el uso de partial static puede dar lugar a una mejora casi cinco veces mayor en el inicio de depuración tendrá un poco de fondo sobre qué es , cuál es la diferencia entre estática y dinámica, y lo que hace esta versión Registrarregistrar "parcial estática".
Acerca de registrar
En el ámbito de cualquier aplicación de Xamarin.Mac se encuentra el marco Cocoa de Apple y el entorno de Objective-C ejecución. La principal responsabilidad de Xamarin.Mac es crear un puente entre este "mundo nativo" y el "mundo administrado" de C#. Parte de esta tarea se controla mediante registrar , que se ejecuta dentro del método NSApplication.Init () . Este es uno de los motivos por los que es necesario llamar primero a cualquier uso de las API de Cocoa NSApplication.Init en Xamarin.Mac.
El trabajo del objeto es informar al tiempo de ejecución de la existencia de las clases de C# de la aplicación que derivan de clases como registrarObjective-C , , y NSApplicationDelegateNSViewNSWindowNSObject . Esto requiere un examen de todos los tipos de la aplicación para determinar qué se debe registrar y qué elementos de cada tipo se deben notificar.
Este examen se puede realizar dinámicamente, al iniciar la aplicación con reflexión, o estáticamente,como un paso de tiempo de compilación. Al seleccionar un tipo de registro, el desarrollador debe tener en cuenta lo siguiente:
- El registro estático puede reducir drásticamente los tiempos de inicio, pero puede ralentizar considerablemente los tiempos de compilación (normalmente más del doble de tiempo de compilación de depuración). Este será el valor predeterminado para las compilaciones de configuración de versión.
- El registro dinámico retrasa este trabajo hasta que se inicia la aplicación y omite la generación de código, pero este trabajo adicional puede crear una pausa apreciable (al menos dos segundos) en el inicio de la aplicación. Esto es especialmente evidente en las compilaciones de configuración de depuración, que tienen como valor predeterminado el registro dinámico y cuya reflexión es más lenta.
El registro estático parcial, introducido por primera vez en Xamarin.iOS 8.13, proporciona al desarrollador la mejor de ambas opciones. Al calcular previamente la información de registro de cada elemento de y enviar esta información con Xamarin.Mac en una biblioteca estática (que solo debe vincularse en tiempo de compilación), Microsoft ha quitado la mayor parte del tiempo de reflexión de la dinámica, pero no afecta al tiempo de Xamarin.Mac.dllregistrar compilación.
habilitación de la estática parcial registrar
Partial Static se habilita en Xamarin.Mac haciendo doble clic en el nombre de Project en Explorador de soluciones , navegando a Mac Build (Compilación de Mac) y agregando al campo RegistrarRegistrar Additional mmp arguments: (Argumentos de mmp adicionales: ). Por ejemplo:
Agregar el registrador partial
a
argumentos mmp adicionales" title="Adding the partial static registrar to additional mmp arguments" data-linktype="relative-path"/>
Recursos adicionales
Estas son algunas explicaciones más detalladas de cómo funcionan internamente las cosas: