Tutorial: Enlazar una biblioteca de Objective-C iOS

Importante

Estamos investigando el uso de enlaces personalizados en la plataforma Xamarin. Realice esta encuesta para informar de esfuerzos de desarrollo futuros.

En este artículo se proporciona un tutorial práctica sobre la creación de un enlace de Xamarin.iOS para una biblioteca Objective-C existente, InfColorPicker. Trata temas como compilar una biblioteca estática, enlazarla y usar el enlace Objective-C en una aplicación xamarin.iOS.

Al trabajar en iOS, es posible que encuentre casos en los que quiera consumir una biblioteca de Objective-C terceros. En esas situaciones, puede usar un enlace de Xamarin.iOS Project para crear un enlace de C# que le permitirá consumir la biblioteca en las aplicaciones de Xamarin.iOS.

Por lo general, en el ecosistema de iOS puede encontrar bibliotecas en tres tipos:

  • Como archivo de biblioteca estática precompilado con .a extensión junto con sus encabezados (archivos .h). Por ejemplo, la biblioteca de análisis de Google
  • Como marco precompilado. Se trata simplemente de una carpeta que contiene la biblioteca estática, los encabezados y, a veces, recursos adicionales con .framework extensión. Por ejemplo, la biblioteca AdMob de Google.
  • Como solo archivos de código fuente. Por ejemplo, una biblioteca que contiene archivos Just .m.h y Objective C.

En el primer y segundo escenario ya habrá una biblioteca estática de CocoaTouch precompilada, por lo que en este artículo nos centraremos en el tercer escenario. Recuerde que, antes de empezar a crear un enlace, compruebe siempre la licencia proporcionada con la biblioteca para asegurarse de que está libre de enlazarlo.

En este artículo se proporciona un tutorial paso a paso sobre la creación de un proyecto de enlace mediante el proyecto InfColorPicker de código abierto como ejemplo, pero toda la información de esta guía se puede adaptar para su uso con cualquier biblioteca de Objective-C terceros. La biblioteca InfColorPicker proporciona un controlador de vista reutilizable que permite al usuario seleccionar un color en función de su representación HSB, lo que hace que la selección de colores sea más fácil de usar.

Ejemplo de la biblioteca InfColorPicker que se ejecuta en iOS

Se tratarán todos los pasos necesarios para consumir esta Objective-C API concreta en Xamarin.iOS:

  • En primer lugar, crearemos una Objective-C biblioteca estática mediante Xcode.
  • A continuación, enlazaremos esta biblioteca estática con Xamarin.iOS.
  • A continuación, muestre cómo Objective Sharpie puede reducir la carga de trabajo generando automáticamente algunas (pero no todas) de las definiciones de API necesarias que requiere el enlace de Xamarin.iOS.
  • Por último, crearemos una aplicación xamarin.iOS que use el enlace.

La aplicación de ejemplo mostrará cómo usar un delegado seguro para la comunicación entre la API InfColorPicker y nuestro código de C#. Una vez que hayamos visto cómo usar un delegado seguro, veremos cómo usar delegados débiles para realizar las mismas tareas.

Requisitos

En este artículo se supone que está familiarizado con Xcode y el Objective-C lenguaje y que ha leído nuestra Binding Objective-C documentación. Además, se requiere lo siguiente para completar los pasos presentados:

  • SDK de Xcode e iOS: Xcode de Apple y la API de iOS más reciente deben instalarse y configurarse en el equipo del desarrollador.
  • Herramientas de línea de comandos de Xcode: las herramientas de línea de comandos de Xcode deben estar instaladas para la versión instalada actualmente de Xcode (consulte a continuación los detalles de instalación).
  • Visual Studio para Mac o Visual Studio: la versión más reciente de Visual Studio para Mac o Visual Studio debe instalarse y configurarse en el equipo de desarrollo. Se requiere un Mac de Apple para desarrollar una aplicación xamarin.iOS y, al usar Visual Studio debe estar conectado a un host de compilación de Xamarin.iOS.
  • La versión más reciente de Objective Sharpie: una copia actual de la herramienta Objective Sharpie descargada desde aquí. Si ya tiene Objective Sharpie instalado, puede actualizarlo a la versión más reciente mediante el sharpie update

Instalación de las herramientas de línea de comandos de Xcode

Como se indicó anteriormente, usaremos las herramientas de la línea de comandos de Xcode (específicamente make y ) en este lipo tutorial. El comando es una utilidad de Unix muy común que automatizará la compilación de bibliotecas y programas ejecutables mediante un archivo Make que especifica cómo se debe compilar make el programa. make El comando es una utilidad de línea de comandos de OS X para crear archivos de arquitectura múltiple; combinará varios archivos en un archivo que pueden usar todas lipo.a las arquitecturas de hardware.

Según la documentación de las preguntas más frecuentes sobre la creación de Apple desde la línea de comandos con Xcode, en OS X 10.9 y superior, el panel Descargas del cuadro de diálogo Preferencias de Xcode ya no admite la descarga de herramientas de línea de comandos.

Deberá usar uno de los métodos siguientes para instalar las herramientas:

  • Instalar Xcode: al instalar Xcode, se incluye con todas las herramientas de línea de comandos. En las correcciones de compatibilidad (shim) de OS X 10.9 (instaladas en ), puede asignar cualquier herramienta incluida en a la herramienta correspondiente /usr/bin/usr/bin dentro de Xcode. Por ejemplo, el comando , que permite buscar o ejecutar cualquier herramienta xcrun dentro de Xcode desde la línea de comandos.

  • La aplicación terminal: desde la aplicación Terminal, puede instalar las herramientas de línea de comandos mediante la ejecución del comando :

    • Inicie la aplicación terminal.
    • Escriba xcode-select --install y presione xcode-select --installpor ejemplo:
    Europa:~ kmullins$ xcode-select --install
    
    • Se le pedirá que instale las herramientas de línea de comandos, haga clic en el botón Instalar:Instalación de las herramientas de línea de comandos.

    • Las herramientas se descargarán e instalarán desde los servidores de Apple: Descarga de las herramientas

  • Descargas para desarrolladores de Apple: el paquete herramientas de línea de comandos está disponible en la página web Descargas para desarrolladores de Apple. Inicie sesión con su id. de Apple y, a continuación, busque y descargue las herramientas de línea de comandos: Buscar las herramientas de línea de comandos.

Con las herramientas de línea de comandos instaladas, estamos listos para continuar con el tutorial.

Tutorial

En este tutorial, se tratarán los pasos siguientes:

  • Crear una biblioteca estática: este paso implica la creación de una biblioteca estática del código InfColorPicker. La biblioteca estática tendrá la .a extensión de archivo y se incrustará en el ensamblado .NET del proyecto de biblioteca.
  • Creación de un enlace de Xamarin.iOS Project: una vez que tenemos una biblioteca estática, la usaremos para crear un proyecto de enlace de Xamarin.iOS. El proyecto de enlace consta de la biblioteca estática que acaba de crear y metadatos en forma de código de C# que explica cómo se Objective-C puede usar la API. Estos metadatos se conocen normalmente como definiciones de API. Usaremos Objective Sharpie para ayudarnos a crear las definiciones de API.
  • Normalizar las definiciones de API: Objective Sharpie hace un gran trabajo de ayudarnos, pero no puede hacer todo. Analizaremos algunos cambios que debemos realizar en las definiciones de API antes de que se puedan usar.
  • Usar la biblioteca de enlaces: por último, crearemos una aplicación de Xamarin.iOS para mostrar cómo usar el proyecto de enlace recién creado.

Ahora que sabemos qué pasos implican, vamos a pasar al resto del tutorial.

Creación de una biblioteca estática

Si inspeccionamos el código de InfColorPicker en Github:

Inspección del código de InfColorPicker en GitHub

Podemos ver los tres directorios siguientes en el proyecto:

  • InfColorPicker: este directorio contiene el código del proyecto.
  • PickerSamplePad: este directorio contiene un ejemplo iPad proyecto.
  • PickerSamplePhone: este directorio contiene un ejemplo iPhone proyecto.

Vamos a descargar el proyecto InfColorPicker desde GitHub descomprimirlo en el directorio que elijamos. Al abrir el destino Xcode para PickerSamplePhone el proyecto, vemos la siguiente estructura de proyecto en el navegador de Xcode:

Estructura del proyecto en el navegador de Xcode

Este proyecto consigue reutilizar el código agregando directamente el código fuente infColorPicker (en el cuadro rojo) a cada proyecto de ejemplo. El código del proyecto de ejemplo está dentro del cuadro azul. Dado que este proyecto concreto no nos proporciona una biblioteca estática, es necesario crear un proyecto de Xcode para compilar la biblioteca estática.

El primer paso es agregar el código fuente de InfoColorPicker a la biblioteca estática. Para lograr esto, vamos a hacer lo siguiente:

  1. Inicie Xcode.

  2. En el menú Archivo,seleccione NuevoProject...:

    Captura de pantalla Project seleccionado en el menú Nuevo del menú Archivo.

  3. Seleccione Biblioteca de marcos, la plantilla Cocoa Touch Static Library y haga clic en el botón Siguiente:

    Selección de la plantilla Cocoa Touch Static Library

  4. Escriba InfColorPicker para el nombre Project InfColorPicker haga clic en el botón Siguiente:

    Escriba InfColorPicker para el nombre Project usuario.

  5. Seleccione una ubicación para guardar el proyecto y haga clic en el botón Aceptar.

  6. Ahora es necesario agregar el origen del proyecto InfColorPicker a nuestro proyecto de biblioteca estática. Dado que el archivo InfColorPicker.h ya existe en nuestra biblioteca estática (de forma predeterminada), Xcode no nos permitirá sobrescribirlo. En finder,vaya al código fuente InfColorPicker del proyecto original que descomprimió de GitHub, copie todos los archivos InfColorPicker y péguelos en nuestro nuevo proyecto de biblioteca estática:

    Copia de todos los archivos InfColorPicker

  7. Vuelva a Xcode, haga clic con el botón derecho en la carpeta InfColorPicker y seleccione Agregar archivos a "InfColorPicker...":

    Adición de archivos

  8. En el cuadro de diálogo Agregar archivos, vaya a los archivos de código fuente InfColorPicker que acaba de copiar, selecciónelos todos y haga clic en el botón Agregar:

    Seleccionar todo y hacer clic en el botón Agregar

  9. El código fuente se copiará en nuestro proyecto:

    El código fuente se copiará en el proyecto

  10. En Xcode Project Navigator, seleccione el archivo InfColorPicker.m y comente las dos últimas líneas (debido a la forma en que se escribió esta biblioteca, este archivo no se usa):

    Edición del archivo InfColorPicker.m

  11. Ahora es necesario comprobar si hay algún marco necesario para la biblioteca. Puede encontrar esta información en el ARCHIVO LÉAME o abriendo uno de los proyectos de ejemplo proporcionados. En este ejemplo Foundation.framework se usa , , por lo que vamos a UIKit.frameworkCoreGraphics.framework agregarlos.

  12. Seleccione las fases de compilación de destino de InfColorPicker y expanda la sección Vincular binario con bibliotecas:

    Expanda la sección Vincular binario con bibliotecas.

  13. Use el + botón para abrir el cuadro de diálogo, lo que le permite agregar los marcos de fotogramas necesarios enumerados anteriormente:

    Agregue los marcos de fotogramas necesarios enumerados anteriormente.

  14. La sección Vincular binario con bibliotecas ahora debe tener un aspecto parecido al de la imagen siguiente:

    Sección Vincular binario con bibliotecas

En este momento estamos cerca, pero no hemos terminado del todo. Se ha creado la biblioteca estática, pero es necesario compilarla para crear un binario fat que incluya todas las arquitecturas necesarias para el dispositivo iOS y el simulador de iOS.

Crear un binario fat

Todos los dispositivos iOS tienen procesadores con tecnología de la arquitectura arm que se han desarrollado con el tiempo. Cada nueva arquitectura agregó nuevas instrucciones y otras mejoras, a la vez que se mantiene la compatibilidad con versiones anteriores. Los dispositivos iOS tienen conjuntos de instrucciones armv6, armv7, armv7s y arm64, aunque armv6ya no usa . El simulador de iOS no funciona con ARM y, en su lugar, es un simulador con tecnología x86 y x86_64 con tecnología. Esto significa que se deben proporcionar bibliotecas para cada conjunto de instrucciones.

Una biblioteca Fat es .a un archivo que contiene todas las arquitecturas admitidas.

La creación de un binario fat es un proceso de tres pasos:

  • Compile una versión ARM 7 & ARM64 de la biblioteca estática.
  • Compile una versión x86 x84_64 de la biblioteca estática.
  • Use la lipo herramienta de línea de comandos para combinar las dos bibliotecas estáticas en una.

Aunque estos tres pasos son bastante sencillos, puede que sea necesario repetirlos en el futuro cuando la biblioteca reciba actualizaciones o si se requieren Objective-C correcciones de errores. Si decide automatizar estos pasos, simplificará el mantenimiento futuro y la compatibilidad del proyecto de enlace de iOS.

Hay muchas herramientas disponibles para automatizar estas tareas: un script de shell, rake,xbuildy make. Cuando se instalan las herramientas de línea de comandos de Xcode, también se instala , por lo que es el sistema de compilación que se usará make para este tutorial. Este es un archivo Make que puede usar para crear una biblioteca compartida de arquitectura múltiple que funcionará en un dispositivo iOS y en el simulador de cualquier biblioteca:

XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=./YOUR-PROJECT-NAME
PROJECT=$(PROJECT_ROOT)/YOUR-PROJECT-NAME.xcodeproj
TARGET=YOUR-PROJECT-NAME

all: lib$(TARGET).a

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

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

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

lib$(TARGET).a: lib$(TARGET)-i386.a lib$(TARGET)-armv7.a lib$(TARGET)-arm64.a
	xcrun -sdk iphoneos lipo -create -output $@ $^

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

Escriba los comandos makefile en el editor de texto sin formato que elija y actualice las secciones con YOUR-PROJECT-NAME con el nombre del proyecto. También es importante asegurarse de pegar exactamente las instrucciones anteriores, con las pestañas dentro de las instrucciones conservadas.

Guarde el archivo con el nombre Makefile en la misma ubicación que la biblioteca estática InfColorPicker Xcode que creamos anteriormente:

Guarde el archivo con el nombre Makefile.

Abra la aplicación terminal en el equipo Mac y vaya a la ubicación del archivo Make. Escriba make en terminal, presione make y se ejecutará el archivo Make:

Salida de archivo Make de ejemplo

Al ejecutar make, verá una gran cantidad de texto que se desplaza por . Si todo ha funcionado correctamente, verá las palabras BUILD SUCCEEDED y , y los archivos se copiarán en la misma ubicación que el archivo libInfColorPicker-i386.alibInfColorPickerSDK.alibInfColorPicker-i386.a:

Los archivos libInfColorPicker-armv7.a, libInfColorPicker-i386.a y libInfColorPickerSDK.a generados por el archivo Make

Puede confirmar las arquitecturas dentro del binario fat mediante el comando siguiente:

xcrun -sdk iphoneos lipo -info libInfColorPicker.a

Esto debería mostrar lo siguiente:

Architectures in the fat file: libInfColorPicker.a are: i386 armv7 x86_64 arm64

En este punto, hemos completado el primer paso del enlace de iOS mediante la creación de una biblioteca estática mediante Xcode y las herramientas de línea de comandos de Xcode make y lipo . Vamos a pasar al paso siguiente y usar Objective-Sharpie para automatizar la creación de los enlaces de API.

Creación de un enlace de Xamarin.iOS Project

Para poder usar Objective-Sharpie para automatizar el proceso de enlace, es necesario crear un Project de enlace de Xamarin.iOS para hospedar las definiciones de API (que usaremos Objective-Sharpie para ayudarnos a compilar) y crear el enlace de C# para nosotros.

Vamos a hacer lo siguiente:

  1. Inicie Visual Studio para Mac:

  2. En el menú Archivo, seleccione Nueva solución...:

    Inicio de una nueva solución

  3. En el cuadro de diálogo Nueva solución, seleccione Bibliotecaenlace de iOS Project:

    Seleccione Enlace de iOS Project

  4. Haga clic en el botón Next (Siguiente).

  5. Escriba "InfColorPickerBinding" como nombre Project y haga clic en el botón Crear para crear la solución:

    Escriba InfColorPickerBinding como nombre Project aplicación

Se creará la solución y se incluirán dos archivos predeterminados:

Estructura de la solución en el Explorador de soluciones

  • ApiDefinition.cs: este archivo contendrá los contratos que definen cómo se encapsularán las API en C#.
  • Structs.cs: este archivo contendrán las estructuras o valores de enumeración que requieran las interfaces y los delegados.

Trabajaremos con estos dos archivos más adelante en el tutorial. En primer lugar, es necesario agregar la biblioteca InfColorPicker al proyecto de enlace.

Incluir la biblioteca estática en el enlace Project

Ahora que tenemos el enlace base Project listo, es necesario agregar la biblioteca Fat Binary que creamos anteriormente para la biblioteca InfColorPicker.

Siga estos pasos para agregar la biblioteca:

  1. Haga clic con el botón derecho en la carpeta Referencias nativas de la Panel de solución seleccione Agregar referencias nativas:

    Agregar referencias nativas

  2. Vaya al fat binary que hemos hecho anteriormente ( libInfColorPickerSDK.a ) y presione el libInfColorPickerSDK.a Abrir:

    Seleccione el archivo libInfColorPickerSDK.a.

  3. El archivo se incluirá en el proyecto:

    Incluir un archivo

Cuando se agrega el archivo .a al proyecto, Xamarin.iOS establecerá automáticamente la acción de compilación del archivo en ObjcBindingNativeLibraryy creará un archivo especial denominado .

Este archivo contiene el LinkWith atributo que indica a Xamarin.iOS cómo controlar la biblioteca estática que se acaba de agregar. El contenido de este archivo se muestra en el siguiente fragmento de código:

using ObjCRuntime;

[assembly: LinkWith ("libInfColorPickerSDK.a", SmartLink = true, ForceLoad = true)]

El LinkWith atributo identifica la biblioteca estática para el proyecto y algunas marcas importantes del vinculador.

Lo siguiente que debemos hacer es crear las definiciones de API para el proyecto InfColorPicker. Para los fines de este tutorial, usaremos Objective Sharpie para generar el archivo ApiDefinition.cs.

Uso de Objective Sharpie

Objective Sharpie es una herramienta de línea de comandos (proporcionada por Xamarin) que puede ayudar a crear las definiciones necesarias para enlazar una biblioteca de terceros a Objective-C C#. En esta sección, usaremos Objective Sharpie para crear el archivo ApiDefinition.cs inicial para el proyecto InfColorPicker.

Para empezar, vamos a descargar el archivo del instalador de Objective Sharpie como se detalla en esta guía. Ejecute el instalador y siga todas las indicaciones en pantalla del Asistente para instalación para instalar Objective Sharpie en nuestro equipo de desarrollo.

Una vez que objective sharpie se haya instalado correctamente, vamos a iniciar la aplicación Terminal y a escribir el siguiente comando para obtener ayuda sobre todas las herramientas que proporciona para ayudar en el enlace:

sharpie -help

Si ejecutamos el comando anterior, se generará la siguiente salida:

Europa:Resources kmullins$ sharpie -help
usage: sharpie [OPTIONS] TOOL [TOOL_OPTIONS]

Options:
  -h, --helpShow detailed help
  -v, --versionShow version information

Available Tools:
  xcode              Get information about Xcode installations and available SDKs.
  pod                Create a Xamarin C# binding to Objective-C CocoaPods
  bind               Create a Xamarin C# binding to Objective-C APIs
  update             Update to the latest release of Objective Sharpie
  verify-docs        Show cross reference documentation for [Verify] attributes
  docs               Open the Objective Sharpie online documentation

Para este tutorial, usaremos las siguientes herramientas de Objective Sharpie:

  • xcode: estas herramientas nos dan información sobre la instalación actual de Xcode y las versiones de las API de iOS y Mac que hemos instalado. Usaremos esta información más adelante cuando generemos nuestros enlaces.
  • bind: usaremos esta herramienta para analizar los archivos .h del proyecto InfColorPicker en los archivos ApiDefinition.cs y StructsAndEnums.cs iniciales.

Para obtener ayuda sobre una herramienta específica de Objective Sharpie, escriba el nombre de la herramienta y la -help opción. Por ejemplo, sharpie xcode -help devuelve la siguiente salida:

Europa:Resources kmullins$ sharpie xcode -help
usage: sharpie xcode [OPTIONS]+

Options:
  -h, -help           Show detailed help
  -v, -verbose        Be verbose with output

Xcode Options:
  -sdks               List all available Xcode SDKs. Pass -verbose for more
                        details.
  -sdkpath SDK        Output the path of the SDK
  -frameworks SDK     List all available framework directories in a given SDK.

Para poder iniciar el proceso de enlace, es necesario obtener información sobre nuestros SDK instalados actuales; para ello, escriba el siguiente comando en el terminal sharpie xcode -sdks :

amyb:Desktop amyb$ sharpie xcode -sdks
sdk: appletvos9.2    arch: arm64
sdk: iphoneos9.3     arch: arm64   armv7
sdk: macosx10.11     arch: x86_64  i386
sdk: watchos2.2      arch: armv7

A partir de lo anterior, podemos ver que tenemos el iphoneos9.3 SDK instalado en nuestro equipo. Con esta información, estamos listos para analizar los archivos de proyecto InfColorPicker en el .h.h inicial y para el proyecto StructsAndEnums.cs InfColorPicker.

Escriba el siguiente comando en la aplicación Terminal:

sharpie bind --output=InfColorPicker --namespace=InfColorPicker --sdk=[iphone-os] -scope [full-path-to-project]/InfColorPicker/InfColorPicker [full-path-to-project]/InfColorPicker/InfColorPicker/*.h

Donde es la ruta de acceso completa al directorio donde se encuentra el archivo de proyecto [full-path-to-project][full-path-to-project] Xcode en nuestro equipo y [iphone-os] es el SDK de iOS que hemos instalado, como se indica en el sharpie xcode -sdks comando . Tenga en cuenta que en este ejemplo hemos pasado *.h como parámetro, que incluye todos los archivos de encabezado de este directorio; normalmente, NO debe hacerlo, sino leer cuidadosamente los archivos de encabezado para buscar el archivo .h de nivel superior que hace referencia a todos los demás archivos pertinentes y simplemente pasarlo a Objective Sharpie.

Sugerencia

Para el -scope argumento , pase la carpeta que tiene los encabezados que desea enlazar. Sin el argumento , Objective Sharpie intentará generar enlaces para los encabezados del SDK de iOS que se importan, por ejemplo, , lo que da lugar a un archivo de definiciones enorme que probablemente generará errores al compilar el proyecto de -scope#import <UIKit.h> enlace. Con el argumento establecido, Objective Sharpie no generará enlaces para ningún -scope encabezado fuera de la carpeta con ámbito.

La siguiente salida se generará en el terminal:

Europa:Resources kmullins$ sharpie bind -output InfColorPicker -namespace InfColorPicker -sdk iphoneos8.1 /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h -unified
Compiler configuration:
    -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -miphoneos-version-min=8.1 -resource-dir /Library/Frameworks/ObjectiveSharpie.framework/Versions/1.1.1/clang-resources -arch armv7 -ObjC

[  0%] parsing /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h
In file included from /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h:60:
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: no 'assign',
      'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute]
@property (nonatomic) UIColor* sourceColor;
^
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: default property
      attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: no 'assign',
      'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute]
@property (nonatomic) UIColor* resultColor;
^
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: default property
      attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
4 warnings generated.
[100%] parsing complete
[bind] InfColorPicker.cs
Europa:Resources kmullins$

Y los archivos InfColorPicker.enums.cs e InfColorPicker.cs se crearán en nuestro directorio:

Los archivos InfColorPicker.enums.cs e InfColorPicker.cs

Abra ambos archivos en el proyecto de enlace que creamos anteriormente. Copie el contenido del archivo InfColorPicker.cs y péguelo en el archivo ApiDefinition.cs, reemplazando el bloque de código existente por el contenido del archivo InfColorPicker.cs (dejando intactas las instrucciones):

Archivo InfColorPickerControllerDelegate

Normalización de las definiciones de API

Objective Sharpie a veces tiene un problema al traducir , por lo que tendremos que modificar la definición de la interfaz y reemplazar Delegates la línea por lo InfColorPickerControllerDelegate[Protocol, Model] siguiente:

[BaseType(typeof(NSObject))]
[Model]

Para que la definición sea similar a la siguiente:

Definición

A continuación, hacemos lo mismo con el contenido del archivo y los copiamos y pegamos en el archivo, dejando InfColorPicker.enums.csStructsAndEnums.csusing intactas las instrucciones:

Contenido del archivo StructsAndEnums.cs

También puede encontrar que Objective Sharpie ha anotado el enlace con [Verify] atributos. Estos atributos indican que debe comprobar que Objective Sharpie hizo lo correcto comparando el enlace con la declaración C/ original (que se proporciona en un comentario por encima de la declaración Objective-C enlazada). Una vez que haya comprobado los enlaces, debe quitar el atributo verify. Para obtener más información, consulte la Guía de comprobación.

En este momento, nuestro proyecto de enlace debe estar completo y listo para compilarse. Vamos a compilar el proyecto de enlace y a asegurarnos de que terminamos sin errores:

Compilar el proyecto de enlace y asegurarse de que no hay errores

Usar el enlace

Siga estos pasos para crear una aplicación de iPhone ejemplo para usar la biblioteca de enlaces de iOS creada anteriormente:

  1. Creación de un proyecto de Xamarin.iOS Project: agregue un nuevo proyecto de Xamarin.iOS denominado InfColorPickerSample a la solución, como se muestra en las capturas de pantalla siguientes:

    Agregar una aplicación de vista única

    Establecer el identificador

  2. Agregar referencia a la Project enlace: actualice el proyecto InfColorPickerSample para que tenga una referencia al proyecto InfColorPickerBinding:

    Agregar referencia al enlace Project

  3. Crear el iPhone Interfaz de usuario: haga doble clic en el archivo MainStoryboard.storyboard del proyecto InfColorPickerSample para editarlo en iOS Designer. Agregue un botón a la vista y llámelo , como se muestra a continuación:

    Agregar un botón a la vista

  4. Agregue el archivo InfColorPickerView.xib: la biblioteca InfColorPicker incluye un archivo .xib. Xamarin.iOS no incluirá este archivo .xib en el proyecto de enlace, lo que provocará errores en tiempo de ejecución en nuestra aplicación de ejemplo. La solución alternativa es agregar el archivo .xib a nuestro proyecto de Xamarin.iOS. Seleccione el proyecto de Xamarin.iOS, haga clic con el botón derecho y seleccione Agregar archivos y agregue el archivo .xib como se muestra en la captura de pantalla siguiente:

    Agregar InfColorPickerView.xib

  5. Cuando se le pregunte, copie el archivo .xib en el proyecto.

A continuación, echemos un vistazo rápido a Los protocolos en y cómo se controlan en Objective-C el enlace y el código de C#.

Protocolos y Xamarin.iOS

En Objective-C , un protocolo define métodos (o mensajes) que se pueden usar en determinadas circunstancias. Conceptualmente, son muy similares a las interfaces de C#. Una diferencia importante entre un protocolo y una interfaz de C# es que los protocolos pueden tener métodos opcionales, métodos que una clase Objective-C no tiene que implementar. Objective-C usa la @optional clave se usa para indicar qué métodos son opcionales. Para obtener más información sobre los protocolos, vea Eventos, protocolos y delegados.

InfColorPickerController tiene uno de estos protocolos, que se muestra en el fragmento de código siguiente:

@protocol InfColorPickerControllerDelegate

@optional

- (void) colorPickerControllerDidFinish: (InfColorPickerController*) controller;
// This is only called when the color picker is presented modally.

- (void) colorPickerControllerDidChangeColor: (InfColorPickerController*) controller;

@end

InfColorPickerController usa este protocolo para informar a los clientes de que el usuario ha elegido un nuevo color y que InfColorPickerController ha finalizado. Objective Sharpie asignó este protocolo como se muestra en el siguiente fragmento de código:

[BaseType(typeof(NSObject))]
[Model]
public partial interface InfColorPickerControllerDelegate {

    [Export ("colorPickerControllerDidFinish:")]
    void ColorPickerControllerDidFinish (InfColorPickerController controller);

    [Export ("colorPickerControllerDidChangeColor:")]
    void ColorPickerControllerDidChangeColor (InfColorPickerController controller);
}

Cuando se compila la biblioteca de enlaces, Xamarin.iOS creará una clase base abstracta denominada , que implementa esta InfColorPickerControllerDelegate interfaz con métodos virtuales.

Hay dos maneras de implementar esta interfaz en una aplicación xamarin.iOS:

  • Delegado fuerte: el uso de un delegado fuerte implica la creación de una clase de C# que crea subclases e invalida los métodos adecuados. InfColorPickerController usará una instancia de esta clase para comunicarse con sus clientes.
  • Delegado débil: un delegado débil es una técnica ligeramente diferente que implica crear un método público en alguna clase (como ) y, a continuación, exponer ese método al protocolo a través de un atributo InfColorPickerDelegateExport .

Los delegados fuertes proporcionan IntelliSense, seguridad de tipos y una mejor encapsulación. Por estos motivos, debe usar delegados fuertes donde pueda, en lugar de un delegado débil.

En este tutorial se analizarán ambas técnicas: primero se implementa un delegado seguro y, a continuación, se explica cómo implementar un delegado débil.

Implementar un delegado fuerte

Finalice la aplicación Xamarin.iOS mediante un delegado fuerte para responder al colorPickerControllerDidFinish: mensaje:

Subclass InfColorPickerControllerDelegate: agregue una nueva clase al proyecto denominada . Edite la clase para que tenga el código siguiente:

using InfColorPickerBinding;
using UIKit;

namespace InfColorPickerSample
{
  public class ColorSelectedDelegate:InfColorPickerControllerDelegate
  {
    readonly UIViewController parent;

    public ColorSelectedDelegate (UIViewController parent)
    {
      this.parent = parent;
    }

    public override void ColorPickerControllerDidFinish (InfColorPickerController controller)
    {
      parent.View.BackgroundColor = controller.ResultColor;
      parent.DismissViewController (false, null);
    }
  }
}

Xamarin.iOS enlazará el Objective-C delegado mediante la creación de una clase base abstracta denominada InfColorPickerControllerDelegate . Subclase este tipo e invalida ColorPickerControllerDidFinish el método para tener acceso al valor de la propiedad de ResultColorInfColorPickerController .

Crear una instancia de ColorSelectedDelegate: nuestro controlador de eventos necesitará una instancia del tipo que creamos en el paso anterior. Edite la InfColorPickerSampleViewController clase y agregue la siguiente variable de instancia a la clase :

ColorSelectedDelegate selector;

Inicializar la variable ColorSelectedDelegate: para asegurarse de que es una instancia válida, actualice el método en para que coincida con el fragmento de código ViewDidLoadViewController siguiente:

public override void ViewDidLoad ()
{
  base.ViewDidLoad ();
  ChangeColorButton.TouchUpInside += HandleTouchUpInsideWithStrongDelegate;
  selector = new ColorSelectedDelegate (this);
}

Implemente el método HandleTouchUpWithStrongDelegate: a continuación, implemente el controlador de eventos para cuando el usuario toque ColorChangeButton. Edite ViewController y agregue el método siguiente:

using InfColorPicker;
...

private void HandleTouchUpInsideWithStrongDelegate (object sender, EventArgs e)
{
    InfColorPickerController picker = InfColorPickerController.ColorPickerViewController();
    picker.Delegate = selector;
    picker.PresentModallyOverViewController (this);
}

Primero se obtiene una instancia de a través de un método estático y se hace que esa instancia sea consciente de InfColorPickerController nuestro delegado seguro a través de la propiedad InfColorPickerController.Delegate . Objective Sharpie generó automáticamente esta propiedad. Por último, PresentModallyOverViewController llamamos a para mostrar la InfColorPickerSampleViewController.xib vista para que el usuario pueda seleccionar un color.

Ejecutar la aplicación: en este momento hemos terminado con todo el código. Si ejecuta la aplicación, debería poder cambiar el color de fondo de , como se InfColorColorPickerSampleView muestra en las capturas de pantalla siguientes:

Ejecutar la aplicación

Enhorabuena. En este momento, ha creado y enlazado correctamente una Objective-C biblioteca para su uso en una aplicación xamarin.iOS. A continuación, vamos a aprender a usar delegados débiles.

Implementar un delegado débil

En lugar de crear subclases de una clase enlazada al protocolo para un delegado determinado, Xamarin.iOS también permite implementar los métodos de protocolo en cualquier clase que derive de , decorando los métodos con y, a continuación, suministrando los Objective-CNSObjectExportAttribute selectores adecuados. Cuando se toma este enfoque, se asigna una instancia de la clase a la WeakDelegate propiedad en lugar de a la propiedad Delegate . Un delegado débil ofrece la flexibilidad de quitar la clase de delegado de una jerarquía de herencia diferente. Veamos cómo implementar y usar un delegado débil en nuestra aplicación xamarin.iOS.

Crear controlador de eventos para TouchUpChanged: vamos a crear un nuevo controlador de eventos para el evento del botón Cambiar color de fondo. Este controlador rellenará el mismo rol que el controlador que creamos en la sección anterior, pero usará un delegado débil en HandleTouchUpInsideWithStrongDelegate lugar de un delegado seguro. Edite la ViewController clase y agregue el método siguiente:

private void HandleTouchUpInsideWithWeakDelegate (object sender, EventArgs e)
{
    InfColorPickerController picker = InfColorPickerController.ColorPickerViewController();
    picker.WeakDelegate = this;
    picker.SourceColor = this.View.BackgroundColor;
    picker.PresentModallyOverViewController (this);
}

Actualizar ViewDidLoad: debemos cambiar para que use el controlador de eventos que acaba de crear. Edite ViewController y cambie para que se parezca al siguiente fragmento de ViewDidLoad código:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    ChangeColorButton.TouchUpInside += HandleTouchUpInsideWithWeakDelegate;
}

Controlar el colorPickerControllerDidFinish: Message: cuando finalice, iOS enviará el mensaje a colorPickerControllerDidFinish:WeakDelegate . Es necesario crear un método de C# que pueda controlar este mensaje. Para ello, creamos un método de C# y, a continuación, lo adornamos con ExportAttribute . Edite ViewController y agregue el método siguiente a la clase :

[Export("colorPickerControllerDidFinish:")]
public void ColorPickerControllerDidFinish (InfColorPickerController controller)
{
    View.BackgroundColor = controller.ResultColor;
    DismissViewController (false, null);
}

Ejecute la aplicación. Ahora debería comportarse exactamente como antes, pero usa un delegado débil en lugar del delegado fuerte. En este momento, ha completado correctamente este tutorial. Ahora debería comprender cómo crear y consumir un proyecto de enlace de Xamarin.iOS.

Resumen

En este artículo se describe el proceso de creación y uso de un proyecto de enlace de Xamarin.iOS. En primer lugar, se ha analizado cómo compilar una biblioteca Objective-C existente en una biblioteca estática. A continuación, se ha abordado cómo crear un proyecto de enlace de Xamarin.iOS y cómo usar Objective Sharpie para generar las definiciones de API para la Objective-C biblioteca. Hemos analizado cómo actualizar y ajustar las definiciones de API generadas para que se ajusten al consumo público. Una vez finalizado el proyecto de enlace de Xamarin.iOS, hemos pasado a consumir ese enlace en una aplicación de Xamarin.iOS, con especial atención al uso de delegados fuertes y delegados débiles.