Generación de código .xib en Xamarin.iOS

La herramienta Interface Builder ("IB") de Apple se puede usar para diseñar interfaces de usuario visualmente. Las definiciones de interfaz creadas por IB se guardan en archivos .xib. Los widgets y otros objetos de los archivos .xib pueden tener una "identidad de clase", que puede ser un tipo definido por el usuario personalizado. El uso de tipos personalizados permite personalizar el comportamiento de los widgets y escribir widgets personalizados.

Estas clases de usuario normalmente son subclases de clases de controlador de interfaz de usuario. Tienen salidas (propiedades) y acciones (eventos) que se pueden conectar a objetos de interfaz. En tiempo de ejecución, se carga el IB. En ese momento, los objetos se crean y las salidas y acciones se conectan dinámicamente a los distintos objetos de interfaz de usuario. Al definir estas clases administradas, debe definir todas las acciones y salidas para que coincidan con las que espera IB. Visual Studio para Mac usa un modelo similar a CodeBehind para simplificar el código. Xcode tiene un modelo Objective-C similar. Pero el modelo y las convenciones de generación de código de Xamarin.iOS se han modificado para que sean más familiares para los desarrolladores de .NET.

Archivos .xib y clases personalizadas

Es posible definir tipos personalizados en archivos .xib, además de usar los tipos existentes de Cocoa Touch. También es posible usar tipos que se definen en otros archivos .xib o que se definen exclusivamente en código de C#. Actualmente, Interface Builder no conoce los detalles de los tipos definidos fuera del archivo .xib actual, por lo que no los enumerará ni mostrará sus salidas y acciones personalizadas. La eliminación de esta limitación está planeada para algún momento en el futuro.

Las clases personalizadas se pueden definir en un archivo .xib mediante el comando "Agregar subclase" en la pestaña "Clases" de Interface Builder. Nos referimos a esas clases como clases "CodeBehind". Si el archivo .xib tiene un archivo homólogo de ".xib.designer.cs" en el proyecto, Visual Studio para Mac lo rellenará automáticamente con definiciones de clases parciales para todas las clases personalizadas del .xib. Nos referimos a estas clases parciales como "clases de diseñador".

Generar código

La generación de código está habilitada por la presencia de un archivo {0}.xib.designer.cs, para cualquier archivo {0}.xib con una acción de compilación de Página. Visual Studio para Mac genera clases parciales en el archivo del diseñador para todas las clases de usuario que puede encontrar en el archivo .xib. Visual Studio para Mac genera propiedades para salidas y métodos parciales para acciones.

El archivo del diseñador se actualiza automáticamente cuando cambia el archivo .xiby Visual Studio para Mac recupera el foco. No se recomienda realizar cambios en el archivo del diseñador, ya que los cambios se sobrescribirán la próxima vez que Visual Studio para Mac actualice el archivo.

Registros y espacios de nombres

Visual Studio para Mac genera las clases de diseñador mediante el espacio de nombres predeterminado del proyecto para la ubicación del archivo del diseñador. Este comportamiento es coherente con la generación normal del espacio de nombres del proyecto .NET. El espacio de nombres de los archivos de diseñador usa la configuración "espacio de nombres predeterminado" del proyecto y sus directivas de nomenclatura de ".NET". Si cambia el espacio de nombres predeterminado del proyecto, las clases regeneradas usarán el nuevo espacio de nombres. Después de la regeneración, es posible que las clases parciales ya no coincidan.

Para que el tiempo de ejecución Objective-C pueda detectar la clase, Visual Studio para Mac aplica un atributo [Register (name)] a la clase. Aunque Xamarin.iOS registra automáticamente las clases derivadas de NSObject, usa los nombres completos de .NET. El atributo aplicado por Visual Studio para Mac invalida el comportamiento de Xamarin.iOS para asegurarse de que cada clase se registra con el nombre usado en el archivo .xib. Agregue el atributo manualmente para todas las clases personalizadas definidas mediante IB, sin usar Visual Studio para Mac para generar archivos del diseñador. Al hacerlo, las clases administradas coinciden con los nombres de clase Objective-C esperados.

Las clases no se pueden definir en más de un .xib o entrarán en conflicto.

Elementos de clase que no son diseñadores

Las clases parciales del diseñador no están diseñadas para usarse tal como está. Las salidas son privadas y no se especifica ninguna clase base. Se espera que cada clase tenga una parte de clase "no diseñador" correspondiente en otro archivo. El archivo "no diseñador" establece la clase base, manipula las salidas y define constructores necesarios para crear instancias de la clase a partir del código nativo. Las plantillas .xib predeterminadas tienen las partes de clase "no diseñador", pero para cualquier otra clase personalizada que defina en un .xib, debe agregar manualmente el elemento no diseñador.

Esta separación mediante clases parciales es necesaria para la flexibilidad. Por ejemplo, varias clases CodeBehind podrían subclasificar una clase abstracta administrada común, que subclasifica la clase que va a ser subclasificada por IB.

Es convencional colocar clases CodeBehind en un archivo {0}.xib.cs junto al archivo de diseñador {0}.xib.designer.cs.

Acciones y salidas generadas

En las clases de diseñador parcial, Visual Studio para Mac genera propiedades correspondientes a las salidas conectadas definidas en IB y métodos parciales correspondientes a las acciones conectadas.

Propiedades de salida

Las clases de diseñador contienen propiedades correspondientes a todas las salidas definidas en la clase personalizada. Estas propiedades habilitan el enlace diferido. Son un detalle de implementación del puente de Xamarin.iOS a Objective C. Piense en ellos como equivalente a los campos privados, diseñados para usarse solo desde la clase CodeBehind. Haga que el campo sea público agregando el descriptor de acceso público al campo en el elemento de clase que no es de diseñador.

Si las propiedades de salida se definen para tener un tipo de id (equivalente a NSObject), el generador de código del diseñador determina actualmente el tipo más seguro posible en función de los objetos conectados a esa salida, por comodidad. Sin embargo, es posible que este comportamiento no se admita en versiones futuras. Se recomienda escribir explícitamente las salidas al definir la clase personalizada.

Propiedades de acción

Las clases de diseñador contienen métodos parciales correspondientes a todas las acciones definidas en la clase personalizada. Estos métodos no tienen una implementación. El propósito de los métodos parciales es doble:

  1. Si escribe partial en el cuerpo de clase del elemento de clase que no es de diseñador, Visual Studio para Mac ofrecerá autocompletar las firmas de todos los métodos parciales no implementados.
  2. Las firmas de método parcial tienen un atributo aplicado que los expone al mundo Objective-C, por lo que se pueden controlar como la acción correspondiente.

Puede omitir el método parcial e implementar la acción aplicando el atributo a otro método. O deje que pase a una clase base.

Si las acciones se definen para tener un tipo de remitente de id (equivalente a NSObject), el generador de código del diseñador determina actualmente el tipo más seguro posible en función de los objetos conectados a esa acción. Sin embargo, es posible que este comportamiento no se admita en versiones futuras. Se recomienda escribir explícitamente las acciones al definir la clase personalizada.

Estos métodos parciales solo se crean para C#, ya que CodeDOM no admite métodos parciales. No se generan para otros idiomas.

Uso de la clase cross-XIB

A veces, los usuarios desean hacer referencia a la misma clase desde varios archivos .xib, por ejemplo, con controladores de pestañas. Puede hacer referencia explícitamente a la definición de clase desde otro archivo .xib o definir de nuevo el mismo nombre de clase en el segundo .xib.

Este último caso puede ser problemático debido a que Visual Studio para Mac procesa archivos .xib individualmente. Visual Studio para Mac no puede detectar ni combinar definiciones duplicadas. Puede acabar con conflictos al aplicar el atributo Registro varias veces cuando se define la misma clase parcial en varios archivos de diseñador. Las versiones recientes de Visual Studio para Mac intentan resolver los conflictos, pero es posible que no siempre funcionen según lo previsto. En el futuro, es probable que este comportamiento no se admita y, en su lugar, Visual Studio para Mac hará que todos los tipos definidos en todos los archivos .xib y el código administrado del proyecto sean visibles directamente desde todos los archivos .xib.

Resolución de tipo

Los tipos usados en IB son nombres de tipo Objective-C asignados a tipos CLR mediante atributos Registro. Al generar código, Visual Studio para Mac resolverá los tipos CLR, calificando completamente los nombres de tipo a los tipos Objective-C. Estos tipos Objective-C se encapsulan en el núcleo de Xamarin.iOS.

El generador de código no puede resolver actualmente tipos CLR a partir de nombres de tipo Objective-C en bibliotecas o código de usuario. En tales casos, genera el nombre de tipo textualmente. Debe tener el mismo nombre que el tipo Objective-C para resolver correctamente el tipo CLR. El tipo CLR debe estar en el mismo espacio de nombres que el código que lo usa. Las versiones futuras del generador de código tendrán en cuenta todos los tipos Objective-C del proyecto.