type registrar for Xamarin.iOS
En este documento se describe el sistema de registro de tipos usado por Xamarin.iOS.
Registro de clases y métodos administrados
Durante el inicio, Xamarin.iOS registrará:
- Clases con un atributo [Register] como clases.
- Clases con un atributo [Category] como categorías.
- Interfaces con un atributo [Protocol] como protocolos.
- Miembros con un objeto [Export],lo que permite acceder a ellos.
Por ejemplo, considere el método Main administrado común en las aplicaciones de Xamarin.iOS:
UIApplication.Main (args, null, "AppDelegate");
Este código indica al Objective-C tiempo de ejecución que use el tipo llamado como clase de delegado de la AppDelegate aplicación. Para que Objective-C el tiempo de ejecución pueda crear una instancia de la clase de AppDelegate C#, esa clase debe registrarse.
Xamarin.iOS realiza el registro automáticamente, ya sea en tiempo de ejecución (registro dinámico) o en tiempo de compilación (registro estático).
El registro dinámico usa la reflexión en el inicio para buscar todas las clases y métodos que se registrarán, pasándolos al tiempo de Objective-C ejecución. El registro dinámico se usa de forma predeterminada para las compilaciones del simulador.
El registro estático inspecciona, en tiempo de compilación, los ensamblados utilizados por la aplicación. Determina las clases y los métodos con los que se va a registrar y genera un Objective-C mapa, que se inserta en el archivo binario. A continuación, en el inicio, registra el mapa con el tiempo de Objective-C ejecución. El registro estático se usa para las compilaciones de dispositivos.
Categorías
A partir de Xamarin.iOS 8.10, es posible crear categorías mediante la Objective-C sintaxis de C#.
Para crear una categoría, use el [Category] atributo y especifique el tipo que se va a extender. Por ejemplo, el código siguiente extiende NSString :
[Category (typeof (NSString))]
Cada uno de los métodos de una categoría tiene un [Export] atributo , lo que hace que esté disponible para el tiempo de Objective-C ejecución:
[Export ("today")]
public static string Today ()
{
return "Today";
}
Todos los métodos de extensión administrados deben ser estáticos, pero es posible crear métodos de instancia mediante la sintaxis estándar de Objective-C C# para los métodos de extensión:
[Export ("toUpper")]
public static string ToUpper (this NSString self)
{
return self.ToString ().ToUpper ();
}
El primer argumento para el método de extensión es la instancia en la que se invocó el método :
[Category (typeof (NSString))]
public static class MyStringCategory
{
[Export ("toUpper")]
static string ToUpper (this NSString self)
{
return self.ToString ().ToUpper ();
}
}
En este ejemplo se agregará un método toUpper de instancia nativo a la clase NSString . Se puede llamar a este método desde Objective-C :
[Category (typeof (UIViewController))]
public static class MyViewControllerCategory
{
[Export ("shouldAutoRotate")]
static bool GlobalRotate ()
{
return true;
}
}
Protocolos
A partir de Xamarin.iOS 8.10, las interfaces con el atributo se [Protocol] exportarán Objective-C a como protocolos:
[Protocol ("MyProtocol")]
interface IMyProtocol
{
[Export ("method")]
void Method ();
}
class MyClass : IMyProtocol
{
void Method ()
{
}
}
Este código exporta IMyProtocol a como un protocolo denominado y una clase denominada que implementa el Objective-CMyProtocolMyClass protocolo.
Nuevo sistema de registro
A partir de la versión estable 6.2.6 y la versión beta 6.3.4, hemos agregado un nuevo estático registrar . En la versión 7.2.1, hemos hecho del nuevo registrar el valor predeterminado.
Este nuevo sistema de registro ofrece las siguientes características nuevas:
Detección en tiempo de compilación de errores del programador:
- Se registran dos clases con el mismo nombre.
- Más de un método exportado para responder al mismo selector
Eliminación de código nativo sin usar:
- El nuevo sistema de registro agregará referencias seguras al código usado en bibliotecas estáticas, lo que permite al vinculador nativo quitar el código nativo no utilizado del binario resultante. En los enlaces de ejemplo de Xamarin, la mayoría de las aplicaciones se vuelven al menos 300 000 menos.
Compatibilidad con subclases
NSObjectgenéricas de ; veaNSObjectpara obtener más información. Además, el nuevo sistema de registro detectará construcciones genéricas no admitidas que anteriormente habrían provocado un comportamiento aleatorio en tiempo de ejecución.
errores detectados por el nuevo registrar
A continuación se muestran algunos ejemplos de los errores detectados por el nuevo registrar .
Exportar el mismo selector más de una vez en la misma clase:
[Register] class MyDemo : NSObject { [Export ("foo:")] void Foo (NSString str); [Export ("foo:")] void Foo (string str) }Exportación de más de una clase administrada con el mismo Objective-C nombre:
[Register ("Class")] class MyClass : NSObject {} [Register ("Class")] class YourClass : NSObject {}Exportación de métodos genéricos:
[Register] class MyDemo : NSObject { [Export ("foo")] void Foo<T> () {} }
limitaciones del nuevo registrar
Algunos aspectos que debe tener en cuenta sobre el nuevo registrar :
Algunas bibliotecas de terceros deben actualizarse para que funcionen con el nuevo sistema de registro. Consulte las modificaciones necesarias a continuación para obtener más detalles.
Una desventaja a corto plazo es también que Clang debe usarse si se usa el marco accounts (esto se debe a que el encabezado accounts.h de Apple solo se puede compilar mediante Clang). Agregue a los argumentos mtouch adicionales para usar Clang si usa Xcode 4.6 o versiones anteriores
--compiler:clang(Xamarin.iOS seleccionará automáticamente Clang en Xcode 5.0 o posterior).Si se usa Xcode 4.6 (o versiones anteriores), se debe seleccionar GCC/G++ si los nombres de tipo exportados contienen caracteres no ASCII (esto se debe a que la versión de Clang incluida con Xcode 4.6 no admite caracteres no ASCII dentro de identificadores en el Objective-C código). Agregue
--compiler:gcca los argumentos mtouch adicionales para usar GCC.
seleccionar un registrar
Puede seleccionar otro si agrega una de las siguientes opciones a los argumentos mtouch adicionales en la configuración de compilación de registrarregistrar proyecto:
--registrar:static: valor predeterminado para las compilaciones de dispositivos--registrar:dynamic: valor predeterminado para las compilaciones del simulador
Nota:
Xamarin admite Classic API otras opciones, como --registrar:legacystatic y --registrar:legacydynamic . Sin embargo, estas opciones no son compatibles con el Unified API.
Deficiencias en el sistema de registro anterior
El sistema de registro anterior tiene las siguientes desventajas:
- No había ninguna referencia estática (nativa) a clases y métodos en bibliotecas nativas de terceros, lo que significaba que no se podía pedir al vinculador nativo que quitara código nativo de terceros que no se usara realmente (porque se quitaría Objective-C todo). Este es el motivo por el que todos los enlaces de terceros tenían que
-force_load libNative.ahacer (o el equivalenteForceLoad=trueen el atributo[LinkWith]). - Podría exportar dos tipos administrados con el mismo Objective-C nombre sin ninguna advertencia. Un escenario poco frecuente era acabar con dos
AppDelegateclases en espacios de nombres diferentes. En tiempo de ejecución sería completamente aleatorio cuál se ha elegido (de hecho, variaba entre las ejecuciones de una aplicación que ni siquiera se recompiló, lo que hizo que se disfrutara de una experiencia de depuración muy desconcertante y frustrante). - Puede exportar dos métodos con la misma Objective-C firma. Una vez más, el que se llamaría desde era aleatorio (pero este problema no era tan común como el anterior, principalmente porque la única manera de experimentar realmente este error era invalidar el método administrado sin Objective-C problemas).
- El conjunto de métodos que se exportó era ligeramente diferente entre las compilaciones dinámicas y estáticas.
- No funciona correctamente al exportar clases genéricas (cuya implementación genérica exacta ejecutada en tiempo de ejecución sería aleatoria, lo que daría lugar a un comportamiento indeterminado).
registrar Nuevo: cambios necesarios en los enlaces
En esta sección se describen los cambios de enlaces que se deben realizar para trabajar con el nuevo registrar .
Los protocolos deben tener el atributo [Protocol].
Los protocolos ahora deben tener el [Protocol] atributo . Si no lo hace, se producirá un error del vinculador nativo como:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_ProtocolName", referenced from: ...
Los selectores deben tener un número válido de parámetros
Todos los selectores deben indicar correctamente el número de parámetros. Anteriormente, estos errores se omitían y podían causar problemas en tiempo de ejecución.
En resumen, el número de dos puntos debe coincidir con el número de parámetros:
- Sin parámetros:
foo - Un parámetro:
foo: - Dos parámetros:
foo:parameterName2:
Los siguientes son usos incorrectos:
// Invalid: export takes no arguments, but function expects one
[Export ("apply")]
void Apply (NSObject target);
// Invalid: exported as taking an argument, but the managed version does not have one:
[Export ("display:")]
void Display ();
Uso del parámetro IsVariadic en Export
Las funciones variádicas deben IsVariadic usar el argumento para el atributo [Export] :
[Export ("variadicMethod:", IsVariadic = true)]
void VariadicMethod (NSObject first, IntPtr subsequent);
Debe vincular a símbolos existentes
Es imposible enlazar clases que no existen en la biblioteca nativa. Si se ha quitado o cambiado el nombre de una clase de la biblioteca nativa, asegúrese de actualizar los enlaces para que coincidan.