Compartir a través de


Migración de un enlace a Unified API

En este artículo se describen los pasos necesarios para actualizar un proyecto de Xamarin Binding existente para que sea compatible con las Unified API para aplicaciones de Xamarin.IOS y Xamarin.Mac.

Información general

A partir del 1 de febrero de 2015 Apple requiere que todos los nuevos envíos a iTunes y Mac App Store deben ser aplicaciones de 64 bits. Como resultado, cualquier aplicación nueva de Xamarin.iOS o Xamarin.Mac tendrá que utilizar la nueva Unified API en lugar de las API MonoTouch y MonoMac Classic existentes para admitir 64 bits.

Además, cualquier proyecto de enlace de datos de Xamarin también debe admitir las nuevas Unified API para incluirse en un proyecto de Xamarin.iOS o Xamarin.Mac de 64 bits. En este artículo se describen los pasos necesarios para actualizar un proyecto de enlace existente para que utilice la Unified API.

Requisitos

Se requiere lo siguiente para completar los pasos presentados en este artículo:

  • Visual Studio para Mac: la versión más reciente de Visual Studio para Mac instalada y configurada en el equipo de desarrollo.
  • Apple Mac: se requiere un equipo mac de Apple para compilar proyectos de enlace para iOS y Mac.

Los proyectos de enlace no son compatibles con Visual Studio en un equipo Windows.

Modificar las instrucciones Using

Las Unified API hacen que sea más fácil que nunca compartir código entre Mac e iOS, además de permitir soportar aplicaciones de 32 y 64 bits con el mismo binario. Al quitar los prefijos de MonoMac y MonoTouch de los espacios de nombres, se consigue un uso compartido más sencillo en los proyectos de aplicación de Xamarin.Mac y Xamarin.iOS.

Como resultado, tendremos que modificar cualquiera de nuestros contratos de enlace (y otros archivos .cs en nuestro proyecto de enlace) para eliminar los prefijos MonoMac y MonoTouch de nuestras instrucciones using.

Por ejemplo, dados los siguientes enunciados de uso en un contrato de enlace:

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.ObjCRuntime;

Quitaríamos el prefijo MonoTouch dando como resultado lo siguiente:

using System;
using System.Drawing;
using Foundation;
using UIKit;
using ObjCRuntime;

De nuevo, tendremos que hacerlo para cualquier archivo .cs en nuestro proyecto de enlace. Una vez realizado este cambio, el siguiente paso es actualizar nuestro proyecto de enlace para utilizar los nuevos tipos de datos nativos.

Para más información sobre la Unified API, consulte la documentación de Unified API. Para más información sobre el soporte de aplicaciones de 32 y 64 bits e información sobre marcos, consulte la documentación Consideraciones sobre plataformas de 32 y 64 bits.

Actualización a tipos de datos nativos

Objective-C asigna el tipo de datos NSInteger a int32_t en sistemas de 32 bits y a int64_t en sistemas de 64 bits. Para adaptarse a este comportamiento, la nueva Unified API sustituye los usos anteriores de int (que en .NET se define como que siempre es System.Int32) por un nuevo tipo de datos: System.nint.

Junto con el nuevo tipo de datos nint, Unified API también presenta los tipos nuint y nfloat, para asignarlos también a los tipos NSUInteger y CGFloat.

Teniendo en cuenta lo anterior, tenemos que revisar nuestra API y asegurarnos de que cualquier instancia de NSInteger, NSUInteger y CGFloat que anteriormente asignábamos a int, uint y float se actualiza a los nuevos tipos nint, nuint y nfloat.

Por ejemplo, dada una definición de método Objective-C de:

-(NSInteger) add:(NSInteger)operandUn and:(NSInteger) operandDeux;

Si el contrato de enlace anterior tenía la siguiente definición:

[Export("add:and:")]
int Add(int operandUn, int operandDeux);

Actualizaríamos el nuevo enlace para que sea:

[Export("add:and:")]
nint Add(nint operandUn, nint operandDeux);

Si estamos asignando a una biblioteca de terceros de la versión más reciente a la que habíamos vinculado inicialmente, es necesario revisar los archivos de encabezado de .h de la biblioteca y ver si alguna llamada explícita a int, int32_t, unsigned int, uint32_t o float se ha actualizado para que sea una NSInteger, NSUInteger o un CGFloat. Si es así, deben realizarse también las mismas modificaciones en el nint, nuint y nfloat tipos en sus asignaciones.

Para obtener más información sobre estos cambios del tipo de datos, consulte el documento Tipos nativos.

Actualizar los tipos CoreGraphics

Los tipos de datos point, size y rectangle que se usan con CoreGraphics usan 32 o 64 bits en función del dispositivo en el que se ejecutan. Cuando Xamarin enlazaba originalmente las API de iOS y Mac usamos estructuras de datos existentes que coincidieron con los tipos de datos de System.Drawing (RectangleF por ejemplo).

Debido a los requisitos para admitir 64 bits y los nuevos tipos de datos nativos, deben realizarse los siguientes ajustes en el código existente al llamar a métodos CoreGraphic :

  • CGRect : use CGRect en lugar de RectangleF al definir regiones rectangulares de número de punto flotante.
  • CGSize : use CGSize en lugar de SizeF al definir tamaños de número de punto flotante (ancho y alto).
  • CGPoint : use CGPoint en lugar de PointF al definir una ubicación de punto flotante (coordenadas X e Y).

Dado lo anterior, necesitaremos revisar nuestra API y asegurarnos de que cualquier instancia de CGRect, CGSize o CGPoint que se ha enlazado previamente a RectangleF, SizeF o PointF se cambie al tipo nativo CGRect, CGSize o CGPoint directamente.

Por ejemplo, dado un inicializador Objective-C de:

- (id)initWithFrame:(CGRect)frame;

Si el enlace anterior incluía el siguiente código:

[Export ("initWithFrame:")]
IntPtr Constructor (RectangleF frame);

Actualizaríamos ese código a:

[Export ("initWithFrame:")]
IntPtr Constructor (CGRect frame);

Con todos los cambios de código ahora en vigor, es necesario modificar el proyecto de enlace o hacer que el archivo se enlace con Unified API.

Modificar el proyecto de enlace

Como último paso para actualizar nuestro proyecto de enlace para usar las Unified API, es necesario modificar el MakeFile que usamos para compilar el proyecto o el tipo de proyecto de Xamarin (si estamos enlazando desde Visual Studio para Mac) e indicar a btouch enlazar con Unified API en lugar de las Classic.

Actualizar un MakeFile

Si usamos un archivo Make para compilar el proyecto de enlace en una .DLL de Xamarin, es necesario incluir la opción de línea de comandos --new-style y llamar a btouch-native en lugar de btouch.

Así que dado el siguiente MakeFile:

BINDDIR=/src/binding
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=XMBindingLibrarySample
PROJECT=$(PROJECT_ROOT)/XMBindingLibrarySample.xcodeproj
TARGET=XMBindingLibrarySample
BTOUCH=/Developer/MonoTouch/usr/bin/btouch

all: XMBindingLibrary.dll

libXMBindingLibrarySample-i386.a:
	$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator -configuration Release clean build
	-mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $@

libXMBindingLibrarySample-arm64.a:
	$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch arm64 -configuration Release clean build
	-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

libXMBindingLibrarySample-armv7.a:
	$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch armv7 -configuration Release clean build
	-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

libXMBindingLibrarySampleUniversal.a: libXMBindingLibrarySample-armv7.a libXMBindingLibrarySample-i386.a libXMBindingLibrarySample-arm64.a
	lipo -create -output $@ $^

XMBindingLibrary.dll: AssemblyInfo.cs XMBindingLibrarySample.cs extras.cs libXMBindingLibrarySampleUniversal.a
	$(BTOUCH) -unsafe -out:$@ XMBindingLibrarySample.cs -x=AssemblyInfo.cs -x=extras.cs --link-with=libXMBindingLibrarySampleUniversal.a,libXMBindingLibrarySampleUniversal.a

clean:
	-rm -f *.a *.dll

Necesitamos cambiar de llamar btouch a btouch-native, por lo que ajustaríamos nuestra definición de macro de la siguiente manera:

BTOUCH=/Developer/MonoTouch/usr/bin/btouch-native

Actualizaríamos la llamada a btouch y agregaríamos la opción --new-style de la siguiente manera:

XMBindingLibrary.dll: AssemblyInfo.cs XMBindingLibrarySample.cs extras.cs libXMBindingLibrarySampleUniversal.a
	$(BTOUCH) -unsafe --new-style -out:$@ XMBindingLibrarySample.cs -x=AssemblyInfo.cs -x=extras.cs --link-with=libXMBindingLibrarySampleUniversal.a,libXMBindingLibrarySampleUniversal.a

Ahora podemos ejecutar nuestra MakeFile como normal para compilar la nueva versión de 64 bits de nuestra API.

Actualizar un tipo de proyecto de enlace

Si usamos una plantilla de proyecto de enlace de Visual Studio para Mac para compilar nuestra API, es necesario actualizar a la nueva versión de Unified API de la plantilla de proyecto de enlace. La manera más fácil de hacerlo es iniciar un nuevo proyecto de enlace de Unified API y copiar todo el código y la configuración existentes.

Haga lo siguiente:

  1. Inicie Visual Studio para Mac:

  2. Seleccione Archivo>Nuevo>Solución...

  3. En el cuadro de diálogo Nueva solución, seleccione iOS>Unified API>Proyecto de enlace de iOS:

    En el cuadro de diálogo Nueva solución, seleccione iOS/Unified API/iOS Binding Project

  4. En el diálogo "Configurar el nuevo proyecto", escriba un Nombre para el nuevo proyecto de enlace y haga clic en el botón Aceptar.

  5. Incluye la versión de 64 bits de la biblioteca Objective-C para la que vaya a crear enlace de datos.

  6. Copie el código fuente del proyecto de enlace de Classic API de 32 bits existente (como los archivos de ApiDefinition.cs y StructsAndEnums.cs existentes).

  7. Realice los cambios indicados anteriormente en los archivos de código fuente.

Con todos estos cambios en su lugar, puede compilar la nueva versión de 64 bits de la API como lo haría con la versión de 32 bits.

Resumen

En este artículo, hemos mostrado los cambios que se deben realizar en un proyecto de enlace de Xamarin existente para admitir las nuevas Unified API y los dispositivos de 64 bits, así como los pasos necesarios para compilar la nueva versión compatible con 64 bits de una API.