You are on page 1of 562

Introducción

Antes de comenzar, consulte los requisitos del sistema y las instrucciones de instalación
para asegurarse de que todo está listo.

Compilación de la primera aplicación


Para empezar a programar inmediatamente, elija una guía de inicio rápido para ayudarle a
compilar su primera aplicación:

Inicio rápido de Android


Inicio rápido de iOS
Inicio rápido de Xamarin.Forms
Introducción a Mac

Introducción al desarrollo móvil


Para obtener más información sobre el funcionamiento de Xamarin y cómo enfocar los
proyectos de desarrollo de aplicaciones móviles, lea las guías siguientes:

Introducción al desarrollo móvil

En este documento se explica el funcionamiento de Xamarin de alto nivel y se incluyen


vínculos a las guías de introducción de iOS, Android y Xamarin.Forms.

Introducción al ciclo de vida del desarrollo de software móvil

En este artículo, se describe el ciclo de vida de desarrollo de software con respecto a


aplicaciones móviles y se describen algunas de las consideraciones necesarias para
compilar proyectos móviles. Los desarrolladores que quieran empezar a compilar
directamente pueden omitir esta guía y leerla más adelante para comprender mejor el
desarrollo móvil.

Presentación de Visual Studio para Mac

En este documento se proporciona información general de Visual Studio para Mac, el


entorno de desarrollo integrado (IDE).
Requisitos del sistema
Los productos de Xamarin dependen de los SDK de la plataforma de Apple y Google para
fijar como destino iOS o Android para que nuestros requisitos del sistema coincidan con los
suyos. Esta página describe la compatibilidad del sistema para la plataforma Xamarin, y el
entorno de desarrollo y versiones del SDK recomendados.

Entornos de desarrollo
Requisitos de macOS
Requisitos de Windows

Visite las instrucciones de instalación para obtener más información sobre cómo obtener el
software y los SDK necesarios.

Entornos de desarrollo
Esta tabla muestra qué plataformas se pueden crear con diferentes combinaciones de
sistema operativo y herramientas de desarrollo:

macOS Windows

Entorno de desarrollo Visual Studio para Mac Visual Studio

Xamarin.iOS Sí Sí (con un equipo Mac)

Xamarin.Android Sí Sí

Solo iOS y Android Android, Windows o UWP


Xamarin.Forms
(macOS en versión preliminar) (iOS con un equipo Mac)

Xamarin.Mac Sí Solo abrir el proyecto y compilar ^

ℹ️ NOTA: Para desarrollar para iOS en equipos Windows debe haber un


equipo Mac accesible en la red, para la depuración y compilación remota. Esto
también funciona si ejecuta Visual Studio dentro de una máquina virtual de
Windows en un equipo Mac.
Requisitos de macOS
El uso de un equipo Mac para el desarrollo de Xamarin requiere las siguientes versiones de
software o del SDK. Compruebe la versión de sistema operativo y siga las instrucciones
para el instalador de Xamarin.

Se
Notas
recomienda

Sistema macOS
La versión mínima necesaria es macOS Sierra (10.12).
operativo Sierra

SDK de iOS
Xamarin.iOS Este SDK de iOS se proporciona junto a Xcode 9.
11

Con el último SDK también puede usar versiones


Android 6.0
anteriores de Android como objetivo, o bien realizar la
Xamarin.Android (nivel de
compilación a partir de versiones anteriores del SDK si es
API 23)
necesario.

Las aplicaciones de Xamarin.Forms compiladas en macOS pueden


incluir proyectos de iOS, Android y macOS, siempre que cumplan los
Xamarin.Forms requisitos de SDK anteriores.
Los proyectos de Xamarin.Forms para Windows o UWP no se pueden
compilar en macOS.

SDK de OS
El SDK de OS X El Capitan se proporciona junto a Xcode
X El
Xamarin.Mac 7.2, mientras que el SDK de macOS se incluye en Xcode
Capitan
8.
(10.11)

ℹ️ NOTA: Xcode se puede instalar (y actualizar) en developer.apple.com o a


través del Mac App Store.

Pruebas y depuración en macOS


Se pueden implementar aplicaciones Xamarin para dispositivos móviles en dispositivos
físicos a través de USB para probar y depurar (las aplicaciones de Xamarin.Mac se pueden
probar directamente en el equipo de desarrollo, las aplicaciones de Apple Watch se
implementan en primer lugar en el iPhone emparejado).

Notas sobre pruebas

La forma más fácil de empezar a trabajar es usar los emuladores


de iPhone, iPad, Apple Watch y Apple TV incluidos en Xcode.
Xamarin.iOS
Para usar un dispositivo con el objetivo de realizar pruebas, siga
estas instrucciones.

Siga estas instrucciones para configurar el dispositivo o usar un


emulador:

El programa de instalación de Xamarin incluye Google Emulator


Xamarin.Android Manager, que le permite configurar emuladores de Google
Android para realizar pruebas.
Genymotion también ofrece la descarga de un emulador gratuito
para uso personal.

Las aplicaciones de Xamarin.Forms para iOS y Android pueden


Xamarin.Forms implementarse para las plataformas más importantes, tal y como se
describe a continuación.

Las aplicaciones de Xamarin.Mac pueden probarse directamente en el


Xamarin.Mac
equipo de desarrollo.

Requisitos de Windows
El uso de un equipo Windows para el desarrollo de Xamarin requiere las siguientes
versiones de software o del SDK. Compruebe la versión del sistema operativo (y confirme
que no está usando una versión Express de Visual Studio; si es así, considere la posibilidad
de actualizar a una edición Community). Los instaladores de Visual Studio 2015 y 2017
incluyen una opción para instalar automáticamente Xamarin.

Se
Notas
recomienda

La versión mínima del sistema operativo es Windows 7. La


Sistema Windows compatibilidad de Xamarin.Forms con Windows requiere
operativo 10 Windows 8.1, mientras que la compatibilidad de
Xamarin.Forms con UWP requiere Windows 10.

Para compilar proyectos de iOS en Windows se requiere lo


siguiente:
SDK de iOS
Visual Studio 2015 o una versión más reciente,
10
además de
Xamarin.iOS instalado en
un equipo Mac que pueda acceder a la red desde un
un equipo
equipo con Windows y que cumpla los requisitos
Mac
mínimos para ejecutar Xamarin en macOS (consulte
la información anterior).

Con el último SDK también puede usar versiones


Android 6.0
anteriores de Android como objetivo, o bien realizar la
Xamarin.Android (nivel de
compilación a partir de versiones anteriores del SDK si es
API 23)
necesario.

Las aplicaciones de Xamarin.Forms para iOS y Android pueden


implementarse para las plataformas más importantes, tal y como se
describe a continuación.
Xamarin.Forms Usar Visual Studio también implica que puede probar aplicaciones para
Windows y la Plataforma universal de Windows (en Windows 10)
mediante los emuladores de Microsoft. Las aplicaciones para Windows
se pueden probar directamente en el equipo de desarrollo.

Los proyectos de Xamarin.Mac (aplicaciones de escritorio para macOS)


pueden abrirse en Visual Studio y compilarse para buscar errores. Sin
embargo, actualmente, las aplicaciones para Mac no se pueden
Xamarin.Mac compilar en Visual Studio para su distribución. Consulte las notas de la
versión en Compatibilidad con Xamarin.Mac para obtener más
información sobre las limitaciones de los proyectos de Mac en Visual
Studio.

ℹ️ NOTAS:

Xamarin para Visual Studio admite cualquier edición de Visual Studio


2015 o 2017 (Community, Professional y Enterprise).

Para desarrollar aplicaciones de Xamarin.Forms para la Plataforma


universal de Windows (UWP), es necesario Windows 10 con Visual Studio
2015 o 2017.

Pruebas y depuración en Windows

Las aplicaciones móviles Xamarin se pueden implementar en dispositivos físicos a través de


USB para probar y depurar (los dispositivos iOS deben estar conectados al equipo Mac, no
al equipo que ejecuta Visual Studio).

Notas sobre pruebas

La forma más fácil de empezar a trabajar es usar los emuladores


de iPhone, iPad, Apple Watch y Apple TV incluidos en Xcode. Se
puede acceder a los emuladores en el equipo Mac conectado
Xamarin.iOS durante la depuración en Visual Studio.
Para usar un dispositivo con el objetivo de realizar pruebas, siga
estas instrucciones. La mayoría de los pasos requieren que el
equipo Mac esté conectado.

Siga estas instrucciones para configurar el dispositivo o usar un


emulador:

El programa de instalación de Xamarin incluye Google Emulator


Xamarin.Android Manager, que le permite configurar emuladores de Google
Android para realizar pruebas.
Hay otros emuladores disponibles para Genymotion y Microsoft
(con Visual Studio 2015).

Las aplicaciones de Xamarin.Forms pueden implementarse para los


dispositivos y emuladores más importantes, tal y como se describe a
continuación. La aplicación de iOS solo se puede probar mediante un
Xamarin.Forms
equipo Mac conectado. Las aplicaciones para escritorio o tableta con
Windows para Windows 8.1 o UWP se pueden probar directamente en
el equipo de desarrollo.

ℹ️ NOTAS:

Descarga del emulador de Windows Phone 8.1.


El emulador de Windows Phone 10 se incluye con el SDK de Visual
Studio 2015 UWP.

Instrucciones de instalación
Puede descargar la versión más reciente de Xamarin para Mac OS en
xamarin.com/download. Para Windows, siga las instrucciones de instalación de Visual
Studio 2017.

Una lista completa de las versiones de producto actuales está disponible en la página
Versiones actuales. Esta página también describe las versiones de productos individuales (e
incluye vínculos a las notas de la versión) para nuestros canales alfa y beta.

Aquí están disponibles instrucciones de instalación específicas para cada plataforma:

Xamarin.iOS
Xamarin.Android
Xamarin.Mac

También hay información adicional sobre las plataformas admitidas y los requisitos de
Xamarin.Forms.
Instalación

Instalación de Xamarin en Visual Studio para Windows

En este artículo se explica cómo instalar Xamarin para Visual Studio en equipos Windows.

Instalación de Visual Studio para Mac

En este artículo se explica cómo instalar Visual Studio para Mac.

Desinstalación de Xamarin

En este artículo se explica cómo desinstalar Xamarin Studio u otros productos de Xamarin
de un equipo Mac o Windows.

Instrucciones de configuración del firewall de Xamarin

Lista de hosts necesarios para la lista de permitidos del firewall para que la plataforma de
Xamarin funcione en la empresa.
Instalación de Xamarin en Visual Studio para
Windows
Gracias a que ahora Xamarin se incluye con todas las ediciones de Visual Studio sin ningún
costo adicional y no requiere ninguna licencia independiente, puede usar el instalador de Visual
Studio para descargar e instalar las herramientas de Xamarin.

Requisitos
Instalación
Agregar Xamarin a Visual Studio 2017
Agregar Xamarin a Visual Studio 2015
Comprobación de la instalación
Pasos siguientes

Requisitos
Para instalar las herramientas de Visual Studio para Xamarin, se necesita lo siguiente:

1. Windows 7 o una versión posterior.

2. Visual Studio 2015 o 2017 (Community, Professional o Enterprise).

3. Xamarin para Visual Studio.

Tenga en cuenta que Xamarin no se puede usar con las ediciones Express de Visual Studio
debido a la falta de compatibilidad con los complementos.

Para obtener más información sobre los requisitos previos para instalar y usar Xamarin, consulte
Requisitos del sistema.

Instalación
Xamarin se puede instalar como parte de una nueva instalación de Visual Studio. Para ello, siga
estos pasos:

1. Descargue Visual Studio Community, Visual Studio Professional o Visual Studio Enterprise
desde la página de Visual Studio (en la parte inferior se encuentran los vínculos de
descarga).

2. Haga doble clic en el paquete descargado para iniciar la instalación.

3. Seleccione la carga de trabajo Desarrollo para dispositivos móviles con .NET en la


pantalla de instalación:

4. Con la opción Desarrollo para dispositivos móviles con .NET seleccionada, eche un
vistazo en el panel Resumen de la derecha. Aquí puede anular la selección de opciones de
desarrollo para dispositivos móviles que no quiera instalar. De forma predeterminada se
instalan todas las opciones que aparecen en la siguiente captura de pantalla (Xamarin
Workbooks, Xamarin Profiler, Xamarin Remoted Simulator, Android NDK, Android
SDK, Java SE Development Kit, Emulador de Android de Google, Compatibilidad con
el lenguaje F# e Intel Hardware Accelerated Execution Manager (HAXM)):

5. Cuando esté listo para comenzar la instalación de Visual Studio, haga clic en el botón
Instalar situado en la esquina inferior derecha:

En función de la edición de Visual Studio que vaya a instalar, el proceso de instalación


puede tardar bastante tiempo. Puede usar las barras de progreso para supervisar la
instalación:

6. Cuando la instalación de Visual Studio haya finalizado, haga clic en el botón Iniciar para
iniciar Visual Studio:
Agregar Xamarin a Visual Studio 2017

Si Visual Studio 2017 ya está instalado, puede agregar Xamarin volviendo a ejecutar el instalador
de Visual Studio para modificar las cargas de trabajo (consulte Modificar Visual Studio para
obtener más información). Después, siga los pasos indicados anteriormente para instalar
Xamarin.

Para obtener más información sobre la descarga e instalación de Visual Studio 2017, consulte
Instalación de Visual Studio 2017.

Agregar Xamarin a Visual Studio 2015

Para agregar Xamarin.Android a una instalación existente de Visual Studio 2015, siga estos
pasos:

1. Haga clic con el botón derecho en el botón Inicio de Windows y seleccione Programas y
características.

2. Haga clic con el botón derecho en Microsoft Visual Studio y haga clic en Cambiar.

3. Cuando aparezca el cuadro de diálogo del instalador de Visual Studio, haga clic en el botón
Modificar.

4. En la pestaña Características, desplácese hacia abajo hasta Desarrollo para móviles


multiplataforma. Haga clic en la casilla de verificación situada junto a C#/.NET (Xamarin):

5. Haga clic en el botón ACTUALIZAR para agregar Xamarin a Visual Studio.

Comprobación de la instalación

En Visual Studio 2017 puede comprobar que Xamarin está instalado haciendo clic en el menú
Ayuda. Si está instalado, debería ver el elemento de menú Xamarin, como se muestra en esta
captura de pantalla:
Si usa una versión anterior de Visual Studio, haga clic en Ayuda > Acerca de Microsoft Visual
Studio y desplácese por la lista de productos instalados para ver si Xamarin está instalado:

Para obtener más información sobre cómo encontrar la información de la versión, consulte Where
can I find my version information and logs? (¿Dónde puedo encontrar los registros y la
información de la versión?).

Pasos siguientes
La instalación de Visual Studio Tools para Xamarin permite empezar a escribir código para sus
aplicaciones, pero requiere un paso más para configurarlo y poder compilar e implementar las
aplicaciones en el simulador, el emulador y el dispositivo. Consulte las siguientes guías para
completar la instalación y empezar a compilar aplicaciones multiplataforma.

iOS

Para obtener información detallada, consulte la guía de instalación de Xamarin.iOS en Windows.

1. Instalación de las herramientas de Xamarin.iOS en Mac


2. Configuración del Mac
3. Configuración del desarrollador de iOS (para ejecutar la aplicación en el dispositivo).
4. Conexión de Visual Studio con el host de compilación del Mac
5. Simulador remoto de iOS
6. Introducción a Xamarin.iOS para Visual Studio

Android

Para obtener información detallada, consulte la guía de instalación de Xamarin.Android en


Windows.

1. Configuración de Xamarin.Android
2. Uso del administrador de Android SDK de Xamarin
3. Emulador de Android SDK
4. Configurar el dispositivo para el desarrollo
Instrucciones de configuración del firewall
para Xamarin

Puntos de conexión que deben incluirse en la lista de


permitidos

Información general
Para que los productos de Xamarin se instalen y funcionen correctamente, determinados
puntos de conexión deben ser accesibles para descargar las herramientas y las
actualizaciones necesarias para el software. Si usted o la empresa tienen una configuración
de firewall estricta, puede experimentar problemas con la instalación, las licencias, los
componentes, etc. En este documento se indican algunos de los puntos de conexión
conocidos que deben aparecer en la lista de permitidos del firewall para que Xamarin
funcione. No se incluyen los puntos de conexión necesarios para las herramientas de otros
fabricantes incluidas en la descarga. Si después de repasar esta lista sigue teniendo
problemas, consulte las guías de solución de problemas de instalación de Apple o Android.

Puntos de conexión que deben incluirse


en la lista de permitidos

Xamarin Installer

Para que el software se instale correctamente con la versión más reciente del instalador de
Xamarin, tiene que agregar las siguientes direcciones conocidas:

xamarin.com (manifiestos del instalador)


dl.xamarin.com (ubicación de descarga del paquete)
dl.google.com (para descargar el SDK de Android)
download.oracle.com (JDK)
visualstudio.com (configurar ubicación de descarga de paquetes)
go.microsoft.com (configurar URL de resolución)
aka.ms (configurar URL de resolución)

Si está usando un equipo Mac y tiene problemas de instalación de Xamarin.Android,


asegúrese de que macOS pueda descargar Java.

Components Store y NuGet (incluye Xamarin.Forms)

Para acceder a Xamarin Component Store o a NuGet (Xamarin.Forms está empaquetado


como NuGet,) tiene que agregar las siguientes direcciones:

components.xamarin.com (para usar Xamarin Components Store)


xampubdl.blob.core.windows.net (hospeda descargas de Components Store)
www.nuget.org (para acceder a NuGet)
az320820.vo.msecnd.net (descargas de NuGet)
dl-ssl.google.com (componentes de Google)

Actualizaciones de software

Para garantizar que las actualizaciones de software se descarguen correctamente, tendrá


que agregar las siguientes direcciones:

software.xamarin.com (servicio de actualizador)


download.visualstudio.microsoft.com
dl.xamarin.com

Xamarin Insights

Para garantizar que la actividad llegue al servidor de Xamarin Insights, tendrá que agregar
las siguientes direcciones:
https://xaapi.xamarin.com

Xamarin Mac Agent


Para conectar Visual Studio a un host de compilación de Mac mediante Xamarin Mac Agent,
el puerto SSH tiene que estar abierto. De forma predeterminada, es el puerto 22.

Resumen
En esta guía se habla de los puntos de conexión que deben aparecer en la lista de
permitidos para que los productos de Xamarin se instalen y se actualicen correctamente en
un equipo.
Desinstalación de Xamarin

Desinstalación de los productos de Xamarin de un equipo

⚠️ En este artículo se explica cómo desinstalar Xamarin Studio u otros productos de


Xamarin de un equipo Mac o Windows. Para obtener información sobre cómo desinstalar
Visual Studio para Mac, consulte el la guía para Desinstalar en docs.microsoft.com

Información general
Hay una serie de productos de Xamarin que permiten el desarrollo de aplicaciones entre plataformas,
incluidas las aplicaciones independientes como Xamarin Studio y las extensiones a otras aplicaciones
como la compatibilidad con Xamarin en Visual Studio.

En esta guía se explica cómo quitar la funcionalidad de Xamarin en Mac OS o desde Visual Studio en
Windows:

1. Desinstalación de Xamarin Studio


1. Desinstalación de Mono
2. Desinstalación de Xamarin.Android
3. Desinstalación de Xamarin.iOS
4. Desinstalación de Xamarin.Mac
5. Desinstalación de Inspector y Workbooks
2. Desinstalación de Xamarin de Windows
1. Desinstalación de Xamarin desde Visual Studio 2015 y anterior
2. Desinstalación de Xamarin desde Visual Studio 2017
3. Desinstalación de Visual Studio para Mac

Si es necesario volver a instalar Xamarin con el Instalador universal, siempre se recomienda que se
reinicie primero el equipo.

Desinstalación de Xamarin en un equipo Mac


Esta guía puede usarse para desinstalar cada producto de manera individual dirigiéndose a la sección
correspondiente. El conjunto de aplicaciones completo de Xamarin puede desinstalarse siguiendo esta
guía de principio a fin.

Para obtener ayuda sobre el uso del script de desinstalación, vaya a Usar el script de desinstalación
en la parte inferior de esta guía.

Desinstalación de Xamarin Studio

El primer paso a la hora de desinstalar Xamarin Studio de un equipo Mac es buscar Xamarin
Studio.app en el directorio /Applications y arrastrarlo a la Papelera. De manera alternativa, haga clic
con el botón derecho y seleccione Trasladar a la Papelera como se muestra a continuación:

Al eliminar este lote de aplicaciones se quitará Xamarin Studio, en cambio, todavía existen otros
archivos relacionados con Xamarin en un sistema de archivos.

Para quitar todos los seguimientos de Xamarin Studio, deben ejecutarse los siguientes comandos en
Terminal:

sudo rm -rf "/Applications/Xamarin Studio.app"


rm -rf ~/Library/Caches/XamarinStudio-*
rm -rf ~/Library/Preferences/XamarinStudio-*
rm -rf ~/Library/Logs/XamarinStudio-*
rm -rf ~/Library/XamarinStudio-*

Desinstalación del SDK de Mono (MDK)

Mono es una implementación de código abierto de Microsoft .NET Framework que usan todos los
productos de Xamarin: Xamarin.iOS, Xamarin.Android y Xamarin.Mac para permitir el desarrollo de
estas plataformas en C#.

⚠️ Nota: Existen otras aplicaciones fuera de Xamarin que también usan Mono, como
Unity. Asegúrese de que no hay otras dependencias en Mono antes de desinstalarlo.

Para quitar Mono Framework de un equipo, ejecute los siguientes comandos en Terminal:

sudo rm -rf /Library/Frameworks/Mono.framework


sudo pkgutil --forget com.xamarin.mono-MDK.pkg
Desinstalación de Xamarin.Android

Existen varios elementos necesarios para la instalación y el uso de Xamarin.Android, como Android
SDK y el SDK de Java. Puede encontrar más información disponible sobre estos componentes
necesarios en la guía Instalación manual.

Use los siguientes comandos para quitar Xamarin.Android:

sudo rm -rf /Developer/MonoDroid


rm -rf ~/Library/MonoAndroid
sudo pkgutil --forget com.xamarin.android.pkg
sudo rm -rf /Library/Frameworks/Xamarin.Android.framework

Desinstalación de Android SDK y del SDK de Java

Android SDK es necesario para la implementación de aplicaciones de Android. Para quitar


completamente todas las partes de Android SDK, busque el archivo en ~/Library/Developer/Xamarin/
y muévalo a la Papelera, como se muestra a continuación:

El SDK de Java (JDK) no necesita desinstalarse, ya que se ha empaquetado previamente como parte
de Mac OS X.

Desinstalación de Xamarin.iOS

Xamarin.iOS permite el desarrollo de aplicaciones de iOS con C# o F# con Xamarin Studio en un


equipo Mac. El host de compilación de Xamarin también se ha instalado automáticamente con
versiones anteriores de Xamarin.iOS para permitir el desarrollo iOS en Visual Studio. Para desinstalar
ambos de un equipo, siga los pasos siguientes:

Use los siguientes comandos en Terminal para quitar todos los archivos de Xamarin.iOS desde un
sistema de archivos:

rm -rf ~/Library/MonoTouch
sudo rm -rf /Library/Frameworks/Xamarin.iOS.framework
sudo rm -rf /Developer/MonoTouch
sudo pkgutil --forget com.xamarin.monotouch.pkg
sudo pkgutil --forget com.xamarin.xamarin-ios-build-host.pkg
Desinstalación del host de compilación de Mac

Nota: Esto puede que ya se haya quitado si ya ha actualizado a Xamarin 4. Ejecute el siguiente
comando en Terminal para quitar la aplicación del host de compilación:

sudo rm -rf "/Applications/Xamarin.iOS Build Host.app"

El trabajo launchd o el proceso del host de compilación puede que siga ejecutándose o
escuchándose en determinados puertos. Puede comprobar su estado ejecutando launchctl list
| grep com.xamarin.mtvs.buildserver en Terminal.

sudo launchctl unload


/Library/LaunchAgents/com.xamarin.mtvs.buildserver.plist
sudo rm -f /Library/LaunchAgents/com.xamarin.mtvs.buildserver.plist

Desinstalación de Xamarin.Mac

Una vez que Xamarin Studio se haya desinstalado correctamente, Xamarin.Mac puede quitarse de su
equipo con los siguientes dos comandos para erradicar el producto y la licencia de su equipo Mac
respectivamente:

sudo rm -rf /Library/Frameworks/Xamarin.Mac.framework


rm -rf ~/Library/Xamarin.Mac

Desinstalación de Inspector y Workbooks

En el caso de la versión 1.2.2 y posteriores, los siguientes comandos Bash quitarán Xamarin Inspector
y Workbooks de Xamarin:

sudo
/Library/Frameworks/Xamarin.Interactive.framework/Versions/Current/uninstall

Para versiones anteriores, consulte la guía para desinstalar Workbooks.

Desinstalación del instalador de Xamarin

Use los siguientes comandos para quitar todos los seguimientos del instalador universal de Xamarin:

rm -rf ~/Library/Caches/XamarinInstaller/
rm -rf ~/Library/Logs/XamarinInstaller/
rm -rf ~/Library/Preferences/Xamarin/

Usar el script de desinstalación

El script de desinstalación quitará Xamarin de un equipo. Para usar el script de desinstalación:

1. Descargue el script de desinstalación y anote la ubicación de descarga. De manera


predeterminada, esta es el directorio /Downloads.

2. Abra Terminal y cambie el directorio de trabajo al lugar donde se haya descargado el script:

$ cd /location/of/file

3. Haga que el script sea ejecutable y, después, ejecútelo con sudo:

$ chmod +x ./xamarin_uninstall.sh
$ sudo ./xamarin_uninstall.sh

4. Por último, elimine el script de desinstalación.

En este momento, Xamarin debe desinstalarse de su equipo.

Desinstalación de Xamarin en un equipo


Windows

Visual Studio 2015 y anterior

Xamarin puede desinstalarse de un equipo Windows mediante el Panel de control. Vaya a


Programas y características o Programas > Desinstalar un programa como se muestra a
continuación:

Para desinstalar Xamarin Studio, busque Xamarin Studio 5.x.x en la lista de programas y haga clic
en el botón Desinstalar. Para quitar la extensión de Xamarin para Visual Studio, y los SDK, busque
Xamarin en la lista de Programas y haga clic en Desinstalar. Estos se muestran en la siguiente
captura de pantalla:
Estos programas también pueden quitarse completamente para todos los componentes de Xamarin:

SDK de Android

GTK#

Instalador de Xamarin Universal

SDK de Java (tenga cuidado al quitarlo, ya que pueden encontrarse otras dependencias en él)

Para desinstalar completamente Visual Studio, siga las instrucciones de Microsoft.

Visual Studio 2017


Xamarin se puede desinstalar desde Visual Studio 2017 mediante la aplicación del instalador:

1. Use el menú Inicio para abrir el instalador de Visual Studio.

2. Pulse el botón Modificar para la instancia que quiera cambiar.

3. En la pestaña Cargas de trabajo, anule la selección de la opción Desarrollo móvil con .NET
(en la sección Dispositivos móviles y juegos).

4. Haga clic en el botón Modificar en la parte inferior derecha de la ventana.

5. El instalador quitará los componentes cuya selección se haya anulado (Visual Studio 2017 debe
cerrarse antes de que el instalador pueda realizar cambios).
Se quiere desinstalar componentes individuales de Xamarin (por ejemplo, el generador de perfiles o
los libros), puede cambiar a la pestaña Componentes individuales en el paso 3 y desactivar
componentes específicos:

Para desinstalar completamente Visual Studio 2017, elija Desinstalar en el menú de tres barras que
hay junto al botón Iniciar.

⚠️ ADVERTENCIA: Si tiene dos (o más) instancias de Visual Studio instaladas en


paralelo (SxS), como una versión de lanzamiento y una versión preliminar, es posible que
al desinstalar una instancia se quiten algunas funciones de Xamarin de las otras
instancias de Visual Studio, incluidas:

Generador de perfiles de Xamarin


Libros/Inspector de Xamarin
Simulador iOS remoto de Xamarin
SDK de Apple Bonjour

Bajo ciertas condiciones, la desinstalación de una de las instancias SxS puede ocasionar
la eliminación incorrecta de estas características. Esto puede degradar el rendimiento de
la plataforma Xamarin en las instancias de Visual Studio que permanecen en el sistema
después de desinstalar la instancia SxS.

Esto se puede resolver mediante la ejecución de la opción Reparación en el instalador de


Visual Studio, que volverá a instalar los componentes que faltan.

Desinstalación de Visual Studio para Mac


Para desinstalar Visual Studio para Mac, pero seguir usando Xamarin Studio, busque Visual
Studio.app en el directorio /Applications y arrástrelo a la Papelera. De manera alternativa, haga clic
con el botón derecho y seleccione Trasladar a la Papelera como se muestra a continuación:
Para desinstalar Xamarin completamente de su equipo, elimine primero Visual Studio para Mac y,
después, siga los pasos que se muestran en la sección Desinstalación de Xamarin Studio.

Resumen
En este artículo hemos analizado la desinstalación completa de Xamarin de un equipo Mac mediante
el uso de comandos de la Terminal, así como la desinstalación de Xamarin de un equipo Windows con
la opción Programas y características (para Visual Studio 2015 y anterior), y el uso del Instalador
de Visual Studio para Visual Studio 2017.
Introducción al desarrollo móvil
La creación de aplicaciones móviles puede ser tan fácil como abrir el IDE, juntar algunos
elementos, realizar unas pruebas rápidas y enviar el resultado al App Store, todo ello en una
misma tarde. O puede ser un proceso muy complicado que conlleva el diseño riguroso por
adelantado, pruebas de facilidad de uso, pruebas de control de calidad en miles de
dispositivos, un ciclo de vida completo de versión beta y la implementación de varias
maneras diferentes.

Esta guía contiene una introducción exhaustiva a la compilación de aplicaciones móviles de


Xamarin, que incluye lo siguiente:

1. Introducción a Xamarin: lista de las características de la plataforma Xamarin.


2. ¿Cómo funciona Xamarin?: breve descripción de cómo funciona Xamarin para usar
C# en iOS y Android.
3. Primeros pasos: conozca los detalles y compile una aplicación de Xamarin para iOS,
Android o todas las plataformas que usan Xamarin.Forms.

El objetivo de este documento es presentar la plataforma Xamarin. Para obtener más


información sobre el proceso de compilación de aplicaciones móviles desde el diseño hasta
la realización de pruebas, consulte el documento Introduction to the Mobile Software
Development Lifecycle (Introducción al ciclo de vida del desarrollo de software móvil).

Consulte nuestros requisitos del sistema para confirmar que puede instalar Xamarin.

Introducción a Xamarin
Al plantearse cómo compilar aplicaciones para iOS y Android, muchas personas piensan
que los lenguajes nativos, Objective-C, Swift y Java son la única opción. Pero en los últimos
años ha surgido un nuevo ecosistema de plataformas para compilar aplicaciones móviles.

Xamarin es único en este entorno, ya que ofrece un solo lenguaje (C#), una biblioteca de
clases y un tiempo de ejecución que funciona en las plataformas móviles iOS, Android y
Windows Phone (el lenguaje nativo de Windows Phone ya es C#), al mismo tiempo que
sigue compilando aplicaciones nativas (no interpretadas) con un rendimiento lo bastante
bueno incluso para juegos exigentes.

Cada una de estas plataformas tiene un conjunto de características diferente y varía en su


capacidad para crear aplicaciones nativas, es decir, aplicaciones que se compilan en código
nativo y que interoperan con fluidez con el subsistema de Java subyacente. Por ejemplo,
algunas plataformas solo permiten compilar aplicaciones en HTML y JavaScript, mientras
que otras son de muy bajo nivel y solo permiten código C o C++. Algunas plataformas ni
siquiera usan el kit de herramientas de control nativo.

Xamarin es único porque combina la potencia de las plataformas nativas y agrega una serie
de características propias muy eficaces, incluidas las siguientes:

1. Enlaces completos para los SDK subyacentes: Xamarin contiene enlaces para casi
todos los SDK de plataforma subyacentes en iOS y Android. Además, estos enlaces
están fuertemente tipados, lo que significa que la navegación y el uso son fáciles y
que proporcionan una sólida comprobación de tipos en tiempo de compilación y
durante el desarrollo. Como resultado, se producen menos errores en tiempo de
ejecución y aplicaciones de mayor calidad.
2. Interoperabilidad con Objective-C, Java, C y C++: Xamarin ofrece funciones para
invocar directamente las bibliotecas de Objective-C, Java, C y C++, lo que le permite
usar diversos tipos de código de terceros ya creado. Esto le permite aprovechar las
ventajas de las bibliotecas existentes de iOS y Android escritas en Objective-C, Java,
C o C++. Además, Xamarin ofrece proyectos de enlace que le permiten enlazar
fácilmente bibliotecas nativas de Objective-C y Java mediante una sintaxis
declarativa.
3. Construcciones de lenguaje moderno: las aplicaciones de Xamarin se escriben en
C#, un lenguaje moderno que incluye mejoras considerables en Objective-C y Java,
como características de lenguaje dinámico, construcciones funcionales como
lambdas, LINQ, características de programación en paralelo, genéricos sofisticados,
etc.
4. Increíble biblioteca de clases base (BCL): las aplicaciones de Xamarin usan la BCL
de .NET, una enorme colección de clases con características completas y
optimizadas, como una eficaz compatibilidad con XML, bases de datos, serialización,
E/S, cadenas y redes, por nombrar algunos. Además, el código C# existente puede
compilarse para su uso en una aplicación, lo que proporciona acceso a miles de
bibliotecas que le permitirán hacer cosas que no contempla la BCL.
5. Moderno entorno de desarrollo integrado (IDE): Xamarin usa Visual Studio para
Mac en Mac OS X y Visual Studio en Windows. Estos IDE modernos incluyen
características como la finalización automática de código, un sofisticado sistema de
administración de proyectos y soluciones, una biblioteca exhaustiva de plantillas de
proyecto, control de código fuente integrado, etc.
6. Compatibilidad multiplataforma móvil: Xamarin ofrece una compatibilidad
multiplataforma sofisticada con las tres principales plataformas móviles: iOS, Android
y Windows Phone. Es posible escribir aplicaciones de modo que compartan hasta el
90 % del código, y la biblioteca de Xamarin.Mobile ofrece una API unificada para tener
acceso a recursos comunes de las tres plataformas. Esto puede reducir
considerablemente los costos de desarrollo y el tiempo de salida al mercado en el
caso de los desarrolladores móviles que se centran en las tres plataformas móviles
más populares.

Gracias al conjunto de características eficaces y completas de Xamarin, se llena un vacío


para los desarrolladores de aplicaciones que quieren usar un lenguaje y una plataforma
modernos para desarrollar aplicaciones móviles multiplataforma.

ℹ️ Esta serie de introducción se centra en los primeros pasos para compilar


aplicaciones iOS y Android. Microsoft ofrece tutoriales para el desarrollo de
Windows Phone aquí. Para más información sobre el desarrollo multiplataforma
con Xamarin (incluidas las aplicaciones UWP para Windows), lea la guía
Building Cross-Platform Applications (Creación de aplicaciones multiplataforma).

¿Cómo funciona Xamarin?


Xamarin ofrece dos productos comerciales: Xamarin.iOS y Xamarin.Android. Ambos se
basan en Mono, una versión de código abierto de .NET Framework que tiene en cuenta las
normas ECMA de .NET publicadas. Mono existe desde hace casi tanto tiempo como el
propio .NET Framework y puede ejecutarse en prácticamente todas las plataformas
imaginables, incluido Linux, Unix, FreeBSD y Mac OS X.

En iOS, el compilador Ahead of time (AOT) de Xamarin compila aplicaciones de


Xamarin.iOS directamente en código de ensamblado nativo de ARM. En Android, el
compilador de Xamarin compila en lenguaje intermedio (IL), que es Just-In-Time (JIT)
compilado en ensamblado nativo cuando se inicia la aplicación.

En ambos casos, las aplicaciones de Xamarin usan un tiempo de ejecución que lo controla
todo automáticamente, como la asignación de memoria, la recolección de elementos no
utilizados, la interoperabilidad de plataforma subyacente, etc.

MonoTouch.dll y Mono.Android.dll

Las aplicaciones de Xamarin se compilan en un subconjunto de la BCL de .NET conocido


como el perfil móvil de Xamarin. Este perfil se ha creado específicamente para aplicaciones
móviles y se ha empaquetado en MonoTouch.dll y Mono.Android.dll (para iOS y Android
respectivamente). Se parece mucho a la manera en que las aplicaciones de Silverlight (y
Moonlight) se compilan en el perfil de .NET de Silverlight/Moonlight. De hecho, el perfil móvil
de Xamarin es equivalente al perfil de Silverlight 4.0 con un conjunto de clases de BCL
agregadas de nuevo.

Para obtener una lista completa de las clases y los ensamblados disponibles, consulte
Xamarin.iOS Assembly List (Lista de ensamblados de Xamarin.iOS) y Xamarin.Android
Assembly List (Lista de ensamblados de Xamarin.Android).

Además de la BCL, estos archivos .dll incluyen contenedores para casi todo el SDK de iOS
y Android, lo que permite invocar las API del SDK subyacente directamente desde C#.

Resultado de la aplicación

Cuando se compilan aplicaciones de Xamarin, el resultado es un paquete de aplicación, ya


sea un archivo .app en iOS o un archivo .apk en Android. Estos archivos no se distinguen
de los paquetes de aplicación compilados con los IDE predeterminados de la plataforma y
se implementan de la misma manera.

Introducción
Ahora que ha aprendido los aspectos básicos del funcionamiento de Xamarin, es hora de
profundizar en los detalles.

El paso siguiente consiste en empezar a compilar la aplicación mediante una de estas


guías:

Hello, iOS

Hello, Android

Introduction to Xamarin.Forms (Introducción a Xamarin.Forms)

Resumen
Este documento es una simple presentación de la plataforma Xamarin. Lo divertido empieza
cuando ponga en funcionamiento su primera aplicación. Para comenzar, consulte las guías
Hello, iOS, Hello, Android e Introduction to Xamarin.Forms (Introducción a Xamarin.Forms).
Introducción al ciclo de vida de desarrollo
de software móvil

Consideraciones al desarrollar aplicaciones móviles

Información general
La creación de aplicaciones móviles puede ser tan fácil como abrir el IDE, juntar algunos
elementos, realizar unas pruebas rápidas y enviar el resultado al App Store, todo ello en una
misma tarde. O puede ser un proceso muy complicado que conlleva el diseño riguroso por
adelantado, pruebas de facilidad de uso, pruebas de control de calidad en miles de
dispositivos, un ciclo de vida completo de versión beta y la implementación de varias
maneras diferentes.

En este documento, vamos a realizar un examen de introducción exhaustivo de la creación


de aplicaciones móviles, incluidos:

1. Proceso: el proceso de desarrollo de software se denomina ciclo de vida de


desarrollo de software (SDLC). Examinaremos todas las fases del SDLC con respecto
al desarrollo de aplicaciones móviles, incluidas: inspiración, diseño, desarrollo,
estabilización, implementación y mantenimiento.
2. Consideraciones: hay una serie de consideraciones que se deben tener en cuenta al
crear aplicaciones móviles, especialmente si se comparan con las aplicaciones de
escritorio o web tradicionales. Examinaremos estas consideraciones y cómo afectan
al desarrollo móvil.

Este documento está pensado para responder a preguntas fundamentales sobre el


desarrollo de aplicaciones móviles, para desarrolladores de aplicaciones nuevos y
experimentados. Adopta un enfoque bastante completo para introducir la mayor parte de los
conceptos que se ejecutarán durante todo el ciclo de vida de desarrollo de software (SDLC).
En cambio, puede que este documento no sea para todos los usuarios, si quiere empezar a
crear aplicaciones, le recomendamos que pase a los tutoriales Introducción al desarrollo
móvil, Hello, Android o Hello, iPhone y vuelva a este documento más adelante.

SDLC de desarrollo móvil


El ciclo de vida de desarrollo móvil es, en gran medida, parecido al SDLC para aplicaciones
web o de escritorio. Al igual que con estos, normalmente hay 5 partes importantes del
proceso:

1. Inicio: todas las aplicaciones se inician con una idea. Normalmente, la idea se
perfecciona en una base sólida para una aplicación.
2. Diseño: la fase de diseño consiste en definir la experiencia del usuario (UX) de la
aplicación (como cuál es el diseño general, cómo funciona, etc.), así como convertir
esa experiencia del usuario en un diseño de interfaz de usuario (UI) adecuado,
normalmente con la ayuda de un diseñador gráfico.
3. Desarrollo: normalmente, es la fase con un uso más intensivo de recursos, esta es la
creación real de la aplicación.
4. Estabilización: cuando el desarrollo ha avanzado lo suficiente, normalmente el
control de calidad empieza a probar la aplicación y se corrigen los errores. A veces,
una aplicación pasará a una fase beta limitada en la que una audiencia de usuarios
más amplia tiene la oportunidad de usarla, enviar comentarios y notificar cambios.
5. Implementación

A menudo, muchas de estas partes se superponen, por ejemplo, es común que el desarrollo
siga mientras se finaliza la interfaz de usuario e incluso puede afectar al diseño de la
interfaz de usuario. Además, una aplicación puede estar en una fase de estabilización al
mismo tiempo que se agregan nuevas características a una nueva versión.

Asimismo, estas fases se pueden usar en varias metodologías de SDLC como Agile, Spiral,
Waterfall, etc.

Cada una de estas fases se explicará con más detalle en las secciones siguientes.
Inicio

La ubicuidad y el nivel de interacción que tienen los usuarios con los dispositivos móviles
implica que casi todos tienen una idea de una aplicación móvil. Los dispositivos móviles
abren una forma totalmente nueva de interactuar con la informática, la web e incluso la
infraestructura corporativa.

La fase de inicio consiste en definir y perfeccionar la idea de una aplicación. Para crear una
aplicación correctamente, es importante hacerse algunas preguntas fundamentales. Aquí
tiene algunas cuestiones que se deben tener en cuenta antes de publicar una aplicación en
una de las App Store públicas:

Ventaja competitiva: ¿ya existen aplicaciones similares? Si es así, ¿cómo se


diferencia esta aplicación de las otras?

Para las aplicaciones que se distribuirán en una empresa:

Integración de la infraestructura: ¿con qué infraestructura existente se integrará o


cuál extenderá?

Además, las aplicaciones deben evaluarse en el contexto del factor de forma móvil:

Valor: ¿qué valor aporta esta aplicación a los usuarios? ¿Cómo la usarán?
Forma/movilidad: ¿cómo funcionará esta aplicación en un factor de forma móvil?
¿Cómo puedo agregar valor mediante tecnologías móviles, como el reconocimiento
de ubicación, la cámara, etc.?

Para ayudarle a diseñar la funcionalidad de una aplicación, puede ser útil definir actores y
casos de uso. Los actores son roles dentro de una aplicación y, a menudo, son usuarios.
Los casos de uso son, normalmente, acciones o intentos.

Por ejemplo, una aplicación de seguimiento de tareas puede tener dos actores: usuario y
amigo. Un usuario podría Crear una tarea y Compartir una tarea con un amigo. En este
caso, crear y compartir una tarea son dos casos de uso distintos que, junto con los actores,
notificarán qué pantallas tiene que compilar, así como qué lógica y entidades empresariales
se deben desarrollar.
Una vez que se ha capturado una cantidad apropiada de casos de uso y actores, es mucho
más fácil empezar a diseñar una aplicación. El desarrollo se puede centrar entonces en
cómo crear la aplicación, en lugar de qué es la aplicación o qué debería hacer.

Diseñar aplicaciones móviles

Una vez que se hayan determinado las características y funcionalidades de la aplicación, el


siguiente paso es intentar resolver la experiencia del usuario o UX.

Diseño de la experiencia del usuario

Normalmente, la experiencia del usuario se realiza a través de tramas de alambres o


prototipos con herramientas como Balsamiq, Mockingbird, Visio o simplemente el lápiz y
papel de siempre. Los prototipos de experiencia del usuario permiten diseñar esta
experiencia sin tener que preocuparse por el diseño real de la interfaz de usuario:

Al crear prototipos de experiencia del usuario, es importante tener en cuenta las


instrucciones de la interfaz para las diferentes plataformas a las que se dirigirá la aplicación.
La aplicación debería "sentirse cómoda" en todas las plataformas. Las instrucciones de
diseño oficial para cada plataforma son:

1. Apple: Directrices de interfaz humana


2. Android: Instrucciones de diseño
3. Windows Phone: Biblioteca de diseño para Windows Phone

Por ejemplo, cada aplicación tiene una metáfora para cambiar de sección en una aplicación.
iOS usa una barra de pestañas en la parte inferior de la pantalla, mientras que Android usa
una barra de pestañas en la parte superior de la pantalla. Por otro lado, Windows Phone
usa la vista Panorámica:

Además, el propio hardware también impone decisiones de la experiencia del usuario. Por
ejemplo, los dispositivos iOS no tienen ningún botón Atrás físico y, por tanto, presentan la
metáfora de controlador de navegación:

Asimismo, el factor de forma también influye en las decisiones de la experiencia del usuario.
Una tableta tiene mucho más espacio y, por tanto, puede mostrar más información. A
menudo, lo que necesita varias pantallas en un teléfono, se comprime en una para una
tableta:

Debido a la infinidad de factores de forma que existen, a menudo hay factores de forma
medianos (entre un teléfono y una tableta) que puede que también quiera abordar.

Diseño de la interfaz de usuario (UI)

Una vez determinada la experiencia del usuario, el siguiente paso es crear el diseño de la
interfaz de usuario. Mientras que la experiencia del usuario suele componerse de prototipos
en blanco y negro, la fase de diseño de la interfaz de usuario es donde se introducen y
finalizan los colores, gráficos, etc. Es importante dedicar tiempo a un buen diseño de la
interfaz de usuario y, por lo general, las aplicaciones más populares tienen un diseño
profesional.

Al igual que con la experiencia del usuario, es importante comprender que cada plataforma
tiene su propio lenguaje de diseño, por lo que una aplicación bien diseñada puede tener un
aspecto diferente en cada plataforma:

Para obtener inspiración sobre el diseño de la interfaz de usuario, consulte algunos de los
siguientes sitios:

1. pttrns.com: (solo iOS)


2. androidpttrns.com: (solo Android)
3. lovelyui.com: (iOS, Android y Windows Phone)
4. mobiledesignpatterngallery.com: (iOS, Android y Windows Phone)

Además, es posible ver las carteras de diseñadores gráficos en sitios como Behance.com y
Dribbble.com. Ahí se pueden encontrar diseñadores de todo el mundo, a menudo en
lugares en que el tipo de cambio es favorable, por lo que un buen diseño gráfico no tiene
que costar mucho necesariamente.

Desarrollo

Normalmente, la fase de desarrollo se inicia muy pronto. De hecho, una vez que una idea
ha madurado un poco en la fase conceptual o de inspiración, a menudo se desarrolla un
prototipo de trabajo que valida la funcionalidad, las suposiciones y ayuda a comprender el
ámbito del trabajo.

En el resto de los tutoriales, nos centraremos principalmente en la fase de desarrollo.

Estabilización

La estabilización es el proceso de solucionar los errores de la aplicación. No solo desde un


punto de vista funcional (por ejemplo: "Se bloquea al hacer clic en este botón"), sino
también de facilidad de uso y rendimiento. Es mejor empezar la estabilización muy pronto
en el proceso de desarrollo para que se puedan realizar correcciones antes de que sean
costosas. Normalmente, las aplicaciones pasan por las fases Prototipo, Alfa, Beta y Versión
candidata para lanzamiento. Hay personas que las definen de forma diferente, pero,
generalmente, siguen el modelo siguiente:

1. Prototipo: la aplicación aún está en fase de prueba de concepto y solo funcionan la


funcionalidad principal o determinadas partes de la aplicación. Hay errores
principales.
2. Alfa: la funcionalidad principal tiene normalmente el código completado (compilado,
pero no probado por completo). Aún hay errores principales, puede que no haya
funcionalidades aisladas.
3. Beta: la mayoría de la funcionalidad está completa y ha pasado al menos una
corrección de errores y una prueba ligeras. Puede que aún haya problemas conocidos
principales.
4. Versión candidata para lanzamiento: toda la funcionalidad está completa y probada.
Salvo errores nuevos, la aplicación es una versión candidata para lanzamiento.

Nunca es demasiado pronto para empezar a probar una aplicación. Por ejemplo, si se
encuentra un problema importante en la fase de prototipo, aún se puede modificar la
experiencia del usuario de la aplicación para darle cabida. Si se encuentra un problema de
rendimiento en la fase alfa, es lo suficientemente pronto para modificar la arquitectura antes
de que se haya generado mucho código basado en suposiciones falsas.

Normalmente, según una aplicación avanza en el ciclo de vida, se abre a más personas
para que la prueben, envíen comentarios, etc. Por ejemplo, las aplicaciones prototipo
pueden mostrarse solo a partes interesadas clave o ponerse a disposición de estas partes,
mientras que las aplicaciones de versión candidata para lanzamiento pueden distribuirse a
los clientes que se hayan registrado para obtener acceso anticipado.

Para realizar primeras pruebas y la implementación en pocos dispositivos, normalmente es


suficiente implementar directamente desde un equipo de desarrollo. En cambio, si se va
ampliando el público, se puede volver más complicado rápidamente. Por tanto, hay una
serie de opciones de implementación de pruebas que facilitan este proceso al permitirle
invitar a usuarios a un grupo de pruebas, lanzar compilaciones en la web y proporcionar
herramientas que permiten que los usuarios envíen comentarios.

Algunas de las más populares son:

1. Testflight: se trata de un producto de iOS que le permite distribuir aplicaciones para


probarlas, así como recibir informes de errores e información de uso de los clientes.
Se incluye como parte de iTunes Connect y no está disponible si forma parte de una
suscripción al programa para desarrolladores empresariales de Apple.
2. LaunchPad (launchpadapp.com): diseñado para Android, este servicio es muy
similar a TestFlight.
3. Vessel (vessel.io): un servicio para iOS y Android que le permite supervisar el uso,
realizar un seguimiento de los clientes e incluso realizar pruebas A/B desde la
aplicación.
4. hockeyapp.com: proporciona un servicio de pruebas para iOS, Android y Windows
Phone.

Distribución

Una vez que la aplicación se ha estabilizado, es el momento de publicarla. Hay una serie de
opciones de distribución diferentes, dependiendo de la plataforma.

Las aplicaciones de Xamarin.iOS y Objective-C se distribuyen exactamente del mismo


modo:

1. Apple App Store: el App Store de Apple es un repositorio de aplicaciones en línea


disponible de forma global que está integrado en Mac OS X a través de iTunes. Sin
duda, es el método de distribución de aplicaciones más popular y permite a los
desarrolladores comercializar y distribuir sus aplicaciones en línea con muy poco
esfuerzo.
2. Implementación interna: la implementación interna está pensada para la distribución
interna de aplicaciones corporativas que no están disponibles de forma pública a
través del App Store.

3. Implementación ad hoc: la implementación ad hoc está pensada principalmente para


desarrollo y pruebas y le permite implementar en un número limitado de dispositivos
aprovisionados correctamente. Al implementar en un dispositivo mediante Xcode o
Visual Studio para Mac, se conoce como implementación ad hoc.

Android

Todas las aplicaciones de Android deben estar firmadas antes de distribuirlas. Los
desarrolladores firman sus aplicaciones mediante su propio certificado protegido por una
clave privada. Este certificado puede proporcionar una cadena de autenticidad que une a un
desarrollador de aplicaciones con las aplicaciones que ha creado y publicado. Debe tenerse
en cuenta que, mientras que un certificado de desarrollo para Android puede estar firmado
por una entidad de certificación reconocida, la mayoría de los desarrolladores no optan por
usar estos servicios y firman de forma automática sus certificados. El propósito principal de
los certificados es diferenciar entre las distintas aplicaciones y desarrolladores. Android usa
esta información para ayudar con el cumplimiento de delegación de permisos entre las
aplicaciones y componentes que se ejecutan en el sistema operativo Android.

A diferencia de otras plataformas móviles populares, Android adopta un enfoque muy


abierto para la distribución de aplicaciones. Los dispositivos no están bloqueados para usar
una única tienda de aplicaciones aprobada. En su lugar, cualquier usuario puede crear una
tienda de aplicaciones y la mayoría de teléfonos Android permite que las aplicaciones se
instalen desde estas tiendas de terceros.

Esto facilita a los desarrolladores un canal de distribución posiblemente más grande y aún
más complejo para sus aplicaciones. Google Play es la tienda de aplicaciones oficial de
Google, pero hay muchas otras. Algunas populares son:

1. AppBrain
2. Tienda Apps de Amazon para Android
3. Handango

4. GetJar

Windows Phone

Las aplicaciones de Windows Phone se distribuyen a los usuarios a través de la Tienda


Microsoft. Los desarrolladores envían sus aplicaciones al Centro de desarrollo de Windows
Phone para que las aprueben y después aparecen en la Tienda.

Microsoft proporciona instrucciones detalladas para implementar aplicaciones de Windows


Phone durante el desarrollo.

Siga estos pasos para publicar aplicaciones para pruebas beta y publicarlas en la tienda.
Los desarrolladores pueden enviar sus aplicaciones y después proporcionar un vínculo de
instalación para los evaluadores, antes de que la aplicación se revise y publique.

Consideraciones sobre el desarrollo móvil


Aunque desarrollar aplicaciones móviles no es fundamentalmente diferente que el desarrollo
web o de escritorio tradicional en términos de proceso o arquitectura, existen algunas
consideraciones que se deben tener en cuenta.

Consideraciones comunes

Multitarea

La multitarea (varias aplicaciones que se ejecutan a la vez) tiene dos retos importantes en
un dispositivo móvil. En primer lugar, dado el espacio real en pantalla limitado, es difícil
mostrar varias aplicaciones de forma simultánea. Por tanto, en los dispositivos móviles solo
puede haber una aplicación en primer plano de cada vez. En segundo lugar, tener varias
aplicaciones abiertas y realizando tareas puede agotar rápidamente la carga de la batería.

Cada plataforma trata la multitarea de forma diferente, lo que exploraremos en breve.

Factor de forma

Normalmente, los dispositivos móviles se dividen en dos categorías (teléfonos y tabletas)


con unos cuantos dispositivos intermedios. El desarrollo para estos factores de forma es
generalmente muy similar, en cambio, el diseño de aplicaciones para ellos puede ser muy
diferente. Los teléfonos tienen un espacio de pantalla muy limitado y las tabletas, aunque
son más grandes, siguen siendo dispositivos móviles con menos espacio de pantalla que la
mayoría de los portátiles. Por este motivo, los controles de interfaz de usuario de la
plataforma móvil se han diseñado específicamente para ser efectivos en factores de forma
más pequeños.

Fragmentación de sistema operativo y dispositivo

Es importante tener en cuenta distintos dispositivos en todo el ciclo de vida de desarrollo de


software:

1. Planeación y conceptualización: tenga en cuenta que el hardware y las


características varían de un dispositivo a otro, puede que una aplicación que se basa
en determinadas características no funcione correctamente en algunos dispositivos.
Por ejemplo, no todos los dispositivos tienen cámaras, por lo que, si está creando una
aplicación de mensajería de vídeo, puede que algunos dispositivos reproduzcan
vídeos, pero no los puedan grabar.
2. Diseño: al diseñar la experiencia del usuario (UX) de una aplicación, preste atención
a las diferentes relaciones y tamaños de pantalla de los dispositivos. Además, al
diseñar la interfaz de usuario (UI) de una aplicación, se deben tener en cuenta
diferentes resoluciones de pantalla.
3. Desarrollo: al usar una característica del código, siempre se debe probar primero la
presencia de esa característica. Por ejemplo, antes de usar una característica de
dispositivo, como una cámara, confirme siempre primero que el sistema operativo
tenga esa característica. Después, al inicializar el dispositivo o característica,
asegúrese de solicitar la compatibilidad actual del sistema operativo sobre el
dispositivo y después use esas opciones de configuración.

4. Pruebas: es muy importante probar la aplicación al principio y con frecuencia en


dispositivos reales. Puede haber incluso dispositivos con las mismas especificaciones
de hardware en que varíe mucho su comportamiento.

Recursos limitados

Los dispositivos móviles son cada vez mejores con el tiempo, pero siguen siendo
dispositivos móviles con capacidades limitadas en comparación con los equipos de
escritorio o portátiles. Por ejemplo, los desarrolladores de escritorio normalmente no se
preocupan por las capacidades de memoria; están acostumbrados a tener memoria virtual y
física en grandes cantidades, mientras que en los dispositivos móviles se puede consumir
toda la memoria disponible rápidamente solo con cargar algunas imágenes de alta calidad.

Además, las aplicaciones de uso intensivo del procesador, como juegos o reconocimiento
de texto, pueden influir realmente en la CPU móvil y afectar negativamente al rendimiento
del dispositivo.

Debido a consideraciones como estas, es importante crear el código de manera inteligente


e implementar pronto y con frecuencia en dispositivos reales para validar la capacidad de
respuesta.
Consideraciones de iOS

Multitarea

La multitarea está muy controlada en iOS y hay una serie de reglas y comportamientos que
la aplicación debe cumplir cuando otra aplicación está en primer plano, de lo contrario, iOS
cancelará la aplicación.

Recursos específicos del dispositivo

En un factor de forma determinado, el hardware puede variar considerablemente entre


diferentes modelos. Por ejemplo, algunos dispositivos tienen una cámara trasera, algunos
también tienen una cámara frontal y otros no tienen ninguna.

Algunos dispositivos antiguos (iPhone 3G y anteriores) ni siquiera permiten la multitarea.

Debido a estas diferencias entre modelos de dispositivos, es importante comprobar la


presencia de una característica antes de intentar usarla.

Restricciones específicas del sistema operativo

Para asegurarse de que las aplicaciones respondan correctamente y sean seguras, iOS
impone una serie de reglas que deben cumplir las aplicaciones. Además de las reglas con
respecto a la multitarea, hay una serie de métodos de evento de los que la aplicación debe
volver en una determinada cantidad de tiempo, de lo contrario, iOS la cancelará.

También cabe observar que las aplicaciones se ejecutan en lo que se conoce como espacio
aislado, un entorno que aplica restricciones de seguridad que restringen a qué puede tener
acceso la aplicación. Por ejemplo, una aplicación puede leer y escribir en su propio
directorio, pero si intenta escribir en otro directorio de aplicaciones, se cancelará.

Consideraciones de Android

Multitarea
La multitarea en Android tiene dos componentes; el primero es el ciclo de vida de la
actividad. Cada pantalla de una aplicación de Android se representa mediante una actividad
y hay un conjunto específico de eventos que se producen cuando una aplicación se coloca
en segundo plano o vuelve al primer plano. Las aplicaciones deben respetar este ciclo de
vida para que respondan y se comporten correctamente. Para obtener más información,
consulte la guía Activity Lifecycle (Ciclo de vida de la actividad).

El segundo componente de la multitarea de Android es el uso de servicios. Los servicios


son procesos de ejecución prolongada que existen independientes de una aplicación y se
usan para ejecutar procesos mientras la aplicación está en segundo plano. Para obtener
más información, consulte la guía Creating Services (Crear servicios).

Muchos dispositivos y muchos factores de forma

A diferencia de iOS, que tiene un conjunto pequeño de dispositivos, o incluso Windows


Phone, que solo se ejecuta en dispositivos aprobados que cumplen un conjunto mínimo de
requisitos de plataforma, Google no impone ningún límite sobre en qué dispositivos se
puede ejecutar el sistema operativo Android. Este paradigma abierto da como resultado un
entorno de productos lleno de una gran variedad de dispositivos diferentes con hardware,
resoluciones y relaciones de pantalla, características del dispositivo y capacidades muy
diferentes.

Debido a la fragmentación extrema de los dispositivos Android, la mayoría de los usuarios


elige los 5 o 6 dispositivos más populares para los que diseñar y probar y les da prioridad a
estos.

Consideraciones de seguridad

Todas las aplicaciones en el sistema operativo Android se ejecutan bajo una identidad
distinta y aislada con permisos limitados. De manera predeterminada, las aplicaciones
pueden hacer muy poco. Por ejemplo, sin permisos especiales, una aplicación no puede
enviar un mensaje de texto, determinar el estado del teléfono, ni siquiera obtener acceso a
Internet. Para tener acceso a estas características, las aplicaciones deben especificar en su
archivo de manifiesto de la aplicación qué permisos quieren y cuándo se instalan; el sistema
operativo lee los permisos, notifica al usuario que la aplicación pide esos permisos y
después permite al usuario continuar o cancelar la instalación. Este es un paso esencial en
el modelo de distribución de Android, debido al modelo de tienda de aplicaciones abierto, ya
que las aplicaciones no se mantienen de la misma forma que en iOS, por ejemplo. Para
obtener una lista de permisos de aplicaciones, consulte el artículo de referencia Manifest
Permissions (Permisos de manifiesto) en la documentación de Android.

Consideraciones sobre Windows Phone

Multitarea

La multitarea en Windows Phone también tiene dos partes: el ciclo de vida de páginas y
aplicaciones y los procesos en segundo plano. Cada pantalla de una aplicación es una
instancia de una clase de página, que tiene eventos asociados que se ponen en estado
activo o inactivo (con reglas especiales para controlar el estado inactivo o "con marcador de
exclusión"). Para obtener más información, consulte la documentación Execution Model
Overview for Windows Phone (Introducción al modelo de ejecución de Windows Phone).

La segunda parte consiste en proporcionar agentes en segundo plano para tareas de


procesamiento, incluso cuando la aplicación no se está ejecutando en primer plano. Puede
encontrar más información sobre la programación de tareas periódicas o la creación de
tareas en segundo plano con uso intensivo de recursos en Background Agents Overview
(Introducción a los agentes en segundo plano).

Capacidades del DISPOSITIVO

Aunque el hardware de Windows Phone es bastante homogéneo debido a las instrucciones


estrictas que proporciona Microsoft, hay componentes que son opcionales y, por tanto,
requieren consideraciones especiales durante la codificación. Entre las capacidades de
hardware opcionales se incluyen la cámara, la brújula y el giroscopio. También hay una
clase especial de memoria insuficiente (256 MB) que requiere una consideración especial, o
los desarrolladores pueden no participar en la compatibilidad con memoria insuficiente.

Base de datos
IOS y Android incluyen el motor de base de datos SQLite que permite el almacenamiento
sofisticado de datos que también es multiplataforma. Windows Phone 7 no incluía una base
de datos, mientras que Windows Phone 7.1 y 8 incluyen un motor de base de datos local
que solo se puede consultar con LINQ to SQL y no es compatible con las consultas de
Transact-SQL. Hay un puerto de código abierto de SQLite disponible que se puede agregar
a las aplicaciones de Windows Phone para proporcionar la compatibilidad multiplataforma
conocida de Transact-SQL.

Consideraciones de seguridad

Las aplicaciones de Windows Phone se ejecutan con un conjunto restringido de permisos


que las aísla unas de otras y limita las operaciones que pueden realizar. El acceso a redes
debe realizarse a través de las API específicas y la comunicación entre aplicaciones solo se
puede realizar a través de mecanismos controlados. El acceso al sistema de archivos
también está restringido; la API de almacenamiento aislado proporciona almacenamiento de
par clave-valor y la capacidad de crear archivos y carpetas de un modo controlado (consulte
Isolated Storage Overview (Introducción al almacenamiento aislado) para obtener más
información).

El acceso de una aplicación a las características de hardware y sistema operativo se


controla mediante las funcionalidades enumeradas en su archivo de manifiesto (similar a
Android). El manifiesto debe declarar las características que requiere la aplicación para que
los usuarios puedan ver y aceptar esos permisos y también para que el sistema operativo
permita el acceso a las API. Las aplicaciones deben requerir acceso a características como
los datos de contactos o citas, la cámara, la ubicación, la biblioteca multimedia, etc.
Consulte la documentación Application Manifest File (Archivo de manifiesto de aplicaciones)
de Microsoft para obtener información adicional.

Resumen
En esta guía, se le ha proporcionado una introducción al SDLC en lo referente al desarrollo
móvil. Se han introducido consideraciones generales para la creación de aplicaciones
móviles y se ha examinado una serie de cuestiones específicas de la plataforma, incluidos
el diseño, las prueba y la implementación.
Troubleshooting Xamarin for Visual Studio
Why doesn't Visual Studio include my referenced library project in my
build?

Visual Studio uses the Configuration Manager to determine which projects in a solution are
automatically included in a given build or deployment configuration. Some templates that are
generated with a referenced library project will already have the referenced library included
in the configuration; but otherwise it will need to be set manually.

Deploy checkboxes disabled in Configuration Manager

Since Xamarin 3.5, the Deploy checkboxes are intentionally disabled in the Visual Studio
Configuration Manager for Xamarin.iOS projects. Instead, Xamarin.iOS projects are now
deployed automatically whenever you press the Start toolbar button or pick the Debug >
Start Debugging menu item. You will still need to set the desired Xamarin.iOS app project
as the StartUp Project before before running either of those commands.

How do I collect the current call stacks of the Visual Studio process?

When the GUI locks up (hangs, freezes) in Visual Studio, an important piece of diagnostic
information to collect is the set of call stacks from all the threads of the Visual Studio
process. To save this information for a hung instance of Visual Studio, you can use a second
instance of Visual Studio.

How do I perform a thorough uninstall for Xamarin for Visual Studio?

This guide details how to perform full manual install and reinstall of Xamarin for Visual
Studio.

Missing Visual Studio extensions after installation

This guide provides troubleshooting steps for several possible scenarios where the Xamarin
extension is not accessible from within Visual Studio.
Why doesn't Visual Studio include my
referenced library project in my build?
Visual Studio uses the Configuration Manager to determine which projects in a solution are
automatically included in a given build or deployment configuration.

Some templates that are generated with a referenced library project will already have the
referenced library included in the configuration; but otherwise it will need to be set manually.

How to use the Configuration Manager

1. Open Build > Configuration Manager


2. Select the configuration to customize, e.g. Debug | iPhone
3. Select checkboxes for the projects you wish to include. Note: Greyed out boxes are
handled automatically, and shouldn't need any changes.

Screencast of these steps: http://screencast.com/t/zLoQOpEn


Deploy checkboxes disabled in Configuration
Manager
Since Xamarin 3.5, Xamarin.iOS projects deployed automatically whenever you press the Start toolbar
button or pick the Debug > Start Debugging menu item. You will still need to set the desired Xamarin.iOS
app project as the StartUp Project before before running either of those commands.

Because of this, the Deploy checkboxes are intentionally disabled in the Visual Studio Configuration
Manager for Xamarin.iOS projects:

This change eliminates an error that could appear in older versions of Xamarin (version 3.3 and earlier)
when the Xamarin.iOS app project was not set to deploy:
Deploy checkboxes disabled in Configuration
Manager
Since Xamarin 3.5, Xamarin.iOS projects deployed automatically whenever you press the Start toolbar
button or pick the Debug > Start Debugging menu item. You will still need to set the desired Xamarin.iOS
app project as the StartUp Project before before running either of those commands.

Because of this, the Deploy checkboxes are intentionally disabled in the Visual Studio Configuration
Manager for Xamarin.iOS projects:

This change eliminates an error that could appear in older versions of Xamarin (version 3.3 and earlier)
when the Xamarin.iOS app project was not set to deploy:
How do I collect the current call stacks of the Visual
Studio process?
When the GUI locks up (hangs, freezes) in Visual Studio, an important piece of diagnostic information to collect is
the set of call stacks from all the threads of the Visual Studio process. To save this information for a hung
instance of Visual Studio, you can use a second instance of Visual Studio:

1. Start a second instance (a new window) of Visual Studio.

2. Close any open solutions in the new instance of Visual Studio.

3. Select Debug > Attach to Process.

4. Select the original hung instance of devenv.exe from the list of Available Processes.

5. Select Debug > Break All.

6. Select Debug > Save Dump As.


7. Change Save as type to Minidump (*.dmp). This will produce a much smaller file than Minidump with
Heap, and the heap is usually not relevant for diagnosing freezes.

8. Save the dump file. If submitting the file online, you can zip it to reduce the size.
How do I perform a thorough uninstall for Xamarin
for Visual Studio?
1. From the Windows Control Panel, uninstall any of the following that are present:

Xamarin
Xamarin for Windows
Xamarin.Android
Xamarin.iOS
Xamarin for Visual Studio

2. In Explorer, delete any remaining files from the Xamarin Visual Studio extension folders (all versions,
including both Program Files and Program Files (x86)):

C:\Program Files*\Microsoft Visual Studio 1*.0\Common7\IDE\Extensions\Xamarin

3. Delete Visual Studio's MEF component cache directory as well:

%LOCALAPPDATA%\Microsoft\VisualStudio\1*.0\ComponentModelCache

In fact, this step by itself is often sufficient to resolve errors such as:

"The 'XamarinShellPackage' package did not load correctly"

"The project file ... cannot be opened. There is a missing project subtype"

"Object reference not set to an instance of an object. at


Xamarin.VisualStudio.IOS.XamarinIOSPackage.Initialize()"

"SetSite failed for package" (in Visual Studio's ActivityLog.xml)

"LegacySitePackage failed for package" (in Visual Studio's ActivityLog.xml)

(See also the Clear MEF Component Cache Visual Studio extension. And see Bug 40781, Comment
19 for a bit more context about the upstream issue in Visual Studio that can cause these errors.)

4. Also check in the VirtualStore directory to see if Windows might have stored any overlay files for the
Extensions\Xamarin or ComponentModelCache directories there:

%LOCALAPPDATA%\VirtualStore

5. Open the registry editor (regedit).


6. Look for the following key:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDlls

7. Find and delete any entries that match this pattern:

C:\Program Files*\Microsoft Visual Studio 1*.0\Common7\IDE\Extensions\Xamarin

8. Look for this key:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\1*.0\ExtensionManager\PendingDeletions

9. Delete any entries that look like they might be related to Xamarin. For example, here's one that used to
cause trouble in older versions of Xamarin:

Mono.VisualStudio.Shell,1.0

10. Open an administrator cmd.exe command prompt, and then run the devenv /setup and devenv
/updateconfiguration commands for each installed version of Visual Studio. For example, for
Visual Studio 2015:

"%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"


/setup
"%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"
/updateconfiguration

11. Reboot.

12. Reinstall the current stable version of Xamarin using from visualstudio.com.

Additional troubleshooting steps for "package did not load


correctly"

In cases where the above steps do not resolve the "package did not load correctly" error, here are a few
more steps to try.

1. Create a new Windows user account.

2. Check if the Xamarin Visual Studio extensions load without error for the new user.

3. If the extensions load correctly, then the problem is most likely caused by some of the stored settings
for the original user:
In Explorer – %LOCALAPPDATA%\Microsoft\VisualStudio\1*.0
In regedit – HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\1*.0
In regedit – HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\1*.0_Config

4. If those stored settings do indeed appear to be the problem, you can try backing them up and then
deleting them.
Missing Visual Studio extensions after installation

Error Message

This project is incompatible with the current edition of Visual Studio

Double-check Visual Studio compatibility

Ensure a compatible version of Visual Studio is installed:

Visual Studio 2015 (Community, Professional, or Enterprise)


Visual Studio 2017 (Community, Professional, or Enterprise)

Visual Studio 2015 Express edition is not compatible with Xamarin because they do not allow installation of 3rd
party extensions.

See also the Windows requirements.

Possible Fix 1: Change the installation to make sure the Visual Studio
extensions are installed

In certain situations, the Xamarin installer might automatically un-check the install options for the Visual Studio
extensions. If that's the cause of the problem, install the missing Visual Studio extensions using the installer's
Change command. For example, to install the extensions for Visual Studio 2013:

1. Open the Windows Programs and Features Control Panel.

2. Right click the Xamarin entry, and select Change.

3. Click Next, then Change.

4. Make sure the Xamarin for Visual Studio 2013 option is set to install:
5. Proceed through the rest of the installer wizard.

Possible Fix 2: Ask Visual Studio to set up the extensions again

1. Check if the Xamarin extensions have been copied into the Visual Studio extensions folder:

C:\Program Files (x86)\Microsoft Visual Studio


12.0\Common7\IDE\Extensions\Xamarin\Xamarin\3.1.228.0

If the extensions are properly installed (for version 3.1.228), there will be 60 items in the folder:
2. After you have confirmed that this folder looks correct, tell Visual Studio to try setting up the extensions
again:

"C:\Program Files (x86)\Microsoft Visual Studio


12.0\Common7\IDE\devenv.exe" /setup

Possible Fix 3: Try a fresh reinstall of Xamarin

1. From the Windows Control Panel, uninstall any of the following that are present:

Xamarin

Xamarin for Windows

Xamarin.Android

Xamarin.iOS

Xamarin for Visual Studio

2. In Explorer, delete any remaining files from the Xamarin Visual Studio extension folders (all versions,
including both Program Files and Program Files (x86)):

C:\Program Files*\Microsoft Visual Studio


1*.0\Common7\IDE\Extensions\Xamarin

3. Also check in the "VirtualStore" directory to see if there might be any "overlay" copies of any of the extension
directories:

%LOCALAPPDATA%\VirtualStore

4. Open the registry editor (regedit).

5. Look for this key:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SharedDlls

6. Find and delete any entries that match this pattern:

C:\Program Files*\Microsoft Visual Studio 1*.0\Common7\IDE\Extensions\Xamarin

7. Look for this key:


HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\1*.0\ExtensionManager\PendingDeletions

8. Delete any entries that look like they might be related to Xamarin. For example, here's one that used to
cause trouble in older versions of Xamarin:

Mono.VisualStudio.Shell,1.0

9. Reboot.

10. Reinstall the current stable version of Xamarin from visualstudio.com.

Possible Fix 4: Repair Visual Studio installation

1. Open the Windows Programs and Features Control Panel.

2. Right click the relevant Microsoft Visual Studio entry, and select Change

3. Click the Repair button in the Visual Studio dialog that opens.
Downgrading Visual Studio 2017
1. Uninstall Visual Studio 2017 using the Visual Studio Installer.

For more information on how to do this, follow the steps in the Uninstall Visual Studio guide.

2. Download the Visual Studio 2017 version 15.0 RTW installer from my.visualstudio.com.

For more information on how to do this, refer to the older downloads page

3. Run the installer to install Visual Studio 2017, version 15.0.

For more information on how to do this, refer to the installation page. Remember to select the
Mobile development with .NET workload when you install.

Compatible Mac Versions

If you are developing on both Visual Studio for Windows and Visual Studio for Mac, it is recommended that
you have compatible versions of all products on both IDEs.

As per this blog post, the compatible versions for 15.0 RTW are:

Xamarin Studio 6.2.1.3


Xamarin.iOS 10.6.0.10
Xamarin.Android 7.1.0-43
Xamarin Profiler 1.2.1-3
Xamarin.Mac 3.0.0.398
Mono Framework MDK 4.8.1.0
Mono Project download archive

These can be download on the Xamarin Account page by selecting the correct version under each product:
ℹ️ If you only use the Mac remotely as a build host for iOS and Xamarin.Mac, you can skip
the the installation of the Android and Visual Studio for Mac packages
Remoted iOS Simulator (for Windows)

Download and Install


Download the installer and install on your Windows computer. Visual Studio Tools for Xamarin should
already be installed.

ℹ️ Using a remote iOS Simulator requires Visual Studio a networked Mac with Xamarin
installed.
Getting Started
To use the remote iOS simulator:

1. Make sure Visual Studio has connected to your Mac at least once before starting the remote iOS
Simulator.
2. Ensure an iOS or tvOS app is the Startup Project and start debugging.

You can disable the remote iOS simulator from Tools > Options > Xamarin > iOS Settings by
unchecking the box for Remote Simulator to Windows shown here:

The iOS simulator will then open on the connected Mac computer. Check this option to turn the remote
iOS simulator back on.

Features
The remote iOS Simulator provides you with a way to test and debug iOS apps on the simulator entirely
from Visual Studio on Windows.

Simulator Window

The window toolbar includes a number of buttons to interact with the simulator:

Home – simulates the home button on the device.


Lock – locks the simulator (you can swipe to unlock).
Screenshot – saves a screenshot of the simulator to disk.

Settings – configure the keyboard and location.

Other options – a variety of simulator options are available such as rotate, shake, or invoke
other states in the simulator. When some options are obscured, they can be accessed from
the ellipsis icon that appears in the toolbar, or by right-clicking on the window.
Settings

The "gear" icon opens the Settings window:


This allows you to enable the hardware keyboard on the simulator, and choose what location is reported
to the device (including a static location, or other moving location options).

Other Options

Right-click anywhere in the simulator window to view all the options available in the simulator, such as
rotation, triggering a shake gesture, and rebooting the simulator:
Touchscreen Support

Most modern Windows computers have touch screens, and the remote iOS simulator lets you touch the
simulator window to test user interactions in your iOS app.

This includes pinching, swiping, and multiple-finger touch gestures - things that previously could only be
easily tested on physical devices.

Stylus support in Windows is also translated to Apple Pencil input on the simulator.
Application Fundamentals

Core Application Concepts

This section provides a guide on some of the more common things tasks or concepts that
developers need to be aware of when developing mobile applications.

Building Cross Platform Applications

By choosing Xamarin and keeping a few things in mind when you design and develop your
mobile applications, you can realize tremendous code sharing across mobile platforms,
reduce your time to market, leverage existing talent, meet customer demand for mobile
access, and reduce cross-platform complexity. This document outlines key guidelines to
realizing these advantages for utility and productivity applications.

Code Sharing Options

Learn about the different code sharing options available for Xamarin projects, including
Portable Class Libraries (PCLs), Shared Projects, and .NET Standard Libraries.

Portable Class Libraries

Portable Class Library projects let you build and distribute assemblies that contain shared
code to run on multiple platforms. To create a Portable Class Library (or "PCL") you first
select which platforms to target, then write code against a sub-set of the .NET Framework
that is available in the profile defined for those platforms. This document describes how to
create and use PCLs with Xamarin.

Shared Projects

Shared Projects let you write common code that is referenced by a number of different
application projects. The code is compiled as part of each referencing project and can
include compiler directives to help incorporate platform-specific functionality in the shared
code base. This article discusses how Shared Projects work and how to create and use
them with Xamarin projects.

.NET Standard

.NET Standard is a new option for sharing code across platforms. It works in a similar
fashion to Portable Class Libraries; code is built against a specific version (currently 1.0
through 1.6) and can then be consumed by other projects that support that level or higher.
.NET Standard projects are supported in Xamarin Studio 6.2, Visual Studio for Windows,
and Visual Studio for Mac.

NuGet Projects: Multiplatform Libraries for Code


Sharing

NuGet packages can be automatically generated from PCL or .NET standard projects; and
Shared Projects can be packaged into "bait and switch" NuGet packages using the separate
NuGet project type. This section explains how to create NuGet packages for each code-
sharing scenario.

Cross Platform Data Access

Most applications have some requirement to save data on the device locally. Unless the
amount of data is trivially small, this usually requires a database and a data layer in the
application to manage database access. iOS and Android both have the SQLite database
engine “built in” and access to store and retrieve data is simplified by Xamarin’s platform.
The Android data access, iOS data access, and Xamarin.Forms data access guides provide
examples of how to access SQLite on each platform.

Introduction To Web Services


This tutorial introduces how to integrate REST, WCF and SOAP web service technologies
with Xamarin mobile applications. It examines various service implementations, evaluates
available tools and libraries to integrate them, and provides sample patterns for consuming
service data. Finally, it provides a basic overview of creating a RESTful web service for
consumption with a Xamarin mobile application.

Memory and Performance Best Practices

This article discusses items to improve memory and performance of applications built with
Xamarin. It examines general, cross-platform memory issues that are common when
working in garbage collected environments, as well as platform specific items. It also covers
performance techniques for keeping applications responsive.

Transport Layer Security

Information on selectingthe correct SSL/TLS implementation to secure your app's network


connectivity.

Notifications

Mobile applications use notifications as an unobtrusive way of informing the user that some
application specific event has happened. Notifications are typically used to notify the user of
the status of an application process that is running in the background. An example of this
might be downloading a large file. This file might take a long time to download, so this
activity should occur in the background. When the download is complete, the user is
informed of the fact by a notification. Additionally, notification ares not just limited to local
applications. It is also possible for server applications to publish notifications to mobile
applications. This article will discuss how to use notifications on both Android and iOS.
Building Cross Platform Applications

Best practices for developing mobile applications with


Xamarin

Sharing Code Options


There are two options for sharing code between cross-platform mobile applications: Shared
Asset Projects and Portable Class Libraries. These options are discussed here; more
information on Portable Class Libraries and Shared Projects is also available.

Building Cross Platform Mobile Apps


Overview

Part 1 – Understanding the Xamarin Mobile Platform

Part 2 – Architecture

Part 3 – Setting Up a Xamarin Cross Platform Solution

Part 4 – Dealing with Multiple Platforms

Part 5 – Practical Code Sharing Strategies

Part 6 - Testing and App Store Approvals

Case Studies
The principles outlined in this document are put into practice in the sample application
Tasky, as well as pre-built applications like Xamarin CRM.
Tasky

Tasky is a simple to-do list application for iOS, Android and Windows Phone. It
demonstrates the basics of creating a cross-platform application with Xamarin and uses a
local SQLite database.

Read the Tasky Case Study.

Summary
This section introduces Xamarin’s application development tools and discusses how to build
applications that target multiple mobile platforms.

It covers a layered architecture that structures code for re-use across multiple platforms, and
describes different software patterns that can be used within that architecture.

Examples are given of common application functions (like file and network operations) and
how they can be built in a cross-platform way.

Finally, it briefly discusses testing, and provides references to a case study that puts these
principles into action.
Building Cross Platform Applications
Overview

Overview
This guide introduces the Xamarin platform and how to architect a cross-platform application
to maximize code re-use and deliver a high-quality native experience on all of the main
mobile platforms: iOS, Android and Windows Phone.

The approach used in this document is generally applicable to both productivity apps and
game apps, however the focus is on productivity and utility (non-game applications). See the
Introduction to MonoGame document or check out Visual Studio Tools for Unity for cross-
platform game development guidance.

The phrase “write-once, run everywhere” is often used to extol the virtues of a single
codebase that runs unmodified on multiple platforms. While it has the benefit of code re-use,
that approach often leads to applications that have a lowest-common-denominator feature-
set and a generic-looking user interface that does not fit nicely into any of the target
platforms.

Xamarin is not just a “write-once, run everywhere” platform, because one of its strengths is
the ability to implement native user interfaces specifically for each platform. However, with
thoughtful design it’s still possible to share most of the non-user interface code and get the
best of both worlds: write your data storage and business logic code once, and present
native UIs on each platform. This document discusses a general architectural approach to
achieve this goal.

Here is a summary of the key points for creating Xamarin cross-platform apps:

Use C# - Write your apps in C#. Existing code written in C# can be ported to iOS and
Android using Xamarin very easily, and obviously used in Windows apps.
Utilize MVC or MVVVM design patterns - Develop your application’s User Interface
using the Model/View/Controller pattern. Architect your application using a
Model/View/Controller approach or a Model/View/ViewModel approach where there is
a clear separation between the “Model” and the rest. Determine which parts of your
application will be using native user interface elements of each platform (iOS, Android,
Windows, Mac) and use this as a guideline to split your application into two
components: “Core” and “User-Interface”.

Build native UIs - Each OS-specific application provides a different user-interface


layer (implemented in C# with the assistance of native UI design tools):

1. On iOS, use the UIKit APIs to create native-looking applications, optionally


utilizing Xamarin's iOS designer to create your UI visually.
2. On Android, use Android.Views to create native-looking applications, taking
advantage of Xamarin’s UI designer.
3. On Windows you will be using XAML for presentation layer, created in Visual
Studio or Blend’s UI designer.
4. On Mac, you will use Storyboards for the presentation layer, created in Xcode.

Xamarin.Forms projects are supported on all platforms, and allow you create user interfaces
that can be shared across platforms using Xamarin.Forms XAML.

The amount of code re-use will depend largely on how much code is kept in the shared core
and how much code is user-interface specific. The core code is anything that does not
interact directly with the user, but instead provides services for parts of the application that
will collect and display this information.

To increase the amount of code re-use, you can adopt cross-platform components that
provide common services across all these systems such as:

1. SQLite-net for local SQL storage,


2. Xamarin Plugins for accessing device-specific capabilities including the camera,
contacts and geolocation,
3. NuGet packages that are compatible with Xamarin projects, such as Json.NET,
4. Using .NET framework features for networking, web services, IO and more.
Some of these components are implemented in the Tasky case study.

Separate Reusable Code into a Core Library

By following the principle of separation of responsibility by layering your application


architecture and then moving core functionality that is platform agnostic into a reusable core
library, you can maximize code sharing across platforms, as the figure below illustrates:

Case Studies

There is one case study that accompanies this document – Tasky Pro. Each case study
discusses the implementation of the concepts outlined in this document in a real-world
example. The code is open source and available on github.
Part 1 – Understanding the Xamarin Mobile
Platform
The Xamarin platform consists of a number of elements that allow you to develop applications for iOS and
Android:

C# language – Allows you to use a familiar syntax and sophisticated features like Generics, LINQ
and the Parallel Task Library.
Mono .NET framework – Provides a cross-platform implementation of the extensive features in
Microsoft’s .NET framework.
Compiler – Depending on the platform, produces a native app (eg. iOS) or an integrated .NET
application and runtime (eg. Android). The compiler also performs many optimizations for mobile
deployment such as linking away un-used code.
IDE tools – The Visual Studio on Mac and Windows allows you to create, build, and deploy Xamarin
projects.

In addition, because the underlying language is C# with the .NET framework, projects can be structured to
share code that can also be deployed to Windows Phone.

Under the Hood


Although Xamarin allows you to write apps in C#, and share the same code across multiple platforms, the
actual implementation on each system is very different.

Compilation

The C# source makes its way into a native app in very different ways on each platform:

iOS – C# is ahead-of-time (AOT) compiled to ARM assembly language. The .NET framework is
included, with unused classes being stripped out during linking to reduce the application size. Apple
does not allow runtime code generation on iOS, so some language features are not available (see
Xamarin.iOS Limitations ).
Android – C# is compiled to IL and packaged with MonoVM + JIT’ing. Unused classes in the
framework are stripped out during linking. The application runs side-by-side with Java/ART (Android
runtime) and interacts with the native types via JNI (see Xamarin.Android Limitations ).
Windows – C# is compiled to IL and executed by the built-in runtime, and does not require Xamarin
tools. Designing Windows applications following Xamarin’s guidance makes it simpler to re-use the
code on iOS and Android. Note that the Universal Windows Platform also has a .NET Native option
which behaves similarly to Xamarin.iOS' AOT compilation.

The linker documentation for Xamarin.iOS and Xamarin.Android provides more information about this part
of the compilation process.

Runtime 'compilation' – generating code dynamically with System.Reflection.Emit – should be


avoided.

Apple’s kernel prevents dynamic code generation on iOS devices, therefore emitting code on-the-fly will not
work in Xamarin.iOS. Likewise, the Dynamic Language Runtime features cannot be used with Xamarin
tools.

Some reflection features do work (eg. MonoTouch.Dialog uses it for the Reflection API), just not code
generation.

Platform SDK Access

Xamarin makes the features provided by the platform-specific SDK easily accessible with familiar C#
syntax:

iOS – Xamarin.iOS exposes Apple’s CocoaTouch SDK frameworks as namespaces that you can
reference from C#. For example the UIKit framework that contains all the user interface controls can
be included with a simple using UIKit; statement.
Android – Xamarin.Android exposes Google’s Android SDK as namespaces, so you can reference
any part of the supported SDK with a using statement, such as using Android.Views; to access
the user interface controls.

Windows – Windows apps are built using Visual Studio on Windows. Project types include Windows
Forms, WPF, WinRT, and the Universal Windows Platform (UWP).

Seamless Integration for Developers

The beauty of Xamarin is that despite the differences under the hood, Xamarin.iOS and Xamarin.Android
(coupled with Microsoft’s Windows SDKs) offer a seamless experience for writing C# code that can be re-
used across all three platforms.

Business logic, database usage, network access, and other common functions can be written once and re-
used on each platform, providing a foundation for platform-specific user interfaces that look and perform as
native applications.

Integrated Development Environment (IDE)


Availability
Xamarin development can be done in Visual Studio on either Mac or Windows. The IDE you choose will be
determined by the platforms you wish to target.

Because Windows apps can only be developed on Windows, to build for iOS, Android, and Windows
requires Visual Studio for Windows. However it's possible to share projects and files between Windows and
Mac computers, so iOS and Android apps can be built on a Mac and shared code could later be added to a
Windows project.

The development requirements for each platform are discussed in more detail in the Requirement guide.

iOS

Developing iOS applications requires a Mac computer, running macOS. You can also use Visual Studio to
write and deploy iOS applications with Xamarin in Visual Studio. However, a Mac is still needed for build
and licensing purposes.

Apple’s Xcode IDE must be installed to provide the compiler and simulator for testing. You can test on your
own devices for free, but to build applications for distribution (eg. the App Store) you must join Apple’s
Developer Program ($99 USD per year). Each time you submit or update an application, it must be
reviewed and approved by Apple before it is made available for customers to download.

Code is written with the Visual Studio IDE and screen layouts can be built programmatically or edited with
Xamarin's iOS Designer in either IDE.

Refer to the Xamarin.iOS Installation Guide for detailed instructions on getting set up.

Android

Android application development requires the Java and Android SDKs to be installed. These provide the
compiler, emulator and other tools required for building, deployment and testing. Java, Google’s Android
SDK and Xamarin’s tools can all be installed and run on the following configurations:

Mac OS X El Capitan and above (10.11+) with Visual Studio for Mac
Windows 7 & above with Visual Studio 2015 or 2017

Xamarin provides a unified installer that will configure your system with the pre-requisite Java, Android and
Xamarin tools (including a visual designer for screen layouts). Refer to the Xamarin.Android Installation
Guide for detailed instructions.

You can build and test applications on a real device without any license from Google, however to distribute
your application through a store (such as Google Play, Amazon or Barnes & Noble) a registration fee may
be payable to the operator. Google Play will publish your app instantly, while the other stores have an
approval process similar to Apple’s.

Windows

Windows apps (WinForms, WPF, or UWP) are built with Visual Studio. They do not use Xamarin directly.
However, C# code can be shared across Windows, iOS and Android. Visit Microsoft’s Dev Center to learn
about the tools required for Windows development.

Creating the User Interface (UI)


A key benefit of using Xamarin is that the application user interface uses native controls on each platform,
creating apps that are indistinguishable from an application written in Objective-C or Java (for iOS and
Android respectively).

When building screens in your app, you can either lay out the controls in code or create complete screens
using the design tools available for each platform.

Create Controls Programmatically

Each platform allows user interface controls to be added to a screen using code. This can be very time-
consuming as it can be difficult to visualize the finished design when hard-coding pixel coordinates for
control positions and sizes.

Programmatically creating controls does have benefits though, particularly on iOS for building views that
resize or render differently across the iPhone and iPad screen sizes.

Visual Designer

Each platform has a different method for visually laying out screens:
iOS – Xamarin's iOS Designer facilitates building Views using drag-and-drop functionality and
property fields. Collectively these Views make up a Storyboard, and can be accessed in the
.Storyboard file that is included in your project.
Android – Xamarin provides an Android drag-and-drop UI designer for Visual Studio. Android screen
layouts are saved as .AXML files when using Xamarin tools.
Windows – Microsoft provides a drag-and-drop UI designer in Visual Studio and Blend. The screen
layouts are stored as .XAML files.

These screenshots show the visual screen designers available on each platform:

In all cases the elements that you create visually can be referenced in your code.

User Interface Considerations

A key benefit of using Xamarin to build cross platform applications is that they can take advantage of native
UI toolkits to present a familiar interface to the user. The UI will also perform as fast as any other native
application.

Some UI metaphors work across multiple platforms (for example, all three platforms use a similar scrolling-
list control) but in order for your application to ‘feel’ right the UI should take advantage of platform-specific
user interface elements when appropriate. Examples of platform-specific UI metaphors include:

iOS – hierarchical navigation with soft back button, tabs on the bottom of the screen.
Android – hardware/system-software back button, action menu, tabs on the top of the screen.
Windows – Windows apps can run on desktops, tablets (such as Microsoft Surface) and phones.
Windows 10 devices may have hardware back button and live tiles, for example.

It is recommended that you read the design guidelines relevant to the platforms you are targeting:
iOS – Apple's Human Interface Guidelines
Android – Google's User Interface Guidelines

Windows – User Experience Design Guidelines for Windows

Library and Code Re-Use


The Xamarin platform allows re-use of existing C# code across all platforms as well as the integration of
libraries written natively for each platform.

C# Source and Libraries

Because Xamarin products use C# and the .NET framework, lots of existing source code (both open
source and in-house projects) can be re-used in Xamarin.iOS or Xamarin.Android projects. Often the
source can simply be added to a Xamarin solution and it will work immediately. If an unsupported .NET
framework feature has been used, some tweaks may be required.

Examples of C# source that can be used in Xamarin.iOS or Xamarin.Android include: SQLite-NET,


NewtonSoft.JSON and SharpZipLib.

Objective-C Bindings + Binding Projects

Xamarin provides a tool called btouch that helps create bindings that allow Objective-C libraries to be used
in Xamarin.iOS projects. Refer to the Binding Objective-C Types documentation for details on how this is
done.

Examples of Objective-C libraries that can be used in Xamarin.iOS include: RedLaser barcode scanning,
Google Analytics and PayPal integration. Open-source Xamarin.iOS bindings are available on github.

.jar Bindings + Binding Projects

Xamarin supports using existing Java libraries in Xamarin.Android. Refer to the Binding a Java Library
documentation for details on how to use a .JAR file from Xamarin.Android.

Open-source Xamarin.Android bindings are available on github.

C via PInvoke

"Platform Invoke" technology (P/Invoke) allows managed code (C#) to call methods in native libraries as
well as support for native libraries to call back into managed code.

For example, the SQLite-NET library uses statements like this:

[DllImport("sqlite3", EntryPoint = "sqlite3_open",


CallingConvention=CallingConvention.Cdecl)]
public static extern Result Open (string filename, out IntPtr db);

This binds to the native C-language SQLite implementation in iOS and Android. Developers familiar with an
existing C API can construct a set of C# classes to map to the native API and utilize the existing platform
code. There is documentation for linking native libraries in Xamarin.iOS, similar principles apply to
Xamarin.Android.

C++ via CppSharp

Miguel explains CXXI (now called CppSharp) on his blog. An alternative to binding to a C++ library directly
is to create a C wrapper and bind to that via P/Invoke.
Part 2 - Architecture
A key tenet of building cross-platform apps is to create an architecture that lends itself to a
maximization of code sharing across platforms. Adhering to the following Object Oriented
Programming principles helps build a well-architected application:

Encapsulation – Ensuring that classes and even architectural layers only expose a
minimal API that performs their required functions, and hides the implementation
details. At a class level, this means that objects behave as ‘black boxes’ and that
consuming code does not need to know how they accomplish their tasks. At an
architectural level, it means implementing patterns like Façade that encourage a
simplified API that orchestrates more complex interactions on behalf of the code in
more abstract layers. This means that the UI code (for example) should only be
responsible for displaying screens and accepting user-input; and never interacting with
the database directly. Similarly the data-access code should only read and write to the
database, but never interact directly with buttons or labels.
Separation of Responsibilities – Ensure that each component (both at architectural
and class level) has a clear and well-defined purpose. Each component should
perform only its defined tasks and expose that functionality via an API that is
accessible to the other classes that need to use it.
Polymorphism – Programming to an interface (or abstract class) that supports
multiple implementations means that core code can be written and shared across
platforms, while still interacting with platform-specific features.

The natural outcome is an application modeled after real world or abstract entities with
separate logical layers. Separating code into layers make applications easier to understand,
test and maintain. It is recommended that the code in each layer be physically separate
(either in directories or even separate projects for very large applications) as well as logically
separate (using namespaces).

Typical Application Layers


Throughout this document and the case studies we refer to the following six application
layers:

Data Layer – Non-volatile data persistence, likely to be a SQLite database but could
be implemented with XML files or any other suitable mechanism.
Data Access Layer – Wrapper around the Data Layer that provides Create, Read,
Update, Delete (CRUD) access to the data without exposing implementation details to
the caller. For example, the DAL may contain SQL statements to query or update the
data but the referencing code would not need to know this.
Business Layer – (sometimes called the Business Logic Layer or BLL) contains
business entity definitions (the Model) and business logic. Candidate for Business
Façade pattern.
Service Access Layer – Used to access services in the cloud: from complex web
services (REST, JSON, WCF) to simple retrieval of data and images from remote
servers. Encapsulates the networking behavior and provides a simple API to be
consumed by the Application and UI layers.
Application Layer – Code that’s typically platform specific (not generally shared
across platforms) or code that is specific to the application (not generally reusable). A
good test of whether to place code in the Application Layer versus the UI Layer is (a)
to determine whether the class has any actual display controls or (b) whether it could
be shared between multiple screens or devices (eg. iPhone and iPad).
User Interface (UI) Layer – The user-facing layer, contains screens, widgets and the
controllers that manage them.

An application may not necessarily contain all layers – for example the Service Access Layer
would not exist in an application that does not access network resources. A very simple
application might merge the Data Layer and Data Access Layer because the operations are
extremely basic.

Common Mobile Software Patterns


Patterns are an established way to capture recurring solutions to common problems. There
are a few key patterns that are useful to understand in building maintainable/understandable
mobile applications.

Model, View, ViewModel (MVVM) – The Model-View-ViewModel pattern is popular


with frameworks that support data-binding, such as Xamarin.Forms. It was popularized
by XAML-enabled SDKs like Windows Presentation Foundation (WPF) and Silverlight;
where the ViewModel acts as a go-between between the data (Model) and user
interface (View) via data binding and commands.
Model, View, Controller (MVC) – A common and often misunderstood pattern, MVC
is most often used when building User Interfaces and provides for a separation
between the actual definition of a UI Screen (View), the engine behind it that handles
interaction (Controller), and the data that populates it (Model). The model is actually a
completely optional piece and therefore, the core of understanding this pattern lies in
the View and Controller. MVC is a popular approach for iOS applications.
Business Façade – AKA Manager Pattern, provides a simplified point of entry for
complex work. For example, in a Task Tracking application, you might have a
TaskManager class with methods such as GetAllTasks() , GetTask(taskID) ,
SaveTask (task) , etc. The TaskManager class provides a Façade to the inner
workings of actually saving/retrieving of tasks objects.
Singleton – The Singleton pattern provides for a way in which only a single instance
of a particular object can ever exist. For example, when using SQLite in mobile
applications, you only ever want one instance of the database. Using the Singleton
pattern is a simple way to ensure this.
Provider – A pattern coined by Microsoft (arguably similar to Strategy, or basic
Dependency Injection) to encourage code re-use across Silverlight, WPF and
WinForms applications. Shared code can be written against an interface or abstract
class, and platform-specific concrete implementations are written and passed in when
the code is used.
Async – Not to be confused with the Async keyword, the Async pattern is used when
long-running work needs to be executed without holding up the UI or current
processing. In its simplest form, the Async pattern simply describes that long-running
tasks should be kicked off in another thread (or similar thread abstraction such as a
Task) while the current thread continues to process and listens for a response from the
background process, and then updates the UI when data and or state is returned.

Each of the patterns will be examined in more detail as their practical use is illustrated in the
case studies. Wikipedia has more detailed descriptions of the MVVM, MVC, Facade,
Singleton, Strategy and Provider patterns (and of Design Patterns generally).
Part 3 - Setting Up A Xamarin Cross Platform
Solution
Regardless of what platforms are being used, Xamarin projects all use the same solution file format (the
Visual Studio .sln file format). Solutions can be shared across development environments, even when
individual projects cannot be loaded (such as a Windows project in Visual Studio for Mac).

When creating a new cross platform application, the first step is to create a blank solution. This section
what happens next: setting up the projects for building cross platform mobile apps.

Sharing Code
Refer to the Code Sharing Options document for a detailed description of how to implement code-sharing
across platforms.

Shared Projects

The simplest approach to sharing code files is use a Shared Project.

This method allows you to share the same code across different platform projects, and use compiler
directives to include different, platform-specific code paths.

Portable Class Libraries (PCL)

Historically a .NET project file (and the resulting assembly) has been targeted to a specific framework
version. This prevents the project or the assembly being shared by different frameworks.

A Portable Class Library (PCL) is a special type of project that can be used across disparate CLI platforms
such as Xamarin.iOS and Xamarin.Android, as well as WPF, Universal Windows Platform, and Xbox. The
library can only utilize a subset of the complete .NET framework, limited by the platforms being targeted.

You can read more about Xamarin's support for Portable Class Libraries and follow the instructions there to
see how the TaskyPortable sample works.

.NET Standard
Introduced in 2016, .NET Standard projects provide an easy way to share code across platforms,
producing assemblies that can be used across Windows, Xamarin platforms (iOS, Android, Mac), and
Linux.

.NET Standard libraries can be created and used like PCLs, except that the APIs available in each version
(from 1.0 to 1.6) are more easily discovered and each version is backwards-compatible with lower version
numbers.

Populating the Solution


Regardless of which method is used to share code, the overall solution structure should implement a
layered architecture that encourages code sharing. The Xamarin approach is to group code into two project
types:

Core project – Write re-usable code in one place, to be shared across different platforms. Use the
principles of encapsulation to hide implementation details wherever possible.

Platform-specific application projects – Consume the re-usable code with as little coupling as
possible. Platform-specific features are added at this level, built on components exposed in the Core
project.

Core Project

Shared code projects should only reference assemblies that are available across all platforms – ie. the
common framework namespaces like System, System.Core and System.Xml.

Shared projects should implement as much non-UI functionality as is possible, which could include the
following layers:

Data Layer – Code that takes care of physical data storage eg. SQLite-NET, an alternative database
like Realm.io or even XML files. The data layer classes are normally only used by the data access
layer.
Data Access Layer – Defines an API that supports the required data operations for the application’s
functionality, such as methods to access lists of data, individual data items and also create, edit, and
delete them.
Service Access Layer – An optional layer to provide cloud services to the application. Contains
code that accesses remote network resources (web services, image downloads, etc) and possibly
caching of the results.
Business Layer – Definition of the Model classes and the Façade or Manager classes that expose
functionality to the platform-specific applications.

Platform-Specific Application Projects

Platform-specific projects must reference the assemblies required to bind to each platform’s SDK
(Xamarin.iOS, Xamarin.Android, Xamarin.Mac, or Windows) as well as the Core shared code project.

The platform-specific projects should implement:

Application Layer – Platform specific functionality and binding/conversion between the Business
Layer objects and the user interface.
User Interface Layer – Screens, custom user-interface controls, presentation of validation logic.

Example

The application architecture is illustrated in this diagram:

This screenshot shows a solution setup with the shared Core project, iOS and Android application projects.
The Shared Project contains code relating to each of the architectural layers (Business, Service, Data and
Data Access code):
Project References
Project references reflect the dependencies for a project. Core projects limit their references to common
assemblies so that the code is easy to share. Platform-specific application projects reference the Shared
code, plus any other platform-specific assemblies they need to take advantage of the target platform.

The application projects each reference Shared project, and contain the user-interface code required to
present functionality to the user, as shown in these screenshots:

Specific examples of how projects should be structured are given in the case studies.

Adding Files

Build Action
It is important to set the correct build-action for certain file types. This list shows the build action for some
common file types:

All C# files – Build Action: Compile


Images in Xamarin.iOS & Windows – Build Action: Content
XIB and Storyboard files in Xamarin.iOS – Build Action: InterfaceDefinition
Images and AXML layouts in Android – Build Action: AndroidResource
XAML files in Windows projects – Build Action: Page
Xamarin.Forms XAML files – Build Action: EmbeddedResource

Generally the IDE will detect the file type and suggest the correct build action.

Case Sensitivity

Finally, remember that some platforms have case-sensitive file systems (eg. iOS and Android) so be sure
to use a consistent file naming standard and make sure that the file names you use in code match the
filesystem exactly. This is especially important for images and other resources that you reference in code.
Part 4 - Dealing with Multiple Platforms

Handling Platform Divergence & Features


Divergence isn’t just a ‘cross-platform’ problem; devices on the ‘same’ platform have
different capabilities (especially the wide variety of Android devices that are available). The
most obvious and basic is screen size, but other device attributes can vary and require an
application to check for certain capabilities and behave differently based on their presence
(or absence).

This means all applications need to deal with graceful degradation of functionality, or else
present an unattractive, lowest-common-denominator feature set. Xamarin’s deep
integration with the native SDKs of each platform allow applications to take advantage of
platform-specific functionality, so it makes sense to design apps to use those features.

See the Platform Capabilities documentation for an overview of how the platforms differ in
functionality.

Examples of Platform Divergence

Fundamental elements that exist across platforms

There are some characteristics of mobile applications that are universal. These are higher-
level concepts that are generally true of all devices and can therefore form the basis of your
application’s design:

Feature selection via tabs or menus


Lists of data and scrolling
Single views of data
Editing single views of data
Navigating back
When designing your high-level screen flow you can base a common user experience on
these concepts.

platform-specific attributes

In addition to the basic elements that exist on all platforms, you will need to address key
platform differences in your design. You may need to consider (and write code specifically to
handle) these differences:

Screen sizes – Some platforms (like iOS and earlier Windows Phone versions) have
standardized screen sizes that are relatively simple to target. Android devices have a
large variety of screen dimensions, which require more effort to support in your
application.
Navigation metaphors – Differ across platforms (eg. hardware ‘back’ button,
Panorama UI control) and within platforms (Android 2 and 4, iPhone vs iPad).
Keyboards – Some Android devices have physical keyboards while others only have
a software keyboard. Code that detects when a soft-keyboard is obscuring part of the
screen needs to be sensitive to these differences.
Touch and gestures – Operating system support for gesture recognition varies,
especially in older versions of each operating system. Earlier versions of Android have
very limited support for touch operations, meaning that supporting older devices may
require separate code

Push notifications – There are different capabilities/implementations on each


platform (eg. Live Tiles on Windows).

Device-specific features

Determine what the minimum features required for the application must be; or when decide
what additional features to take advantage of on each platform. Code will be required to
detect features and disable functionality or offer alternatives (eg. an alternative to geo-
location could be to let the user type a location or choose from a map):

Camera – Functionality differs across devices: some devices don’t have a camera,
others have both front- and rear-facing cameras. Some cameras are capable of video
recording.
Geo-location & maps – Support for GPS or Wi-Fi location is not present on all
devices. Apps also need to cater for the varying levels of accuracy that’s supported by
each method.
Accelerometer, gyroscope and compass – These features are often found in only a
selection of devices on each platform, so apps almost always need to provide a
fallback when the hardware isn’t supported.
Twitter and Facebook – only ‘built-in’ on iOS5 and iOS6 respectively. On earlier
versions and other platforms you will need to provide your own authentication
functions and interface directly with each services’ API.

Near Field Communications (NFC) – Only on (some) Android phones (at time of
writing).

Dealing with Platform Divergence

There are two different approaches to supporting multiple platforms from the same code-
base, each with its own set of benefits and disadvantages.

Platform Abstraction – Business Façade pattern, provides a unified access across


platforms and abstracts the particular platform implementations into a single, unified
API.

Divergent Implementation – Invocation of specific platform features via divergent


implementations via architectural tools such as interfaces and inheritance or
conditional compilation.

Platform Abstraction

Class Abstraction

Using either interfaces or base classes defined in the shared code and implemented or
extended in platform-specific projects. Writing and extending shared code with class
abstractions is particularly suited to Portable Class Libraries because they have a limited
subset of the framework available to them and cannot contain compiler directives to support
platform-specific code branches.

Interfaces

Using interfaces allows you to implement platform-specific classes that can still be passed
into your shared libraries to take advantage of common code.

The interface is defined in the shared code, and passed into the shared library as a
parameter or property.

The platform-specific applications can then implement the interface and still take advantage
of shared code to ‘process’ it.

Advantages

The implementation can contain platform-specific code and even reference platform-specific
external libraries.

Disadvantages

Having to create and pass implementations into the shared code. If the interface is used
deep within the shared code then it ends up being passed through multiple method
parameters or otherwise pushed down through the call chain. If the shared code uses lots of
different interfaces then they must all be created and set in the shared code somewhere.

Inheritance

The shared code could implement abstract or virtual classes that could be extended in one
or more platform-specific projects. This is similar to using interfaces but with some behavior
already implemented. There are different viewpoints on whether interfaces or inheritance are
a better design choice: in particular because C# only allows single inheritance it can dictate
the way your APIs can be designed going forward. Use inheritance with caution.

The advantages and disadvantages of interfaces apply equally to inheritance, with the
additional advantage that the base class can contain some implementation code (perhaps
an entire platform agnostic implementation that can be optionally extended).

Xamarin.Forms

See the Xamarin.Forms documentation.

Plug-in Cross-Platform Functionality

You can also extend cross-platform apps in a consistent way using plugins.

Linked from our plugins github, most plugins are open-source projects (typically available for
installation via Nuget) that help you implement a variety of platform-specific functionality from
battery status to settings with a common API that is easy to consume in Xamarin Platform
and Xamarin.Forms apps.

Other Cross-Platform Libraries

There are a number of 3rd party libraries available that provide cross-platform functionality:

MvvmCross - https://github.com/slodge/MvvmCross/
Vernacular (for localization) - https://github.com/rdio/vernacular/
MonoGame (for XNA games) - http://monogame.codeplex.com/

NGraphics - NGraphics and its precursor


https://github.com/praeclarum/CrossGraphics

Divergent Implementation

Conditional Compilation

There are some situations where your shared code will still need to work differently on each
platform, possibly accessing classes or features that behave differently. Conditional
compilation works best with Shared Asset Projects, where the same source file is being
referenced in multiple projects that have different symbols defined.

Xamarin projects always define __MOBILE__ which is true for both iOS and Android
application projects (note the double-underscore pre- and post-fix on these symbols).

#if __MOBILE__
// Xamarin iOS or Android-specific code
#endif

iOS

Xamarin.iOS defines __IOS__ which you can use to detect iOS devices.

#if __IOS__
// iOS-specific code
#endif

There are also Watch- and TV-specific symbols:

#if __TVOS__
// tv-specific stuff
#endif

#if __WATCHOS__
// watch-specific stuff
#endif

Android

Code that should only be compiled into Xamarin.Android applications can use the following

#if __ANDROID__
// Android-specific code
#endif

Each API version also defines a new compiler directive, so code like this will let you add
features if newer APIs are targeted. Each API level includes all the ‘lower’ level symbols.
This feature is not really useful for supporting multiple platforms; typically the __ANDROID__
symbol will be sufficient.

#if __ANDROID_11__
// code that should only run on Android 3.0 Honeycomb or newer
#endif

Mac

There is not currently a built-in symbol for Xamarin.Mac, but you can add your own in the
Mac app project Options > Build > Compiler in the Define symbols box, or edit the
.csproj file and add there (for example __MAC__)

<PropertyGroup><DefineConstants>__MAC__;$(DefineConstants)
</DefineConstants></PropertyGroup>

Windows Phone

Windows Phone apps defines two symbols – WINDOWS_PHONE and SILVERLIGHT – that
can be used to target code to the platform. These don't have the underscores surrounding
them like the Xamarin platform symbols do.

Using Conditional Compilation

A simple case-study example of conditional compilation is setting the file location for the
SQLite database file. The three platforms have slightly different requirements for specifying
the file location:

iOS – Apple prefers non-user data to be placed in a specific location (the Library
directory), but there is no system constant for this directory. Platform-specific code is
required to build the correct path.
Android – The system path returned by Environment.SpecialFolder.Personal
is an acceptable location to store the database file.
Windows Phone – The isolated storage mechanism does not allow a full path to be
specified, just a relative path and filename.
Universal Windows Platform – Uses Windows.Storage APIs.

The following code uses conditional compilation to ensure the DatabaseFilePath is


correct for each platform:

public static string DatabaseFilePath {


get {
var filename = "TodoDatabase.db3";
#if SILVERLIGHT
// Windows Phone 8
var path = filename;
#else

#if __ANDROID__
string libraryPath =
Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
#if __IOS__
// we need to put in /Library/ on iOS5.1 to meet Apple's
iCloud terms
// (they don't want non-user-generated data in Documents)
string documentsPath = Environment.GetFolderPath
(Environment.SpecialFolder.Personal); // Documents folder
string libraryPath = Path.Combine (documentsPath, "..",
"Library");
#else
// UWP
string libraryPath =
Windows.Storage.ApplicationData.Current.LocalFolder.Path;
#endif
#endif
var path = Path.Combine (libraryPath, filename);
#endif
return path;
}

The result is a class that can be built and used on all platforms, placing the SQLite database
file in a different location on each platform.
Part 5 - Practical Code Sharing Strategies
This section gives examples of how to share code for common application scenarios.

Data Layer
The data layer consists of a storage engine and methods to read and write information. For
performance, flexibility and cross-platform compatibility the SQLite database engine is
recommended for Xamarin cross-platform applications. It runs on a wide variety of platforms
including Windows, Android, iOS and Mac.

SQLite

SQLite is an open-source database implementation. The source and documentation can be


found at SQLite.org. SQLite support is available on each mobile platform:

iOS – Built in to the operating system.


Android – Built in to the operating system since Android 2.2 (API Level 10).
Windows – See the SQLite for Universal Windows Platform extension.

Even with the database engine available on all platforms, the native methods to access the
database are different. Both iOS and Android offer built-in APIs to access SQLite that could
be used from Xamarin.iOS or Xamarin.Android, however using the native SDK methods
offers no ability to share code (other than perhaps the SQL queries themselves, assuming
they’re stored as strings). For details about native database functionality search for
CoreData in iOS or Android’s SQLiteOpenHelper class; because these options are not
cross-platform they are beyond the scope of this document.

ADO.NET

Both Xamarin.iOS and Xamarin.Android support System.Data and Mono.Data.Sqlite


(see the Xamarin.iOS documentation for more info). Using these namespaces allows you to
write ADO.NET code that works on both platforms. Edit the project’s references to include
System.Data.dll and Mono.Data.Sqlite.dll and add these using statements to your
code:

using System.Data;
using Mono.Data.Sqlite;

Then the following sample code will work:

string dbPath = Path.Combine (


Environment.GetFolderPath
(Environment.SpecialFolder.Personal),
"items.db3");
bool exists = File.Exists (dbPath);
if (!exists)
SqliteConnection.CreateFile (dbPath);
var connection = new SqliteConnection ("Data Source=" + dbPath);
connection.Open ();
if (!exists) {
// This is the first time the app has run and/or that we need
the DB.
// Copy a "template" DB from your assets, or programmatically
create one like this:
var commands = new[]{
"CREATE TABLE [Items] (Key ntext, Value ntext);",
"INSERT INTO [Items] ([Key], [Value]) VALUES ('sample',
'text')"
};
foreach (var command in commands) {
using (var c = connection.CreateCommand ()) {
c.CommandText = command;
c.ExecuteNonQuery ();
}
}
}
// use `connection`... here, we'll just append the contents to a
TextView
using (var contents = connection.CreateCommand ()) {
contents.CommandText = "SELECT [Key], [Value] from [Items]";
var r = contents.ExecuteReader ();
while (r.Read ())
Console.Write("\n\tKey={0}; Value={1}",
r ["Key"].ToString (),
r ["Value"].ToString ());
}
connection.Close ();

Real-world implementations of ADO.NET would obviously be split across different methods


and classes (this example is for demonstration purposes only).

SQLite-NET – Cross-Platform ORM

An ORM (or Object-Relational Mapper) attempts to simplify storage of data modeled in


classes. Rather than manually writing SQL queries that CREATE TABLEs or SELECT,
INSERT and DELETE data that is manually extracted from class fields and properties, an
ORM adds a layer of code that does that for you. Using reflection to examine the structure of
your classes, an ORM can automatically create tables and columns that match a class and
generate queries to read and write the data. This allows application code to simply send and
retrieve object instances to the ORM, which takes care of all the SQL operations under the
hood.

SQLite-NET acts as a simple ORM that will allow you to save and retrieve your classes in
SQLite. It hides the complexity of cross platform SQLite access with a combination of
compiler directives and other tricks.

Features of SQLite-NET:
Tables are defined by adding attributes to Model classes.
A database instance is represented by a subclass of SQLiteConnection , the main
class in the SQLite-Net library.
Data can be inserted, queried and deleted using objects. No SQL statements are
required (although you can write SQL statements if required).
Basic Linq queries can be performed on the collections returned by SQLite-NET.

The source code and documentation for SQLite-NET is available at SQLite-Net on github
and has been implemented in both case-studies. A simple example of SQLite-NET code
(from the Tasky Pro case study) is shown below.

First, the TodoItem class uses attributes to define a field to be a database primary key:

public class TodoItem : IBusinessEntity


{
public TodoItem () {}
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public bool Done { get; set; }
}

This allows a TodoItem table to be created with the following line of code (and no SQL
statements) on an SQLiteConnection instance:

CreateTable<TodoItem> ();

Data in the table can also be manipulated with other methods on the SQLiteConnection
(again, without requiring SQL statements):

Insert (TodoItem); // 'task' is an instance with data populated in


its properties
Update (TodoItem); // Primary Key field must be populated for Update
to work
Table<TodoItem>.ToList(); // returns all rows in a collection

See the case study source code for complete examples.

File Access
File access is certain to be a key part of any application. Common examples of files that
might be part of an application include:

SQLite database files.


User-generated data (text, images, sound, video).
Downloaded data for caching (images, html or PDF files).

System.IO Direct Access

Both Xamarin.iOS and Xamarin.Android allow file system access using classes in the
System.IO namespace.

Each platform does have different access restrictions that must be taken into consideration:

iOS applications run in a sandbox with very restricted file-system access. Apple further
dictates how you should use the file system by specifying certain locations that are
backed-up (and others that are not). Refer to the Working with the File System in
Xamarin.iOS guide for more details.
Android also restricts access to certain directories related to the application, but it also
supports external media (eg. SD cards) and accessing shared data.
Windows Phone 8 (Silverlight) do not allow direct file access – files can only be
manipulated using IsolatedStorage.
Windows 8.1 WinRT and Windows 10 UWP projects only offer asynchronous file
operations via Windows.Storage APIs, which are different from the other platforms.

Example for iOS and Android

A trivial example that writes and reads a text file is shown below. Using
Environment.GetFolderPath allows the same code to run on iOS and Android, which
each return a valid directory based on their filesystem conventions.

string filePath = Path.Combine (


Environment.GetFolderPath
(Environment.SpecialFolder.Personal),
"MyFile.txt");
System.IO.File.WriteAllText (filePath, "Contents of text file");
Console.WriteLine (System.IO.ReadAllText (filePath));

Refer to the Xamarin.iOS Working with the File System document for more information on
iOS-specific filesystem functionality. When writing cross-platform file access code,
remember that some file-systems are case-sensitive and have different directory separators.
It is good practice to always use the same casing for filenames and the Path.Combine()
method when constructing file or directory paths.

Windows.Storage for Windows 8 and Windows 10

The Creating Mobile Apps with Xamarin.Forms book Chapter 20. Async and File I/O
includes samples for Windows 8.1 and Windows 10.

Using a DependencyService it's possible to read and file files on these platforms using
the supported APIs:

StorageFolder localFolder = ApplicationData.Current.LocalFolder;


IStorageFile storageFile = await
localFolder.CreateFileAsync("MyFile.txt",

CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(storageFile, "Contents of text file");

Refer to the book chapter for more details.

Isolated Storage on Windows Phone 7 & 8 (Silverlight)


Isolated Storage is a common API for saving and loading files across all iOS, Android, and
older Windows Phone platforms.

It is the default mechanism for file access in Windows Phone (Silverlight) that has been
implemented in Xamarin.iOS and Xamarin.Android to allow common file-access code to be
written. The System.IO.IsolatedStorage class can be referenced across all three
platforms in a Shared Project.

Refer to the Isolated Storage Overview for Windows Phone for more information.

The Isolated Storage APIs are not available in Portable Class Libraries. One alternative for
PCL is the PCLStorage NuGet

Cross-platform file access in PCLs

There is also a PCL-compatible Nuget – PCLStorage – that facilities cross-platform file


access for Xamarin-supported platforms and the latest Windows APIs.

Network Operations
Most mobile applications will have networking component, for example:

Downloading images, video and audio (eg. thumbnails, photos, music).


Downloading documents (eg. HTML, PDF).
Uploading user data (such as photos or text).
Accessing web services or 3rd party APIs (including SOAP, XML or JSON).

The .NET Framework provides a few different classes for accessing network resources:
HttpClient, WebClient, and HttpWebRequest.

HttpClient

The HttpClient class in the System.Net.Http namespace is available in Xamarin.iOS,


Xamarin.Android, and most Windows platforms. There is a Microsoft HTTP Client Library
Nuget that can be used to bring this API into Portable Class Libraries (and Windows Phone
8 Silverlight).

var client = new HttpClient();


var request = new HttpRequestMessage(HttpMethod.Get,
"https://xamarin.com");
var response = await myClient.SendAsync(request);

WebClient

The WebClient class provides a simple API to retrieve remote data from remote servers.

Universal Windows Platofrm operations must be async, even though Xamarin.iOS and
Xamarin.Android support synchronous operations (which can be done on background
threads).

The code for a simple asychronous WebClient operation is:

var webClient = new WebClient ();


webClient.DownloadStringCompleted += (sender, e) =>
{
var resultString = e.Result;
// do something with downloaded string, do UI interaction on
main thread
};
webClient.Encoding = System.Text.Encoding.UTF8;
webClient.DownloadStringAsync (new Uri ("http://some-
server.com/file.xml"));

WebClient also has DownloadFileCompleted and DownloadFileAsync for retrieving


binary data.

HttpWebRequest
HttpWebRequest offers more customization than WebClient and as a result requires
more code to use.

The code for a simple synchronous HttpWebRequest operation is:

var request = HttpWebRequest.Create(@"http://some-


server.com/file.xml ");
request.ContentType = "text/xml";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as
HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
Console.WriteLine("Error fetching data. Server returned
status code: {0}", response.StatusCode);
using (StreamReader reader = new
StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
// do something with downloaded string, do UI interaction on
main thread
}
}

There is an example in our Web Services documentation.

Reachability

Mobile devices operate under a variety of network conditions from fast Wi-Fi or 4G
connections to poor reception areas and slow EDGE data links. Because of this, it is good
practice to detect whether the network is available and if so, what type of network is
available, before attempting to connect to remote servers.

Actions a mobile app might take in these situations include:


If the network is unavailable, advise the user. If they have manually disabled it (eg.
Airplane mode or turning off Wi-Fi) then they can resolve the issue.
If the connection is 3G, applications may behave differently (for example, Apple does
not allow apps larger than 20Mb to be downloaded over 3G). Applications could use
this information to warn the user about excessive download times when retrieving
large files.
Even if the network is available, it is good practice to verify connectivity with the target
server before initiating other requests. This will prevent the app’s network operations
from timing out repeatedly and also allow a more informative error message to be
displayed to the user.

There is a Xamarin.iOS sample available (which is based on Apple’s Reachability sample


code ) to help detect network availability.

WebServices
See our documentation on Working with Web Services, which covers accessing REST,
SOAP and WCF endpoints using Xamarin.iOS. It is possible to hand-craft web service
requests and parse the responses, however there are libraries available to make this much
simpler, including Azure, RestSharp, and ServiceStack. Even basic WCF operations can be
accessed in Xamarin apps.

Azure

Microsoft Azure is a cloud platform that provides a wide variety of services for mobile apps,
including data storage and sync, and push notifications.

Visit azure.microsoft.com to try it for free.

RestSharp

RestSharp is a .NET library that can be included in mobile applications to provide a REST
client that simplifies access to web services. It helps by providing a simple API to request
data and parse the REST response. RestSharp can be useful

The RestSharp website contains documentation on how to implement a REST client using
RestSharp. RestSharp provides Xamarin.iOS and Xamarin.Android examples on github.

There is also a Xamarin.iOS code snippet in our Web Services documentation.

ServiceStack

Unlike RestSharp, ServiceStack is both a server-side solution to host a web service as well
as a client library that can be implemented in mobile applications to access those services.

The ServiceStack website explains the purpose of the project and links to document and
code samples. The examples include a complete server-side implementation of a web
service as well as various client-side applications that can access it.

There is a Xamarin.iOS example on the ServiceStack website, and a code snippet in our
Web Services documentation.

WCF

Xamarin tools can help you consume some Windows Communication Foundation (WCF)
services. In general, Xamarin supports the same client-side subset of WCF that ships with
the Silverlight runtime. This includes the most common encoding and protocol
implementations of WCF: text-encoded SOAP messages over the HTTP transport protocol
using the BasicHttpBinding.

Due to the size and complexity of the WCF framework, there may be current and future
service implementations that will fall outside of the scope supported by Xamarin’s client-
subset domain. In addition, WCF support requires the use of tools only available in a
Windows environment to generate the proxy.

Threading
Application responsiveness is important for mobile applications – users expect applications
to load and perform quickly. A ‘frozen’ screen that stops accepting user-input will appear to
indicate the application has crashed, so it is important not to tie up the UI thread with long-
running blocking calls such as network requests or slow local operations (such as unzipping
a file). In particular the startup process should not contain long-running tasks – all mobile
platforms will kill an app that takes too long to load.

This means your user interface should implement a ‘progress indicator’ or otherwise
‘useable’ UI that is quick to display, and asynchronous tasks to perform background
operations. Executing background tasks requires the use of threads, which means the
background tasks needs a way to communicate back to the main thread to indicate progress
or when they have completed.

Parallel Task Library

Tasks created with the Parallel Task Library can run asynchronously and return on their
calling thread, making them very useful for triggering long-running operations without
blocking the user interface.

A simple parallel task operation might look like this:

using System.Threading.Tasks;
void MainThreadMethod ()
{
Task.Factory.StartNew (() => wc.DownloadString
("http://...")).ContinueWith (
t => label.Text = t.Result,
TaskScheduler.FromCurrentSynchronizationContext()
);
}

The key is TaskScheduler.FromCurrentSynchronizationContext() which will


reuse the SynchronizationContext.Current of the thread calling the method (here the main
thread that is running MainThreadMethod) as a way to marshal back calls to that thread.
This means if the method is called on the UI thread, it will run the ContinueWith operation
back on the UI thread.

If the code is starting tasks from other threads, use the following pattern to create a
reference to the UI thread and the task can still call back to it:

static Context uiContext =


TaskScheduler.FromCurrentSynchronizationContext();

Invoking on the UI Thread

For code that doesn’t utilize the Parallel Task Library, each platform has its own syntax for
marshaling operations back to the UI thread:

iOS – owner.BeginInvokeOnMainThread(new NSAction(action))


Android – owner.RunOnUiThread(action)
Xamarin.Forms – Device.BeginInvokeOnMainThread(action)
Windows – Deployment.Current.Dispatcher.BeginInvoke(action)

Both the iOS and Android syntax requires a ‘context’ class to be available which means the
code needs to pass this object into any methods that require a callback on the UI thread.

To make UI thread calls in shared code, follow the IDispatchOnUIThread example (courtesy
of @follesoe). Declare and program to an IDispatchOnUIThread interface in the shared
code and then implement the platform-specific classes as shown here:

// program to the interface in shared code


public interface IDispatchOnUIThread {
void Invoke (Action action);
}
// iOS
public class DispatchAdapter : IDispatchOnUIThread {
public readonly NSObject owner;
public DispatchAdapter (NSObject owner) {
this.owner = owner;
}
public void Invoke (Action action) {
owner.BeginInvokeOnMainThread(new NSAction(action));
}
}
// Android
public class DispatchAdapter : IDispatchOnUIThread {
public readonly Activity owner;
public DispatchAdapter (Activity owner) {
this.owner = owner;
}
public void Invoke (Action action) {
owner.RunOnUiThread(action);
}
}
// WP7
public class DispatchAdapter : IDispatchOnUIThread {
public void Invoke (Action action) {
Deployment.Current.Dispatcher.BeginInvoke(action);
}
}

Xamarin.Forms developers should use Device.BeginInvokeOnMainThread in common


code (Shared Projects or PCL).

Platform and Device Capabilities and


Degradation
Further specific examples of dealing with different capabilities are given in the Platform
Capabilities documentation. It deals with detecting different capabilities and how to gracefully
degrade an application to provide a good user experience, even when the app can’t operate
to its full potential.
Part 6 - Testing and App Store Approvals

Testing
Many apps (even Android apps, on some stores) will have to pass an approval process
before they are published; so testing is critical to ensure your app reaches the market (let
alone succeeds with your customers). Testing can take many forms, from developer-level
unit testing to managing beta testing across a wide variety of hardware.

Test on All Platforms

There are slight differences between what .NET supports on Windows phone, tablet, and
desktop devices, as well as limitations on iOS that prevent dynamic code to be generated on
the fly. Either plan on testing the code on multiple platforms as you develop it, or schedule
time to refactor and update the model part of your application at the end of the project.

It is always good practice to use the simulator/emulator to test multiple versions of the
operating system and also different device capabilities/configurations.

You should also test on as many different physical hardware devices as you can.

Devices in cloud

The mobile phone and tablet ecosystem is growing all the time, making it impossible to test
on the ever-increasing number of devices available. To solve this problem a number of
services offer the ability to remotely control many different devices so that applications can
be installed and tested without needing to directly invest in lots of hardware.

App Center Test offers an easy way to test iOS and Android applications on hundreds of
different devices.

Test Management
When testing applications within your organization or managing a beta program with external
users, there are two challenges:

Distribution – Managing the provisioning process (especially for iOS devices) and
getting updated versions of software to the testers.
Feedback – Collecting information about application usage, and detailed information
on any errors that may occur.

There are a number of services help to address these issues, by providing infrastructure that
is built into your application to collect and report on usage and errors, and also streamlining
the provisioning process to help sign-up and manage testers and their devices.

The Xamarin Insights Preview offers a solution to the second part of this issue, providing
crash reporting and sophisticated application usage information.

Test Automation

Xamarin UITest can be used to create automated user interface test scripts that can be run
locally or uploaded to App Center Test.

Unit Testing

Touch.Unit

Xamarin.iOS includes a unit-testing framework called Touch.Unit which follows the


JUnit/NUnit style writing tests.

Refer to our Unit Testing with Xamarin.iOS documentation for details on writing tests and
running Touch.Unit.

Andr.Unit

There is an open-source equivalent of Touch.Unit for Android called Andr.Unit. You can
download it from github and read about the tool on @spouliot's blog.
Windows Phone

Here are some links to help setup unit testing for Windows Phone:

http://www.jeff.wilcox.name/2010/05/sl3-utf-bits/
http://www.jeff.wilcox.name/2011/06/updated-ut-mango-bits/
http://www.smartypantscoding.com/a-cheat-sheet-for-unit-testing-silverlight-apps-on-
windows-phone-7
http://mobile.dzone.com/articles/unit-testing-your-windows

App Store Approvals


Apple and Microsoft operate the only store on their platforms: the App Store and
Marketplace respectively. Both lock-down their devices and implement a rigorous app review
process to control the quality of applications available to download. Android’s open nature
means there are a number of store options ranging from Google’s Play, which is widely
available and has no review process, to Amazon’s Appstore for Android and hardware-
specific efforts like Samsung Apps which have more limited distribution and implement an
approval process.

Waiting for an app to be reviewed can be very stressful - business pressures often mean
applications are submitted for approval with very little margin for error prior to a “targeted”
launch date. The process itself can take up to two weeks and isn’t necessarily transparent:
there is limited feedback on the progress of your application until it is finally rejected or
approved. Rejection can mean missing a marketing window of opportunity, especially if it
happens more than once, and weeks pass between your original launch date and when the
app is finally approved.

Be prepared

The first piece of advice: plan your app’s launch well in advance and make allowances for a
possible rejection and re-submission. Each store requires you to create an account before
submitting your app - do this as early as possible. While Google Play’s signup only takes a
few minutes if your apps are free, the process gets a lot more involved if you are selling
them and need to supply banking and tax information. Apple and Microsoft’s processes are
both much more involved than Google’s, it could take a week or more to get your account
approved so factor this time into your launch plans.

Once your account has been approved, you’re ready to submit an app. The actual process
to submit apps is covered in the following documentation:

Publishing to Apple's iOS App Store


Preparing an app for Google Play
Windows developers should visit the Windows Dev Center to read about submitting
their apps.

The remainder of this section discusses things you should take into consideration to ensure
your app is approved without any hiccups.

Quality

It sounds obvious, but applications will often get rejected because they do not meet a certain
level of quality: after all, this is the reason why the curated stores have an approval process
in the first place!

Crashes are a common reason for rejection. If it’s too easy to make your app crash, it’s
guaranteed to be rejected. Most developers don’t submit their apps with the expectation that
they’ll crash, yet they often do. Test your app thoroughly before submitting it, focusing not
just on making sure everything works but also that you handle common mobile error
scenarios such as network problems and resource constraints like memory or storage
space. Use both the simulator and physical devices to test - regardless of how well code
runs in a simulator, only a device can demonstrate an app’s real performance. Use as many
different devices as you can find, and enlist a team of beta-testers if you can - third-party
services can help manage beta distribution and feedback.

All mobile operating systems will kill an application that doesn’t start quickly enough. The
length of time allowed varies, but in general apps should aim to be responsive in a few
seconds and use background tasks to do any work that would take longer. Apps that take
too long to load, or are not responsive enough in regular use will be rejected. Always provide
user feedback when something is happening in the background, or the app will appear to
have crashed and once again, get rejected.

Check Your Edge Cases

A common trap for developers is failing to address edge-cases, especially those that require
re-configuring their simulator or device to test properly. It can be easy to forget that not every
customer is going to “Allow” your app to access their location because after the developer
has accepted the request once, they’ll never be prompted again. Permissions and network
usage are specifically focussed on during the approval process, which means a small
oversight in these areas can result in rejection.

The following list is a good starting point for checking edge-cases that might have been
missed:

Customers may ‘deny’ access to services – especially in iOS, access to data such
as geo-location information is only provided if the user grants permission to your
application. Application testers should frequently re-install the application in its initial
state and disallow any permission requests to ensure the application behaves
appropriately. Toggle permission on and off to verify correct behavior as customers
change their mind.
Customers are everywhere – don’t assume that an app will only be used in the city
or country where it was developed! Code that works with GPS coordinates, date and
time values and currencies can all be affected by the customer’s location and locale
settings. All platforms offer a simulator that let you specify different locations and
locales - use it to test locations in other hemispheres and with cultures that format
dates and currencies differently. Latitude and longitude values can be positive or
negative, the decimal separator could be a period or a comma, and dates can be
formatted a myriad of ways - deal with it!
Slow network connections – app developers often work in an ‘ideal world’ of fast,
always working network connectivity, which obviously isn’t the case in the real world.
Testing with slow network connectivity (such as a poor 3G connection) as well as with
no network access is critical to ensuring you don’t ship a buggy app. The approval
process will always include a test with the device in airplane mode, so ensure that you
have tested that for yourself.

Hardware varies – remember to test on the oldest, slowest hardware that you plan to
support. There are two aspects that might affect your app: performance, which might
be unusable on an older device, and support for hardware features such as a camera,
microphone, GPS, gyroscope or other optional component. Applications should
degrade gracefully (and not crash) when a component is unavailable.

Guidelines are more than just a ‘guide’

Apple is famous for being strict about adherence to their Human Interface Guidelines as one
of the key strengths of their platform is consistency (and the perceived increase in usability).
Microsoft has taken a similar approach with Windows applications implementing the Metro-
style UI. The approval process for both platforms will involve your app being evaluated for its
adherence to the relevant design philosophy.

That isn’t to say that user interface innovation isn’t supported or encouraged, but there are
certain things you “just shouldn’t do” or your app will be rejected.

On iOS, this includes misusing built-in icons or using other well established metaphors in a
non-consistent manner; for example using the ‘compose’ icon for anything other than
creating new content.

Windows developers should be similarly careful; a common mistake is failing to properly


support the hardware Back button according to Microsoft’s guidelines.

Encourage your designers to read and follow the design guidelines for each platform.

Implementing Platform-Specific Features

Things are a little stricter when it comes to implementing platform-specific services,


especially on iOS. To avoid automatic-rejection by Apple, there are some rules to follow with
the following iOS features:

In-App purchases – Applications must NOT implement external payment


mechanisms for digital products including in-game currency, application features,
magazine subscriptions and a lot more. iOS apps must use Apple’s iTunes-based
service for this kind of functionality. There is a loophole - apps like the Kindle Reader
and some subscription-based apps let you purchase content elsewhere that gets
attached to an “account” which you can then access via the app, however in this case
the app must not contain links or references to the out-of-app purchase process (or,
once again, it’ll be rejected).
iCloud backup – With the advent of iCloud, Apple’s reviewers are much more strict
regarding how apps use storage (to ensure customer’s remote backup experience is
pleasant). Apps that waste backup-able storage space may get rejected, so use the
Cache folder appropriately and follow Apple’s other storage-related guidelines.
Newsstand – Newspaper and magazine apps are a great fit for Apple’s Newsstand,
however apps must implement at least one auto-renewing subscription and support
background downloading to be approved.

Maps – It’s increasingly common to add overlays and other features to mobile maps,
however be careful not to obscure the map ‘credits’ information (such as the Google
logo in iOS5) as doing so will result in rejection.

Manage Your Metadata

In addition to the obvious technical issues that can result in an application being rejected,
there are some more subtle aspects of your submission that could result in rejection,
especially around the metadata (description, keywords and marketing images) that you
submit with your application for display within the App Store or Marketplace.

Imagery – Follow the platform’s guidelines for application icons and store pictures.
Don’t use trademarked images, we’ve seen apps get rejected because their icons
featured a drawing of an iPhone!
Trademarks – Avoid using any trademarks other than your own. Apps have been
denied for mentioning trademarks in the app description or even in the keywords on
Apple’s App Store.
Description – Do not use the word ‘beta’ or in any way indicate that the app is not
ready for prime time. Don’t mention other mobile platforms (even if your app is cross-
platform). Most importantly, make sure the app does exactly what you say it does. If
you list a bunch of features in your description, it had better be obvious how to use
each of those features or you'll get a "feature mentioned in the application's description
is not implemented" rejection.

Put as much effort into the application’s metadata as into development and testing.
Applications DO get rejected for minor infringements in the metadata so it is worthwhile
taking the time to get it right.

App Stores: Not For Everyone

The primary focus of the stores on each platform is consumer distribution - the ability to
reach as many customers as possible. However not all applications are targeted at
consumers, there is a rapidly growing base of in-house and extranet-like applications that
require limited distribution to employees, suppliers or customers. These apps aren’t “for sale”
and don’t need approval, since the developer controls distribution to a closed group of users.
Support for this type of deployment varies by platform.

Android offers the most flexibility in this regard: applications can be installed directly from a
URL or email attachment (so long as the device’s configuration allows it). This means it is
trivial to create and distribute in-house corporate applications or publish applications to
specific customers or suppliers.

Apple provides an in-house deployment option to developers enrolled in the iOS Developer
Enterprise Program, which bypasses the App Store approval process and allows companies
to distribute in-house apps to their employees. Unfortunately this license does not address
the need for extranet-like app distribution to other closed groups of customers or suppliers.
Enterprise (and Ad-Hoc) Deployment

App Store Summary


The review process can be daunting, but like the rest of the development lifecycle you can
help ensure success with some planning and attention to detail. It all comes down to a few
simple steps: read and understand the user interface guidelines you must adhere to, follow
the rules if you are implementing platform-specific features, test thoroughly (then test some
more) and finally make sure your application metadata is correct before you submit.

One last word of advice to developers publishing on Google Play: the lack of approval
process may seem like it makes your job easier - but your customers will be even more
demanding than a review team. Follow these guidelines as though your app could get
rejected, otherwise it will be your customers doing the rejecting.
Case Study: Tasky

Overview
Tasky Portable is a simple to-do list application. This document discusses how it was designed and built,
following the guidance of the Building Cross-Platform Applications document. The discussion covers the following
areas:

Design

This section describes a general approach for starting a new cross-platform mobile application project, such as
generating requirements, creating screen mockups and identifying key features of the code.

Common Code

Explains how a cross-platform database and business layer is constructed. A TaskItemManager class is written
to provide a simple ‘API’ that is accessed by the UI Layer. The implementation details of the common code are
encapsulated by the TaskItemManager and TaskItem classes that it returns. Each platform accesses
common code from a Portable Class Library(PCL)

Platform-Specific Applications

Tasky runs on iOS, Android and Windows Phone. Each platform-specific application implements a native user-
interface to do the following:

1. Display a list of tasks

2. Create, edit, save and delete tasks.

Design Process
It is advisable to create a of road-map for what you want to achieve before you start coding. This is especially
true for cross-platform development, where you are building functionality that will be exposed in multiple ways.
Starting with a clear idea of what you're building saves time and effort later in the development cycle.

Requirements

The first step in designing an application is to identify desired features. These can be high-level goals or detailed
use cases. Tasky has straightforward functional requirements:
View a list of tasks
Add, edit and delete tasks
Set a task’s status to ‘done’

You should consider your use of platform-specific features. Can Tasky take advantage of iOS geofencing or
Windows Phone Live Tiles? Even if you don't use platform-specific features in the first version, you should plan
ahead to make sure your business & data layers can accommodate them.

User Interface Design

Start with a high-level design that can be implemented across the target platforms. Take care to note platform-
specfic UI constraints. For example, a TabBarController in iOS can display more than five buttons, whereas
the Windows Phone equivalent can display up to four. Draw the screen-flow using the tool of your choice (paper
works).

Data Model

Knowing what data needs to be stored will help determine which persistence mechanism to use. See Cross-
Platform Data Access for information about the available storage mechanisms and help deciding between them.
For this project, we'll be using SQLite.NET.

Tasky needs to store three properties for each 'TaskItem':


Name – String
Notes – String

Done – Boolean

Core Functionality

Consider the API that the user interface will need to consume to meet the requirements. A to-do list requires the
following functions:

List all tasks – to display the main screen list of all available tasks
Get one task – when a task row is touched
Save one task – when a task is edited
Delete one task – when a task is deleted
Create empty task – when a new task is created

To achieve code reuse, this API should be implemented once in the Portable Class Library.

Implementation

Once the application design has been agreed upon, consider how it might be implemented as a cross-platform
application. This will become the application’s architecture. Following the guidance in the Building Cross-Platform
Applications document, the application code should be broken down into the following parts:

Common Code – a common project that contains re-useable code to store the task data; expose a Model
class and an API to manage the saving and loading of data.

Platform-specific Code – platform-specific projects that implement a native UI for each operating system,
utilizing the common code as the ‘back end’.
These two parts are described in the following sections.

Common (PCL) Code


Tasky Portable uses the Portable Class Library strategy for sharing common code. See the Sharing Code
Options document for a description of code-sharing options.

All common code, including the data access layer, database code and contracts, is placed in the library project.

The complete PCL project is illustrated below. All of the code in the portable library is compatible with each
targeted platform. When deployed, each native app will reference that library.

The class diagram below shows the classes grouped by layer. The SQLiteConnection class is boilerplate
code from the Sqlite-NET package. The rest of the classes are custom code for Tasky. The TaskItemManager
and TaskItem classes represent the API that is exposed to the platform-specific applications.
Using namespaces to separate the layers helps to manage references between each layer. The platform-specific
projects should only need to include a using statement for the Business Layer. The Data Access Layer and
Data Layer should be encapsulated by the API that is exposed by TaskItemManager in the Business Layer.

References

Portable class libraries need to be usable across multiple platforms, each with varying levels of support for
platform and framework features. Because of that, there are limitations on which packages and framework
libraries can be used. For example, Xamarin.iOS does not support the c# dynamic keyword, so a portable class
library can't use any package that depends on dynamic code, even though such code would work on Android.
Visual Studio for Mac will prevent you from adding incompatible packages and references, but you'll want to keep
limitations in mind to avoid surprises later on.

Note: You'll see that your projects reference framework libraries that you haven't used. These references are
included as part of the Xamarin project templates. When apps are compiled, the linking process will remove
unreferenced code, so even though System.Xml has been referenced, it will not be included in the final
application because we are not using any Xml functions.

Data Layer (DL)

The Data Layer contains the code that does the physical storage of data – whether to a database, flat files or
other mechanism. The Tasky data layer consists of two parts: the SQLite-NET library and the custom code added
to wire it up.

Tasky relies on the Sqlite-net nuget package (published by Frank Kreuger) to embed SQLite-NET code that
provides an Object-Relational Mapping (ORM) database interface. The TaskItemDatabase class inherits from
SQLiteConnection and adds the required Create, Read, Update, Delete (CRUD) methods to read and write
data to SQLite. It is a simple boilerplate implementation of generic CRUD methods that could be re-used in other
projects.

The TaskItemDatabase is a singleton, ensuring that all access occurs against the same instance. A lock is
used to prevent concurrent access from multiple threads.

SQLite on Windows Phone


While iOS and Android both ship with SQLite as part of the operating system, Windows Phone does not include a
compatible database engine. To share code across all three platforms a Windows phone-native version of SQLite
is required. See Working with a Local Database for more information about setting up your Windows Phone
project for Sqlite.

Using an Interface to Generalize Data Access

The Data Layer takes a dependency on BL.Contracts.IBusinessIdentity so that it can implement


abstract data access methods that require a primary key. Any Business Layer class that implements the interface
can then be persisted in the Data Layer.

The interface just specifies an integer property to act as the primary key:

public interface IBusinessEntity {


int ID { get; set; }
}

The base class implements the interface and adds the SQLite-NET attributes to mark it as an auto-incrementing
primary key. Any class in the Business Layer that implements this base class can then be persisted in the Data
Layer:

public abstract class BusinessEntityBase : IBusinessEntity {


public BusinessEntityBase () {}
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
}

An example of the generic methods in the Data Layer that use the interface is this GetItem<T> method:

public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()


{
lock (locker) {
return Table<T>().FirstOrDefault(x => x.ID == id);
}
}

Locking to prevent Concurrent Access

A lock is implemented within the TaskItemDatabase class to prevent concurrent access to the database. This
is to ensure concurrent access from different threads is serialized (otherwise a UI component might attempt to
read the database at the same time a background thread is updating it). An example of how the lock is
implemented is shown here:
static object locker = new object ();
public IEnumerable<T> GetItems<T> () where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return (from i in Table<T> () select i).ToList ();
}
}
public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return Table<T>().FirstOrDefault(x => x.ID == id);
}
}

Most of the Data Layer code could be re-used in other projects. The only application-specific code in the layer is
the CreateTable<TaskItem> call in the TaskItemDatabase constructor.

Data Access Layer (DAL)

The TaskItemRepository class encapsulates the data storage mechanism with a strongly-typed API that
allows TaskItem objects to be created, deleted, retrieved and updated.

Using Conditional Compilation

The class uses conditional compilation to set the file location - this is an example of implementing Platform
Divergence. The property that returns the path compiles to different code on each platform. The code and
platform-specific compiler directives are shown here:

public static string DatabaseFilePath {


get {
var sqliteFilename = "TaskDB.db3";
#if SILVERLIGHT
// Windows Phone expects a local path, not absolute
var path = sqliteFilename;
#else
#if __ANDROID__
// Just use whatever directory SpecialFolder.Personal returns
string libraryPath =
Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
// we need to put in /Library/ on iOS5.1+ to meet Apple's iCloud terms
// (they don't want non-user-generated data in Documents)
string documentsPath = Environment.GetFolderPath
(Environment.SpecialFolder.Personal); // Documents folder
string libraryPath = Path.Combine (documentsPath, "..", "Library"); //
Library folder
#endif
var path = Path.Combine (libraryPath, sqliteFilename);
#endif
return path;
}
}

Depending on the platform, the output will be “/Library/TaskDB.db3” for iOS, “/Documents/TaskDB.db3” for
Android or just “TaskDB.db3” for Windows Phone.

Business Layer (BL)

The Business Layer implements the Model classes and a Façade to manage them. In Tasky the Model is the
TaskItem class and TaskItemManager implements the Façade pattern to provide an API for managing
TaskItems.

Façade

TaskItemManager wraps the DAL.TaskItemRepository to provide the Get, Save and Delete methods that
will be referenced by the Application and UI Layers.

Business rules and logic would be placed here if required – for example any validation rules that must be
satisfied before an object is saved.

API for Platform-Specific Code

Once the common code has been written, the user interface must be built to collect and display the data exposed
by it. The TaskItemManager class implements the Façade pattern to provide a simple API for the application
code to access.

The code written in each platform-specific project will generally be tightly coupled to the native SDK of that
device, and only access the common code using the API defined by the TaskItemManager. This includes the
methods and business classes it exposes, such as TaskItem.

Images are not shared across platforms but added independently to each project. This is important because each
platform handles images differently, using different file names, directories and resolutions.

The remaining sections discuss the platform-specific implementation details of the Tasky UI.

iOS App
There are only a handful of classes required to implement the iOS Tasky application using the common PCL
project to store and retrieve data. The complete iOS Xamarin.iOS project is shown below:

The classes are shown in this diagram, grouped into layers.

References

The iOS app references the platform-specific SDK libraries – eg. Xamarin.iOS and MonoTouch.Dialog-1.

It must also reference the TaskyPortableLibrary PCL project. The references list is shown here:
The Application Layer and User Interface Layer are implemented in this project using these references.

Application Layer (AL)

The Application Layer contains platform-specific classes required to ‘bind’ the objects exposed by the PCL to the
UI. The iOS-specific application has two classes to help display tasks:

EditingSource – This class is used to bind lists of tasks to the user interface. Because
MonoTouch.Dialog was used for the Task list, we need to implement this helper to enable swipe-to-
delete functionality in the UITableView . Swipe-to-delete is common on iOS, but not Android or Windows
Phone, so the iOS specific project is the only one that implements it.
TaskDialog – This class is used to bind a single task to the UI. It uses the MonoTouch.Dialog Reflection
API to ‘wrap’ the TaskItem object with a class that contains the correct attributes to allow the input screen
to be correctly formatted.

The TaskDialog class uses MonoTouch.Dialog attributes to create a screen based on a class’s properties.
The class looks like this:

public class TaskDialog {


public TaskDialog (TaskItem task)
{
Name = task.Name;
Notes = task.Notes;
Done = task.Done;
}
[Entry("task name")]
public string Name { get; set; }
[Entry("other task info")]
public string Notes { get; set; }
[Entry("Done")]
public bool Done { get; set; }
[Section ("")]
[OnTap ("SaveTask")] // method in HomeScreen
[Alignment (UITextAlignment.Center)]
public string Save;
[Section ("")]
[OnTap ("DeleteTask")] // method in HomeScreen
[Alignment (UITextAlignment.Center)]
public string Delete;
}

Notice the OnTap attributes require a method name – these methods must exist in the class where the
MonoTouch.Dialog.BindingContext is created (in this case, the HomeScreen class discussed in the next
section).

User Interface Layer (UI)

The User Interface Layer consists of the following classes:

1. AppDelegate – Contains calls to the Appearance API to style the fonts and colors used in the application.
Tasky is a simple application so there are no other initialization tasks running in FinishedLaunching .
2. Screens – subclasses of UIViewController that define each screen and its behavior. Screens tie
together the UI with Application Layer classes and the common API ( TaskItemManager ). In this
example the screens are created in code, but they could have been designed using Xcode’s Interface
Builder or the storyboard designer.

3. Images – Visual elements are an important part of every application. Tasky has splash screen and icon
images, which for iOS must be supplied in regular and Retina resolution.

Home Screen

The Home Screen is a MonoTouch.Dialog screen that displays a list of tasks from the SQLite database. It
inherits from DialogViewController and implements code to set the Root to contain a collection of
TaskItem objects for display.
The two main methods related to displaying and interacting with the task list are:

1. PopulateTable – Uses the Business Layer’s TaskManager.GetTasks method to retrieve a collection of


TaskItem objects to display.

2. Selected – When a row is touched, displays the task in a new screen.

Task Details Screen

Task Details is an input screen that allows tasks to be edited or deleted.

Tasky uses MonoTouch.Dialog’s Reflection API to display the screen, so there is no UIViewController
implementation. Instead, the HomeScreen class instantiates and displays a DialogViewController using the
TaskDialog class from the Application Layer.

This screenshot shows an empty screen that demonstrates the Entry attribute setting the watermark text in the
Name and Notes fields:
The functionality of the Task Details screen (such as saving or deleting a task) must be implemented in the
HomeScreen class, because this is where the MonoTouch.Dialog.BindingContext is created. The
following HomeScreen methods support the Task Details screen:

1. ShowTaskDetails – Creates a MonoTouch.Dialog.BindingContext to render a screen. It creates the


input screen using reflection to retrieve property names and types from the TaskDialog class. Additional
information, such as the watermark text for the input boxes, is implemented with attributes on the
properties.
2. SaveTask – This method is referenced in the TaskDialog class via an OnTap attribute. It is called when
Save is pressed, and uses a MonoTouch.Dialog.BindingContext to retrieve the user-entered data
before saving the changes using TaskItemManager .

3. DeleteTask – This method is referenced in the TaskDialog class via an OnTap attribute. It uses
TaskItemManager to delete the data using the primary key (ID property).

Android App
The complete Xamarin.Android project is pictured below:

The class diagram, with classes grouped by layer:


References

The Android app project must reference the platform-specific Xamarin.Android assembly to access classes from
the Android SDK.

It must also reference the PCL project (eg. TaskyPortableLibrary) to access the common data and business layer
code.

Application Layer (AL)

Similar to the iOS version we looked at earlier, the Application Layer in the Android version contains platform-
specific classes required to ‘bind’ the objects exposed by the Core to the UI.

TaskListAdapter – to display a List of objects we need to implement an adapter to display custom objects in a
ListView. The adapter controls which layout is used for each item in the list – in this case the code uses an
Android built-in layout SimpleListItemChecked.

User Interface (UI)

The Android app’s User Interface Layer is a combination of code and XML markup.

Resources/Layout – screen layouts and the row cell design implemented as AXML files. The AXML can
be written by hand, or laid-out visually using the Xamarin UI Designer for Android.
Resources/Drawable – images (icons) and custom button.

Screens – Activity subclasses that define each screen and its behavior. Ties together the UI with
Application Layer classes and the common API (TaskItemManager).

Home Screen

The Home Screen consists of an Activity subclass HomeScreen and the HomeScreen.axml file which defines
the layout (position of the button and task list). The screen looks like this:

The Home Screen code defines the handlers for clicking the button and clicking items in the list, as well as
populating the list in the OnResume method (so that it reflects changes made in the Task Details Screen). Data is
loaded using the Business Layer’s TaskItemManager and the TaskListAdapter from the Application Layer.

Task Details Screen

The Task Details Screen also consists of an Activity subclass and an AXML layout file. The layout determines
the location of the input controls and the C# class defines the behavior to load and save TaskItem objects.
All references to the PCL library are through the TaskItemManager class.

Windows Phone App


The complete Windows Phone project:

The diagram below presents the classes grouped into layers:


References

The platform-specific project must reference the required platform-specific libraries (such as Microsoft.Phone
and System.Windows) to create a valid Windows Phone application.

It must also reference the PCL project (eg. TaskyPortableLibrary) to utilize the TaskItem class and
database.

Application Layer (AL)

Again, as with the iOS and Android versions, the application layer consists of the non-visual elements that help to
bind data to the user interface.

ViewModels

ViewModels wrap data from the PCL ( TaskItemManager) and presents it in way that can be consumed by
Silverlight/XAML data binding. This is an example of platform-specific behavior (as discussed in the Cross-
Platform Applications document).

User Interface (UI)


XAML has a unique data-binding capability that can be declared in markup and reduce the amount of code
required to display objects:

1. Pages – XAML files and their codebehind define the user interface and reference the ViewModels and the
PCL project to display and collect data.

2. Images – Splash screen, background and icon images are a key part of the user interface.

MainPage

The MainPage class uses the TaskListViewModel to display data using XAML’s data-binding features. The
page’s DataContext is set to the view model, which is populated asynchronously. The {Binding} syntax in
the XAML determines how the data is displayed.

TaskDetailsPage

Each task is displayed by binding the TaskViewModel to the XAML defined in the TaskDetailsPage.xaml. The
task data is retrieved via the TaskItemManager in the Business Layer.

Results
The resulting applications look like this on each platform:

iOS

The application uses iOS-standard user interface design, such as the ‘add’ button being positioned in the
navigation bar and using the built-in plus (+) icon. It also uses the default UINavigationController ‘back’
button behavior and supports ‘swipe-to-delete’ in the table.
Android

The Android app uses built-in controls including the built-in layout for rows that require a ‘tick’ displayed. The
hardware/system back behavior is supported in addition to an on-screen back button.

Windows Phone

The Windows Phone app uses the standard layout, populating the app bar at the bottom of the screen instead of
a nav bar at the top.
Summary
This document has provided a detailed explanation of how the principles of layered application design have been
applied to a simple application to facilitate code re-use across three mobile platforms: iOS, Android and Windows
Phone.

It has described the process used to design the application layers and discussed what code & functionality has
been implemented in each layer.

The code can be downloaded from github.


Sharing Code Options

Overview

There are three alternative methods for sharing code between cross-platform applications:

Shared Projects – Use the Shared Asset Project type to organize your source code, and use #if
compiler directives as required to manage platform-specific requirements.
Portable Class Libraries – Create a Portable Class Library (PCL) targetting the platforms you wish
to support, and use Interfaces to provide platform-specific functionality.
.NET Standard Libraries – .NET Standard projects work similarly to PCLs, requiring the use of
Interfaces to inject platform-specific functionality.

The goal of a code-sharing strategy is to support the architecture shown in this diagram, where a single
codebase can be utilized by multiple platforms.

This article compares the three methods to help you choose the right project type for your applications.

Shared Projects
The simplest approach to sharing code files is to use a Shared Project (introduced in Xamarin Studio 5 and
Visual Studio 2013 Update 2). Shared Projects are discussed in detail here.

This screenshot shows a solution file containing three application projects (for Android, iOS and Windows
Phone), with a Shared project that contains common C# source code files:

The conceptual architecture is shown in the following diagram, where each project includes all the shared
source files:

Example

A cross platform application that supports iOS, Android and Windows Phone would require an application
project for each platform. The common code lives in the Shared Project.

An example solution would contain the following folders and projects (project names have been chosen for
expressiveness, your projects do not have to follow these naming guidelines):
Shared – Shared Project containing the code common to all projects.
AppAndroid – Xamarin.Android application project.
AppiOS – Xamarin.iOS application project.
AppWinPhone – Windows Phone application project.

In this way the three application projects are sharing the same source code (the C# files in Shared). Any
edits to the shared code will be shared across all three projects.

Benefits

Allows you to share code across multiple projects.


Shared code can be branched based on the platform using compiler directives (eg. using #if
__ANDROID__ , as discussed in the Building Cross Platform Applications document).
Application projects can include platform-specific references that the shared code can utilize (such as
using Community.CsharpSqlite.WP7 in the Tasky sample for Windows Phone).

Disadvantages

Unlike most other project types, a Shared Project has no 'output' assembly. During compilation, the
files are treated as part of the referencing project and compiled into that assembly. If you wish to
share your code as a assembly then Portable Class Libraries or .NET Standard are a better solution.

Refactorings that affect code inside 'inactive' compiler directives will not update the code.

Remarks

A good solution for application developers writing code that is only intended for sharing in their app (and
not distributing to other developers).

Portable Class Libraries


Portable Class Libraries are discussed in detail here.
Benefits

Allows you to share code across multiple projects.


Refactoring operations always update all affected references.

Disadvantages

Cannot use compiler directives.


Only a subset of the .NET framework is available to use, determined by the profile selected (see the
Introduction to PCL for more info).

Remarks

A good solution if you plan to share the resulting assembly with other developers.

.NET Standard Libraries


.NET Standard is discussed in detail here.
Benefits

Allows you to share code across multiple projects.


Refactoring operations always update all affected references.
A larger surface area of the .NET Base Class Library (BCL) is available than PCL profiles.

Disadvantages

Cannot use compiler directives.

Remarks

.NET Standard is similar to PCL, but with a simpler model for platform support and a greater number of
classes from the BCL.

Summary
The code sharing strategy you choose will be driven by the platforms you are targeting. Choose a method
that works best for your project.

PCL or .NET Standard are good choices for building sharable code libraries (especially publishing on
NuGet). Shared Projects work well for application developers planning to use lots of plaform-specific
functionality in their cross-platforma apps.
Portable Class Libraries

Creating Reusable Cross Platform Library Projects

Introduction to Portable Class Libraries

Portable Class Libraries allow you to write code and produce libraries that can be shared
across mulitple platforms including Xamarin.iOS, Xamarin.Android and Windows Phone.
Portable Class Libraries (PCLs) can be created in both Visual Studio for Mac and Visual
Studio, and then referenced in each platform-specific project to allow code to be easily
shared. This document explains a little about how PCLs work and shows how to create and
consume them in cross-platform mobile apps.

Portable Visual Basic.NET

Visual Studio supports the creation of Portable Class Libraries using Visual Basic.NET which
can then be incorporated into Xamarin applications. This article shows how to create a new
Visual Basic PCL and then use it in a sample Xamarin.iOS, Xamarin.Android and Windows
Phone application.
Introduction to Portable Class Libraries
A key component of building cross-platform applications is being able to share code across various platform-
specific projects. However, this is complicated by the fact that different platforms often use a different sub-set of
the .NET Base Class Library (BCL), and therefore are actually built to a different .NET Core Library Profile. This
means that each platform can only use class libraries that are targeted to the same profile, so they would appear
to require separate class library projects for each platform.

There are two major approaches to code sharing that address this problem: Shared Asset Projects and
Portable Class Library (PCL) projects.

Shared Asset Projects use a single set of files and offers a quick and simple way in which to share code
within a solution and generally employs conditional compilation directives to specify code paths for various
platforms that will use it (for more information see the Shared Projects article and the Setting up a Xamarin
Cross-Platform Solution guide ).
PCL projects target specific profiles that support a known set of BCL classes/features. However, the down
side to PCL is that they often require extra architectural effort to separate profile specific code into their
own libraries. For a more detailed discussion on these two approaches, see the Sharing Code Options
guide .

This page explains how to create a PCL project that targets a specific profile, which can then be referenced by
multiple platform-specific projects.

Requirements
Portable Library projects are automatically enabled in Visual Studio for Mac on macOS, and are built-in to Visual
Studio 2013 and later.

What is a Portable Class Library?


When you create an Application Project or a Library Project, the resulting DLL is restricted to working on the
specific platform it is created for. This prevents you from writing an assembly for a Windows app, and then re-
using it on Xamarin.iOS and Xamarin.Android.

When you create a Portable Class Library, however, you can choose a combination of platforms that you want
your code to run on. The compatibility choices you make when creating a Portable Class Library are translated
into a “Profile” identifier, which describes which platforms the library supports.

The table below shows some of the features that vary by .NET platform. To write a PCL assembly that is
guaranteed to run on specific devices/platforms you simply choose which support is required when you create
the project.

Feature .NET Framework UWP apps Silverlight Windows Phone Xamarin

Core Y Y Y Y Y

LINQ Y Y Y Y Y

IQueryable Y Y Y 7.5 + Y

Serialization Y Y Y Y Y

Data Annotations 4.0.3 + Y Y Y

The Xamarin column reflects the fact that Xamarin.iOS and Xamarin.Android supports all the profiles shipped
with Visual Studio 2013 and above, and the availability of features in any libraries you create will only be limited
by the other platforms you choose to support.

This includes profiles that are combinations of:

.NET 4 or .NET 4.5


Silverlight 5
Windows Phone 8
UWP apps

You can read more about the different profiles' capabilities on Microsoft’s website and see another community
member's PCL profile summary which includes supported framework info and other notes.

Creating a PCL to share code has a number of pros and cons versus the File-Linking alternative:

Benefits

1. Centralized code sharing – write and test code in a single project that can be consumed by other libraries
or applications.
2. Refactoring operations will affect all code loaded in the solution (the Portable Class Library and the
platform-specific projects).
3. The PCL project can be easily referenced by other projects in a solution, or the output assembly can be
shared for others to reference in their solutions.

Disadvantages

1. Because the same Portable Class Library is shared between multiple applications, platform-specific
libraries cannot be referenced (eg. Community.CsharpSqlite.WP7).
2. The Portable Class Library subset may not include classes that would otherwise be available in both
MonoTouch and Mono for Android (such as DllImport or System.IO.File).

To some extent both disadvantages can be circumvented using the Provider pattern or Dependency Injection to
code the actual implementation in the platform projects against an interface or base class that is defined in the
Portable Class Library.

This diagram shows the architecture of a cross-platform application using a Portable Class Library to share code,
but also using Dependency Injection to pass in platform-dependent features:

[[ide name="xs"]]

Visual Studio for Mac Walkthrough


This section walks through how to create and use a Portable Class Library using Visual Studio for Mac. Refer the
to PCL Example section for a complete implementation.

Creating a PCL

Adding a Portable Class Library to your solution is very similar to adding a regular Library project.

1. In the New Project dialog select the Multiplatform > Library > Portable Library option
2. When a PCL is created in Visual Studio for Mac it is automatically configured with a Profile that works for
Xamarin.iOS and Xamarin.Android. The PCL project will appear as shown in this screenshot:

The PCL is now ready for code to be added. It can also be referenced by other projects (Application projects,
Library projects and even other PCL projects).

Editing PCL Settings

To view and change the PCL settings for this project, right-click the project and choose Options > Build >
General to see the screen shown here:
The settings on this screen control which platforms this particular PCL is compatible with. Changing any of these
options alters the profile being used by this PCL, which in turn controls what features can be used in the portable
code.

Changing any of the Target Framework options automatically updates the Current Profile; the screen will
also display a warning if incompatible options are selected.
If the profile is changed after code has already been added to the PCL, it’s possible that the library will no longer
compile if the code references features that are not part of the newly-selected profile.

Working With a PCL

When code is written in a PCL library, the Visual Studio for Mac editor will recognize the limitations of the
selected profile and adjust auto-complete options accordingly. For example, this screenshot shows the auto-
complete options for System.IO using the default profile (Profile136) used in Visual Studio for Mac – notice the
scrollbar which indicates about half of the available classes are displayed (in fact there are only 14 classes
available).

Compare that with the System.IO auto-complete in a Xamarin.iOS or Xamarin.Android project – there are 40
classes available including commonly used classes like File and Directory which are not in any PCL profile.

This reflects the underlying trade-off of using PCL – the ability to share code seamlessly across many platforms
means certain APIs are not available to you because they don’t have comparable implementations across all
possible platforms.

Using PCL

Once a PCL project has been created, you can add a reference to it from any compatible Application or Library
project in the same way you normally add references. In Visual Studio for Mac, right-click on the References
node and choose Edit References… then switch to the Projects tab as shown:

The following screenshot shows the Solution pad for the TaskyPortable sample app, showing the PCL library at
the bottom and a reference to that PCL library in the Xamarin.iOS project.
The output from a PCL (ie. the resulting assembly DLL) can also be added as a reference to most projects. This
makes PCL an ideal way to ship cross-platform components and libraries.

[[/ide]]

[[ide name="vs"]]

Visual Studio Walkthrough


This section walks through how to create and use a Portable Class Library using Visual Studio. Refer the to PCL
Example section for a complete implementation.

Creating A PCL

Adding a PCL to your solution in Visual Studio is slightly different to adding a regular project.

1. In the Add New Project screen, select the Portable Class Library option
2. Visual Studio will immediately prompt with the following dialog so that the profile can be configured. Tick
the platforms you need to support and press OK.

3. The PCL project will appear as shown in the Solution Explorer. The References node will indicate that the
library uses a subset of the .NET Framework (defined by the PCL profile).
The PCL is now ready for code to be added. It can also be referenced by other projects (Application projects,
Library projects and even other PCL projects).

Editing PCL Settings

The PCL settings can be viewed and changed by right-clicking on the project and choosing Properties > Library
, as shown in this screenshot:

If the profile is changed after code has already been added to the PCL, it’s possible that the library will no longer
compile if the code references features that are not part of the newly-selected profile.

Working with a PCL

When code is written in a PCL library, Visual Studio will recognize the limitations of the selected profile and
adjust Intellisense options accordingly. For example, this screenshot shows the auto-complete options for
System.IO using the default profile (Profile136) – notice the scrollbar which indicates about half of the available
classes are displayed (in fact there are only 14 classes available).
Compare that with the System.IO auto-complete in a regular project – there are 40 classes available including
commonly used classes like File and Directory which are not in any PCL profile.

This reflects the underlying trade-off of using PCL – the ability to share code seamlessly across many platforms
means certain APIs are not available to you because they don’t have comparable implementations across all
possible platforms.

Using PCL

Once a PCL project has been created, you can add a reference to it from any compatible Application or Library
project in the same way you normally add references. In Visual Studio, right-click on the References node and
choose Add Reference... then switch to the Solution : Projects tab as shown:

The following screenshot shows the Solution pane for the TaskyPortable sample app, showing the PCL library at
the bottom and a reference to that PCL library in the Xamarin.iOS project.
The output from a PCL (ie. the resulting assembly DLL) can also be added as a reference to most projects. This
makes PCL an ideal way to ship cross-platform components and libraries.

[[/ide]]

PCL Example
The TaskyPortable sample application demonstrates how a Portable Class Library can be used with Xamarin.
Here are some screenshots of the resulting apps running on iOS, Android and Windows Phone:
It shares a number of data and logic classes that are purely portable code, and it also demonstrates how to
incorporate platform-specific requirements using Dependency Injection for the SQLite database implementation.

The solution structure is shown below (in Visual Studio for Mac and Visual Studio respectively):
Because the SQLite-NET code has platform-specific pieces (to work with the SQLite implementations on each
different operating system) for demonstration purposes it has been refactored into an abstract class that can be
compiled into a Portable Class Library, and the actual code implemented as subclasses in the iOS and Android
projects.

TaskyPortableLibrary

The Portable Class Library is limited in the .NET features that it can support. Because it is compiled to run on
multiple platforms, it cannot make use of [DllImport] functionality that is used in SQLite-NET. Instead SQLite-
NET is implemented as an abstract class, and then referenced through the rest of the shared code. An extract of
the abstract API is shown below:

public abstract class SQLiteConnection : IDisposable {

public string DatabasePath { get; private set; }


public bool TimeExecution { get; set; }
public bool Trace { get; set; }
public SQLiteConnection(string databasePath) {
DatabasePath = databasePath;
}
public abstract int CreateTable<T>();
public abstract SQLiteCommand CreateCommand(string cmdText, params object[]
ps);
public abstract int Execute(string query, params object[] args);
public abstract List<T> Query<T>(string query, params object[] args) where T :
new();
public abstract TableQuery<T> Table<T>() where T : new();
public abstract T Get<T>(object pk) where T : new();
public bool IsInTransaction { get; protected set; }
public abstract void BeginTransaction();
public abstract void Rollback();
public abstract void Commit();
public abstract void RunInTransaction(Action action);
public abstract int Insert(object obj);
public abstract int Update(object obj);
public abstract int Delete<T>(T obj);
public void Dispose()
{
Close();
}
public abstract void Close();

The remainder of the shared code uses the abstract class to “store” and “retrieve” objects from the database. In
any application that uses this abstract class we must pass in a complete implementation that provides the actual
database functionality.

TaskyAndroid and TaskyiOS

The iOS and Android application projects contain the user-interface and other platform-specific code used to
wire-up the shared code in the PCL.

These projects also contain an implementation of the abstract database API that works on that platform. On iOS
and Android the Sqlite database engine is built-in to the operating system, so the implementation can use
[DllImport] as shown to provide the concrete implementation of database connectivity. An excerpt of the
platform-specific implementation code is shown here:

[DllImport("sqlite3", EntryPoint = "sqlite3_open")]


public static extern Result Open(string filename, out IntPtr db);

[DllImport("sqlite3", EntryPoint = "sqlite3_close")]


public static extern Result Close(IntPtr db);

The full implementation can be seen in the sample code.

TaskyWinPhone

The Windows Phone application has its UI built with XAML and contains other platform-specific code to connect
the shared objects with the user interface.

In contrast to the implementation used for iOS and Android, the Windows Phone app must create and use an
instance of the Community.Sqlite.dll as part of its abstract database API. Rather than using DllImport,
methods like Open are implemented against the Community.Sqlite assembly that is referenced in the
TaskWinPhone project. An excerpt is shown here, for comparison with the iOS and Android version above

public static Result Open(string filename, out Sqlite3.sqlite3 db)


{
db = new Sqlite3.sqlite3();
return (Result)Sqlite3.sqlite3_open(filename, ref db);
}

public static Result Close(Sqlite3.sqlite3 db)


{
return (Result)Sqlite3.sqlite3_close(db);
}

Summary

This article has briefly discussed the benefits and pitfalls of Portable Class Libraries, demonstrated how to create
and consume PCLs from inside Visual Studio for Mac and Visual Studio; and finally introduced a complete
sample application – TaskyPortable – that shows a PCL in action.
Portable Visual Basic.NET

Visual Basic.NET for Xamarin using Portable Class Libraries

Xamarin iOS and Android projects do not natively support Visual Basic; however developers can use
Portable Class Libraries to migrate existing Visual Basic code to iOS and Android, or to write significant
portion of their application logic in Visual Basic. Xamarin.Forms applications can be created entirely in
Visual Basic (excluding custom renderers, dependency services, and XAML codebehind).

Requirements
Creating a Visual Basic.NET PCL
Building native Xamarin.iOS and Xamarin.Android apps that use VB
Building Xamarin.Forms apps with VB

Requirements
Portable Class Library Support was added in Xamarin.Android 4.10.1, Xamarin.iOS 7.0.4 and Xamarin
Studio 4.2, meaning any Xamarin projects created with those tools can incorporate Visual Basic PCL
assemblies.

To create and compile Visual Basic Portable Class Libraries you must use Visual Studio on Windows
(Visual Studio 2012 or newer).

ℹ️ NOTE: Visual Basic libraries can only be created and compiled using Visual Studio.
Xamarin.iOS and Xamarin.Android do not support the Visual Basic language.

If you work solely in Visual Studio you can reference the Visual Basic project from Xamarin.iOS
and Xamarin.Android projects.

If your iOS and Android projects must also be loaded in Visual Studio for Mac you should
reference the output assembly from the Visual Basic PCL.

Creating a Visual Basic.NET PCL


This section walks through how to create a Visual Basic Portable Class Library using Visual Studio. The
library can then be referenced in other projects, including Xamarin.iOS, Xamarin.Android, and
Xamarin.Forms apps.
Creating a PCL

When adding a Visual Basic PCL in Visual Studio you must choose a Profile that describes what platforms
your library should be compatible with. Profiles are explained in the Introduction to PCL document.

The steps to create a PCL and choose its Profile are:

1. In the New Project screen, select the Visual Basic > Class Library (Portable) option:

2. Visual Studio will immediately prompt with the following Add Portable Class Library dialog so that
the Profile can be configured. Tick the platforms you need to support and press OK.

3. The Visual Basic PCL project will appear as shown in the Solution Explorer like this:
The PCL is now ready for Visual Basic code to be added. PCL projects can be referenced by other projects
(Application projects, Library projects and even other PCL projects).

Editing the PCL Profile

The PCL Profile (that controls which platforms the PCL is compatible with) can be viewed and changed by
right-clicking on the project and choosing Properties > Library > Change.... The resulting dialog is shown
in this screenshot:

If the profile is changed after code has already been added to the PCL, it’s possible that the library will no
longer compile if the code references features that are not part of the newly selected profile.
Summary

This article has demonstrated how consume Visual Basic code in Xamarin applications using Visual Studio
and Portable Class Libraries. Even though Xamarin does not support Visual Basic directly, compiling Visual
Basic into a PCL allows code written with Visual Basic to be included in iOS and Android apps.

The following pages describe how to use Visual Basic.NET PCLs in native or Xamarin.Forms apps:

Building native Xamarin.iOS and Xamarin.Android apps that use VB


Building Xamarin.Forms apps with VB
Visual Basic.NET in Xamarin iOS and Android

Visual Basic.NET for Xamarin native mobile apps

The TaskyPortable sample application demonstrates how Visual Basic code compiled into a Portable Class
Library can be used with Xamarin. Here are some screenshots of the resulting apps running on iOS, Android and
Windows Phone:

The iOS, Android and Windows Phone projects in the example are all written in C#. The user interface for each
application is built with native technologies (Storyboards, Xml and Xaml respectively), while the TodoItem
management is provided by the Visual Basic Portable Class Library using an IXmlStorage implementation
provided by the native project.

Sample Walkthrough

This guide discusses how Visual Basic has been implemented in the TaskyPortableVB Xamarin sample for iOS
and Android.

⚠️ Review the instructions on Visual Basic.NET PCLs before continuing with this guide.

VisualBasicPortableLibrary
Visual Basic Portable Class Libraries can only be created in Visual Studio. The example library contains the
basics of our application in four Visual Basic files:

IXmlStorage.vb
TodoItem.vb
TodoItemManager.vb
TodoItemRepositoryXML.vb

IXmlStorage.vb

Because file access behaviors vary so greatly between platforms, Portable Class Libraries do not provide
System.IO file storage APIs in any profile. This means that if we want to interact directly with the filesystem in
our portable code, we need to call back to our native projects on each platform. By writing our Visual Basic code
against a simple interface that can be implemented in C# on each platform, we can have shareable Visual Basic
code that still has access to the file system.

The sample code uses this very simple interface that contains just two methods: to read and write a serialized
Xml file.

Public Interface IXmlStorage


Function ReadXml(filename As String) As List(Of TodoItem)
Sub WriteXml(tasks As List(Of TodoItem), filename As String)
End Interface

iOS, Android and Windows Phone implementations for this interface will be shown later in the guide.

TodoItem.vb

This class contains the business object to be used throughout the application. It will be defined in Visual Basic
and shared with the iOS, Android and Windows Phone projects that are written in C#.

The class definition is shown here:

Public Class TodoItem


Property ID() As Integer
Property Name() As String
Property Notes() As String
Property Done() As Boolean
End Class

The sample uses XML serialization and de-serialization to load and save the TodoItem objects.

TodoItemManager.vb
The Manager class presents the ‘API’ for the portable code. It provides basic CRUD operations for the
TodoItem class, but no implementation of those operations.

Public Class TodoItemManager


Private _repository As TodoItemRepositoryXML
Public Sub New(filename As String, storage As IXmlStorage)
_repository = New TodoItemRepositoryXML(filename, storage)
End Sub
Public Function GetTask(id As Integer) As TodoItem
Return _repository.GetTask(id)
End Function
Public Function GetTasks() As List(Of TodoItem)
Return New List(Of TodoItem)(_repository.GetTasks())
End Function
Public Function SaveTask(item As TodoItem) As Integer
Return _repository.SaveTask(item)
End Function
Public Function DeleteTask(item As TodoItem) As Integer
Return _repository.DeleteTask(item.ID)
End Function
End Class

The constructor takes an instance of IXmlStorage as a parameter. This allows each platform to provide its own
working implementation while still letting the portable code describe other functionality that can be shared.

TodoItemRepository.vb

The repository class contains the logic for managing the list of TodoItem objects. The complete code is shown
below – the logic exists mainly to manage a unique ID value across the TodoItems as they are added and
removed from the collection.

Public Class TodoItemRepositoryXML


Private _filename As String
Private _storage As IXmlStorage
Private _tasks As List(Of TodoItem)

''' <summary>Constructor</summary>
Public Sub New(filename As String, storage As IXmlStorage)
_filename = filename
_storage = storage
_tasks = _storage.ReadXml(filename)
End Sub
''' <summary>Inefficient search for a Task by ID</summary>
Public Function GetTask(id As Integer) As TodoItem
For t As Integer = 0 To _tasks.Count - 1
If _tasks(t).ID = id Then
Return _tasks(t)
End If
Next
Return New TodoItem() With {.ID = id}
End Function
''' <summary>List all the Tasks</summary>
Public Function GetTasks() As IEnumerable(Of TodoItem)
Return _tasks
End Function
''' <summary>Save a Task to the Xml file
''' Calculates the ID as the max of existing IDs</summary>
Public Function SaveTask(item As TodoItem) As Integer
Dim max As Integer = 0
If _tasks.Count > 0 Then
max = _tasks.Max(Function(t As TodoItem) t.ID)
End If
If item.ID = 0 Then
item.ID = ++max
_tasks.Add(item)
Else
Dim j = _tasks.Where(Function(t) t.ID = item.ID).First()
j = item
End If
_storage.WriteXml(_tasks, _filename)
Return max
End Function
''' <summary>Removes the task from the XMl file</summary>
Public Function DeleteTask(id As Integer) As Integer
For t As Integer = 0 To _tasks.Count - 1
If _tasks(t).ID = id Then
_tasks.RemoveAt(t)
_storage.WriteXml(_tasks, _filename)
Return 1
End If
Next
Return -1
End Function
End Class

ℹ️ NOTE: this code is is an example of a very basic data-storage mechanism. It is provided to


demonstrate how a Portable Class Library can code against an interface to access platform-specific
functionality (in this case, loading and saving an Xml file). It it not intended to be a production-quality
database alternative.

iOS, Android and Windows Phone Application Projects

This section contains the platform-specific implementations for the IXmlStorage interface and shows how it is
used in each application. The application projects are all written in C#.

iOS and Android IXmlStorage

Xamarin.iOS and Xamarin.Android provide full System.IO functionality so you can easily load and save the Xml
file using the following class:

public class XmlStorageImplementation : IXmlStorage


{
public XmlStorageImplementation(){}
public List<TodoItem> ReadXml(string filename)
{
if (File.Exists(filename))
{
var serializer = new XmlSerializer(typeof(List<TodoItem>));
using (var stream = new FileStream(filename, FileMode.Open))
{
return (List<TodoItem>)serializer.Deserialize(stream);
}
}
return new List<TodoItem>();
}
public void WriteXml(List<TodoItem> tasks, string filename)
{
var serializer = new XmlSerializer(typeof(List<TodoItem>));
using (var writer = new StreamWriter(filename))
{
serializer.Serialize(writer, tasks);
}
}
}

In the iOS application the TodoItemManager and the XmlStorageImplementation are created in the
AppDelegate.cs file as shown in this code snippet. The first four lines are just building the path to the file where
data will be stored; the final two lines show the two classes being instantiated.

var xmlFilename = "TodoList.xml";


string documentsPath =
Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
string libraryPath = Path.Combine(documentsPath, "..", "Library"); // Library
folder
var path = Path.Combine(libraryPath, xmlFilename);
var xmlStorage = new XmlStorageImplementation();
TaskMgr = new TodoItemManager(path, xmlStorage);

In the Android application the TodoItemManager and the XmlStorageImplementation are created in the
Application.cs file as shown in this code snippet. The first three lines are just building the path to the file where
data will be stored; the final two lines show the two classes being instantiated.

var xmlFilename = "TodoList.xml";


string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = Path.Combine(libraryPath, xmlFilename);
var xmlStorage = new AndroidTodo.XmlStorageImplementation();
TaskMgr = new TodoItemManager(path, xmlStorage);

The rest of the application code is primarily concerned with the user interface and using the TaskMgr class to
load and save TodoItem classes.

Windows Phone IXmlStorage

Windows Phone does not provide complete access to the device’s file system, instead exposing the
IsolatedStorage API. The IXmlStorage implementation for Windows Phone looks like this:

public class XmlStorageImplementation : IXmlStorage


{
public XmlStorageImplementation(){}
public List<TodoItem> ReadXml(string filename)
{
IsolatedStorageFile fileStorage =
IsolatedStorageFile.GetUserStoreForApplication();
if (fileStorage.FileExists(filename))
{
var serializer = new XmlSerializer(typeof(List<TodoItem>));
using (var stream = new StreamReader(new
IsolatedStorageFileStream(filename, FileMode.Open, fileStorage)))
{
return (List<TodoItem>)serializer.Deserialize(stream);
}
}
return new List<TodoItem>();
}
public void WriteXml(List<TodoItem> tasks, string filename)
{
IsolatedStorageFile fileStorage =
IsolatedStorageFile.GetUserStoreForApplication();
var serializer = new XmlSerializer(typeof(List<TodoItem>));
using (var writer = new StreamWriter(new
IsolatedStorageFileStream(filename, FileMode.OpenOrCreate, fileStorage)))
{
serializer.Serialize(writer, tasks);
}
}
}

The TodoItemManager and the XmlStorageImplementation are created in the App.xaml.cs file as shown
in this code snippet.

var filename = "TodoList.xml";


var xmlStorage = new XmlStorageImplementation();
TodoMgr = new TodoItemManager(filename, xmlStorage);

The rest of the Windows Phone application consists of Xaml and C# to create the user interface and use the
TodoMgr class to load and save TodoItem objects.

Visual Basic PCL in Visual Studio for Mac


Visual Studio for Mac does NOT support the Visual Basic language – you cannot create or compile Visual Basic
projects with Visual Studio for Mac.

Visual Studio for Mac’s support for Portable Class Libraries means that it can reference PCL assemblies that
were built from Visual Basic.

This section explains how to compile a PCL assembly in Visual Studio and then ensure that it will be stored in a
version control system and referenced by other projects.

Keeping the PCL output from Visual Studio

By default most version control systems (including TFS and Git) will be configured to ignore the /bin/ directory
which means the compiled PCL assembly will not be stored. This means you would need to manually copy it to
any computers running Visual Studio for Mac to add a reference to it.

To ensure your version control system can store the PCL assembly output, you can create a post-build script that
copies it into the project root. This post-build step helps ensure the assembly can be easily added to source
control and shared with other projects.

Visual Studio 2017

1. Right-click on the project and choose the Properties > Build Events section.

2. Add a post-build script that copies the output DLL from this project into the project root directory (which is
outside of /bin/). Depending on your version control configuration, the DLL should now be able to be added
to source control.

Visual Studio 2015

1. Right-click on the project and choose Properties > Compile , then ensure All Configurations is selected in
the top-left comb-box. Click the Build Events... button in the bottom right.
2. Add a post-build script that copies the output DLL from this project into the project root directory (which is
outside of /bin/ ). Depending on your version control configuration, the DLL should now be able to be
added to source control.
All Versions

Next time you build the project, the Portable Class Library assembly will be copied to the project root, and when
you check-in/commit/push your changes the DLL will be stored (so that it can be downloaded onto a Mac with
Visual Studio for Mac).

This assembly can then be added to Xamarin projects in Visual Studio for Mac, even though the Visual Basic
language itself is not supported in Xamarin iOS or Android projects.

Referencing the PCL in Visual Studio for Mac

Because Xamarin does not support Visual Basic it cannot load the PCL project (nor the Windows Phone app) as
shown in this screenshot:

We can still include the Visual Basic PCL assembly DLL in the Xamarin.iOS and Xamarin.Android projects:

1. Right-click on the References node and select Edit References...


2. Select the .Net Assembly tab and navigate to the output DLL in the Visual Basic project directory. Even
though Visual Studio for Mac cannot open the project, all the files should be there from source control.
Click Add then OK to add this assembly to the iOS and Android applications.

3. The iOS and Android applications can now include the application logic provided by the Visual Basic
Portable Class Library. This screenshot shows an iOS application that references the Visual Basic PCL and
has code that uses the functionality from that library.
If changes are made to the Visual Basic project in Visual Studio remember to build the project, store the resulting
assembly DLL in source control, and then pull that new DLL from source control onto your Mac so that Visual
Studio for Mac builds contain the latest functionality.

Summary

This article has demonstrated how consume Visual Basic code in Xamarin applications using Visual Studio and
Portable Class Libraries. Even though Xamarin does not support Visual Basic directly, compiling Visual Basic into
a PCL allows code written with Visual Basic to be included in iOS and Android apps.
Xamarin.Forms using Visual Basic.NET
Xamarin does not support Visual Basic directly - follow the instructions on this page to create a C#
Xamarin.Forms PCL solution and then replace the common code PCL project with Visual Basic.

ℹ️ NOTE: You must use Visual Studio on Windows to program with Visual Basic.

Xamarin.Forms with Visual Basic Walkthrough

Follow these steps to create a simple Xamarin.Forms project that uses Visual Basic:

1. Create a new Xamarin.Forms C# solution that uses Portable Class Libraries (PCL). Go to File > New
Project and in the New Project window navigate to Installed > Templates > Visual C# > Cross Platform
then choose Cross Platform App (Xamarin.Forms or Native) > Xamarin.Forms.

2. Right-click on the solution and Add > New Project.

3. Choose the Visual Basic > Class Library (Portable) project type:
4. Select the platforms as shown to configure the correct PCL Profile (be sure to include Xamarin.iOS and
Xamarin.Android):

5. Right-click on the Visual Basic project and choose Properties, then change the Default namespace to
match the existing C# projects:

6. Right-click on the new Visual Basic project and choose Manage Nuget Packages, then install
Xamarin.Forms and close the package manager window.

7. Rename the default Class1 file and class to App:

8. Paste the following code into the App.vb file, which will become the starting point of your Xamarin.Forms
app. Remember to include Imports Xamarin.Forms and add Inherits Application to the class:

Imports Xamarin.Forms

Public Class App


Inherits Application

Public Sub New()


Dim label = New Label With {.HoriztonalTextAlignment =
TextAlignment.Center,
.FontSize =
Device.GetNamedSize(NamedSize.Medium, GetType(Label)),
.Text = "Welcome to Xamarin.Forms with
Visual Basic.NET"}
Dim stack = New StackLayout With {
.VerticalOptions = LayoutOptions.Center
}
stack.Children.Add(label)

Dim page = New ContentPage


page.Content = stack
MainPage = page

End Sub

End Class

1. Now we need to point the iOS and Android projects at the new Visual Basic project. Right-click on the
References node in the iOS and Android projects to open the Reference Manager. Un-tick the the C#
portable library and tick the VB portable library (don't forget, do this for both the iOS and Android projects).

2. Delete the C# portable project. Add new .vb files to build out your Xamarin.Forms application. A template
for new ContentPages in Visual Basic is shown below:

Imports Xamarin.Forms

Public Class Page2


Inherits ContentPage

Public Sub New()


Dim label = New Label With {.HoriztonalTextAlignment =
TextAlignment.Center,
.FontSize =
Device.GetNamedSize(NamedSize.Medium, GetType(Label)),
.Text = "Visual Basic ContentPage"}
Dim stack = New StackLayout With {
.VerticalOptions = LayoutOptions.Center
}
stack.Children.Add(label)

Content = stack
End Sub
End Class

Limitations of Visual Basic in Xamarin.Forms

As stated on the Portable Visual Basic.NET page, Xamarin does not support the Visual Basic language. This
means there are some limitations on where you can use Visual Basic:

Custom Renderers cannot be written in Visual Basic, they must be written in C# in the native platform
projects.

Dependency Service implementations cannot be written in Visual Basic, they must be written in C# in the
native platform projects.

XAML pages cannot be included in the Visual Basic project - the code-behind generator can only build C#.
It is possible to include XAML in a separate, referenced, C# portable class library and use databinding to
populate the XAML files via Visual Basic models (an example of this is included in the sample).

Xamarin does not support the Visual Basic.NET language.


Shared Projects

Using Shared Projects to share code

Overview
Shared Projects (also sometimes called Shared Asset Projects) let you write code that is shared between
multiple target projects including Xamarin applications.

They support compiler directives so that you can conditionally include platform-specific code to be
compiled into a subset of the projects that are referencing the Shared Project. There is also IDE support to
help manage the compiler directives and visualize how the code will look in each application.

If you have used file-linking in the past to share code between projects, Shared Projects works in a similar
way but with much improved IDE support.

Requirements
Shared Project support was added in Xamarin Studio 5 and Visual Studio 2013 Update 2 (see note).

⚠️ Microsoft released this new project type - Shared Projects (download Visual Studio
extension preview) - for Visual Studio 2013 Update 2 (April 2014). Refer to Microsoft's
Windows Phone 8.1 and Microsoft Store docs for more details on how it works with those
platforms.

What is a Shared Project?


Unlike most other project types a shared project does not have any output (in DLL form), instead the code
is compiled into each project that references it. This is illustrated in the diagram below - conceptually the
entire contents of the Shared Project is "copied into" each referencing project and compiled as though it
was a part of them.
The code in a Shared Project can contain compiler directives that will enable or disable sections of code
depending on which application project is using the code, which is suggested by the colored platform boxes
in the diagram.

A Shared Project does not get compiled on its own, it exists purely as a grouping of source code files that
can be included in other projects. When referenced by another project, the code is effectively compiled as
part of that project. Shared Projects cannot reference any other project type (including other Shared
Projects).

Note that Android application projects cannot reference other Android application projects - for example, an
Android unit test project cannot reference an Android application project. For more information about this
limitation, see this forum discussion.

[[ide name="xs"]]

Visual Studio for Mac Walkthrough


This section walks through how to create and use a Shared Project using Visual Studio for Mac. Refer the
to Shared Project Example section for a complete example.

Creating a Shared Project

To create a new Shared Project navigate to File > New Solution... and choose a name.
You can also add a new Shared Project to a solution by right-clicking on the solution file and choosing Add
> Add New Project.... A new Shared Project looks as shown below - notice there are no References or
Component nodes; these are not supported for Shared Projects.

For a Shared Project to be useful, it needs to be referenced by at least one build-able project (such as an
iOS or Android application or library, or a PCL project). A Shared Project does not get compiled when it has
nothing referencing it, so syntax (or any other) errors will not be highlighted until it has been referenced by
something else.

Adding a reference to a Shared Project is done the same way as referencing a regular Library project. This
screenshot shows a Xamarin.iOS project referencing a Shared Project.

Once the Shared Project is referenced by another library or application you can build the solution and view
any errors in the code. When the Shared Project is referenced by two-or-more other projects, a menu
appears in the top-left of the source code editor that shows choose which projects reference this file.
Shared Project Options

When you right-click on a Shared Project and choose Options there fewer settings than other project
types. Because Shared Projects are not compiled (on their own), you cannot set output or compiler options,
project configurations, assembly signing, or custom commands. The code in a Shared Project effectively
inherits these values from whatever is referencing them.

The Options screen is shown below - the Project Name and the Default Namespace are the only two
settings that you will generally change.

[[/ide]]

[[ide name="vs"]]

Visual Studio Walkthrough


This section walks through how to create and use a Shared Project using Visual Studio. Refer the to
Shared Project Example section for a complete implementation.
Creating a Shared Project

To create a new Shared Project navigate to File > New Solution... and choose a name for the project and
solution.

You can also add a new Shared Project to a solution by right-clicking on the solution file and choosing Add
> New Project.... A new Shared Project looks as shown below (after a class file has been added) - notice
there are no References or Component nodes; these are not supported for Shared Projects.

For a Shared Project to be useful, it needs to be referenced by at least one build-able project (such as an
iOS or Android application or library, or a PCL project). A Shared Project does not get compiled when it has
nothing referencing it, so syntax (or any other) errors will not be highlighted until it has been referenced by
something else.

Adding a reference to a Shared Project is done the same way as referencing a regular Library project. This
screenshot shows a Xamarin.iOS project referencing a Shared Project.
Once the Shared Project is referenced by another library or application you can build the solution and view
any errors in the code. When the Shared Project is referenced by two-or-more other projects, a menu
appears in the top-left of the source code editor to see which projects reference the current code file.

Shared Project Properties

When you select a Shared Project there fewer settings in the Properties panel than other project types.
Because Shared Projects are not compiled (on their own), you cannot set output or compiler options,
project configurations, assembly signing, or custom commands. The code in a Shared Project effectively
inherits these values from whatever is referencing them.

The Properties panel is shown below - the Root Namespace is the only setting that you can change.

[[/ide]]

Shared Project Example


The Tasky example uses a Shared Project to contain the common code used by both the iOS, Android and
Windows Phone applications. Both the SQLite.cs and TaskRepository.cs source code files utilise
compiler directives (eg. #if __ANDROID__) to produce different output for each of the applications that
reference them.

The complete solution structure is shown below (in Visual Studio for Mac and Visual Studio respectively):

[[ide name="xs"]]
[[/ide]]

[[ide name="vs"]]
[[/ide]]

The Windows Phone project can be navigated from within Visual Studio for Mac, even though that project
type is not supported for compilation in Visual Studio for Mac.

The running applications are shown below.


Summary
This document described how Shared Projects work, how they can be created and used in both Visual
Studio for Mac and Visual Studio, and introduced a simple sample application that demonstrates a Shared
Project in action.
.NET Standard

Using .NET Standard Library Projects to share code

The .NET Standard Library is a formal specification of .NET APIs that are intended to be available on all .NET
runtimes. The motivation behind the Standard Library is establishing greater uniformity in the .NET ecosystem.
ECMA 335 continues to establish uniformity for .NET runtime behavior, but there is no similar spec for the .NET
Base Class Libraries (BCL) for .NET library implementations.

You can think of it as a simplified, next generation of Portable Class Library. It is a single library with a uniform
API for all .NET Platforms including .NET Core. You just create a single .NET Standard Library and use it from
any runtime that supports .NET Standard Platform.

[[ide name="xs"]]

Xamarin Studio

.NET Standard library projects can be created in Xamarin Studio 6.2, by first creating a Portable Library project:

Once the project has been created, right-click and open the Project Options window. In the General section the
project can be converted to .NET Standard and set to use a specific version in the Platform drop-down list:
You can then create a NuGet package to share the library with other developers.

Visual Studio for Mac Walkthrough

This section walks through how to create and use a .NET Standard Library using Visual Studio for Mac. Refer to
the .NET Standard Library Example section for a complete implementation.

Creating a .NET Standard Library

Adding a .NET Standard Library to your solution is fairly straight forward.

1. In the Add New Project dialog, select the .NET Core category and then select Class Library(.NET
Core).

Note: This template will be renamed to .NET Standard in a future version of Visual Studio for Mac.

2. The .NET Standard Library project will appear as shown in the Solution Explorer. The Dependencies node
will indicate that the library uses the NETStandard.Library.
Editing .NET Standard Library Settings

The .NET Standard Library settings can be viewed and changed by right-clicking on the project and selecting
Options as shown in this screenshot:
Inside you can change your version of netstandard by changing the Target Framework dropdown value.

Additionally: You can edit the .csproj directly to change this value.

[[/ide]]

[[ide name="vs"]]

Visual Studio (Windows) Walkthrough

This section walks through how to create and use a .NET Standard Library using Visual Studio. Refer to the .NET
Standard Library Example section for a complete implementation.

Creating a .NET Standard Library

Visual Studio 2017

Adding a .NET Standard Library to your solution is fairly straight forward.

1. In the Add New Project dialog, select the .NET Standard category and then select Class
Library(.NET Standard).

2. The .NET Standard Library project will appear as shown in the Solution Explorer. The Dependencies node
will indicate that the library uses the NETStandard.Library.

Editing .NET Standard Library Settings

The .NET Standard Library settings can be viewed and changed by right-clicking on the project and selecting
Properties as shown in this screenshot:

Inside you can change your version of netstandard by changing the Target Framework dropdown value.

Additionally: You can edit the .csproj directly to change this value.

Using .NET Standard Library

Once a .NET Standard Library has been created, you can add a reference to it from any compatible Application
or Library project in the same way you normally add references. In Visual Studio, right-click on the References
node and choose Add Reference... then switch to the Solution : Projects tab as shown:

[[/ide]]
.NET Standard

Using .NET Standard Library Projects to share code

The .NET Standard Library is a formal specification of .NET APIs that are intended to be available on all .NET
runtimes. The motivation behind the Standard Library is establishing greater uniformity in the .NET ecosystem.
ECMA 335 continues to establish uniformity for .NET runtime behavior, but there is no similar spec for the .NET
Base Class Libraries (BCL) for .NET library implementations.

You can think of it as a simplified, next generation of Portable Class Library. It is a single library with a uniform
API for all .NET Platforms including .NET Core. You just create a single .NET Standard Library and use it from
any runtime that supports .NET Standard Platform.

[[ide name="xs"]]

Xamarin Studio

.NET Standard library projects can be created in Xamarin Studio 6.2, by first creating a Portable Library project:

Once the project has been created, right-click and open the Project Options window. In the General section the
project can be converted to .NET Standard and set to use a specific version in the Platform drop-down list:
You can then create a NuGet package to share the library with other developers.

Visual Studio for Mac Walkthrough

This section walks through how to create and use a .NET Standard Library using Visual Studio for Mac. Refer to
the .NET Standard Library Example section for a complete implementation.

Creating a .NET Standard Library

Adding a .NET Standard Library to your solution is fairly straight forward.

1. In the Add New Project dialog, select the .NET Core category and then select Class Library(.NET
Core).

Note: This template will be renamed to .NET Standard in a future version of Visual Studio for Mac.

2. The .NET Standard Library project will appear as shown in the Solution Explorer. The Dependencies node
will indicate that the library uses the NETStandard.Library.
Editing .NET Standard Library Settings

The .NET Standard Library settings can be viewed and changed by right-clicking on the project and selecting
Options as shown in this screenshot:
Inside you can change your version of netstandard by changing the Target Framework dropdown value.

Additionally: You can edit the .csproj directly to change this value.

[[/ide]]

[[ide name="vs"]]

Visual Studio (Windows) Walkthrough

This section walks through how to create and use a .NET Standard Library using Visual Studio. Refer to the .NET
Standard Library Example section for a complete implementation.

Creating a .NET Standard Library

Visual Studio 2017

Adding a .NET Standard Library to your solution is fairly straight forward.

1. In the Add New Project dialog, select the .NET Standard category and then select Class
Library(.NET Standard).

2. The .NET Standard Library project will appear as shown in the Solution Explorer. The Dependencies node
will indicate that the library uses the NETStandard.Library.

Editing .NET Standard Library Settings

The .NET Standard Library settings can be viewed and changed by right-clicking on the project and selecting
Properties as shown in this screenshot:

Inside you can change your version of netstandard by changing the Target Framework dropdown value.

Additionally: You can edit the .csproj directly to change this value.

Using .NET Standard Library

Once a .NET Standard Library has been created, you can add a reference to it from any compatible Application
or Library project in the same way you normally add references. In Visual Studio, right-click on the References
node and choose Add Reference... then switch to the Solution : Projects tab as shown:

[[/ide]]
NuGet Projects (Nugetizer 3000)

Multiplatform Libraries for Code Sharing

It is possible to automatically create NuGet packages to share code across platforms using
the Nugetizer 3000. This makes is possible to create NuGet packages from existing library
projects or by creating a new Multiplatform Library Project.

[[ide name="xs"]] The Nugetizer 3000 is included with Visual Studio for Mac 6.2. [[/ide]]

[[ide name="vs"]] To use the Nugetizer 3000 in Visual Studio, please download and run the
VSIX installer. [[/ide]]

Once configured, every build of the project outputs a complete NuGet package, which can
be used to share code internally with other apps or uploaded to NuGet.org.

There are three scenarios for using this feature:

Existing Library Projects

Create a NuGet package from existing PCL (or .NET Standard) projects.

Creating a New Multiplatform Library Project

Create a new library to share common code via NuGet, using a PCL or .NET
Standard.
Creating New Platform-Specific Library Projects

Create a new library and NuGet that includes platform-specific code for iOS and
Android, and uses a Shared Project to contain the common code and platform-specific
projects to support iOS- or Android-specific functionality.

Refer to the Metadata guide for details on the required and optional metadata that must be
added to any NuGet package.

Further NuGet Information

Read more about manually creating NuGets for Xamarin and how to include a NuGet
package in an app.

Microsoft's NuGet Documentation contains more detailed information on the .nupkg format
and using NuGet packages in Visual Studio.

The design discussion for NuGet Package Projects (a.k.a. NuGetizer 3000) is available on
the NuGet GitHub repository.
Creating a NuGet from Existing Library
Projects
Existing PCL or .NET Standard libraries can be turned into NuGets via the Project Options
window:

1. Right-click on the library project in the Solution Pad and choose Options.

2. Go to the NuGet Package > Metadata section and enter all the required information in
the General tab:

3. Optionally, add additional metadata in the Details tab.

4. Once the metadata is configured, you can right-click on the project and choose Create
NuGet Package and the .nupkg NuGet package file will be saved in the /bin/ folder
(either Debug or Release, depending on configuration).
5. To create the NuGet package on every build or deploy, go to the NuGet Package >
Build section and tick Create a NuGet Package when building the project:

ℹ️ Building the NuGet package can slow down the build process. If this box is
not ticked, you can still generate a NuGet package manually at any time from the
project context menu (shown in step 4 above).

Verifying the Output

NuGet packages are also ZIP files, so it's possible to inspect the internal structure of the
generated package.

This screenshot shows the contents of a PCL-based NuGet – only a single PCL assembly is
included:
Creating a New Multiplatform Library for NuGet
Creating a Multiplatform Library project that uses PCL or .NET Standard means that the resulting NuGet can be
added to any .NET project that supports the target profile, including ASP.NET projects, or desktop apps using
WinForms, WPF, or UWP.

The library can only contain code supported by the selected PCL or .NET Standard profile, as well as any other
NuGets that are added. This is suited to business logic and algorithms that can be expressed entirely in the .NET
base class library.

A single assembly is created and built into a NuGet package.

If you later need platform-specific functionality, platform-specific projects can be added.

Steps to Create a Multiplatform Library NuGet

1. Select File > New Solution (or right click an existing solution and choose Add > New Project).

2. Choose Multiplatform Library from the Multiplatform > Library section:

3. Enter a Name and Description, and choose Single for all platforms:
4. Complete the wizard. A single library project is created in the solution.

5. Right-click on the new library project and then select Options. The Build > General section allows the
Target Framework to be set – choose a .NET Portable PCL profile or a .NET Standard version:

6. Also in the Project Options window, open the NuGet Package > Metadata section and enter the required
metadata (as well as any optional metadata):

7. Right-click on the library project and choose Create NuGet Package (or build or deploy the solution) and
the .nupkg NuGet package file will be saved in the /bin/ folder (either Debug or Release, depending on
configuration):
Verifying the Output

NuGet packages are also ZIP files, so it's possible to inspect the internal structure of the generated package.

This screenshot shows the contents of a PCL-based NuGet – only a single PCL assembly is included:

Adding Platform-Specific Code


PCL-based projects and .NET Standard-based projects cannot contain platform-specific references (such as iOS
or Android functionality).

If an existing PCL project or .NET Standard project needs to be expanded to include platform-specific code, this
can be done by right-clicking on the project and selecting Add > Add Platform Implementation...:

One or more platform projects can be added to the solution, and the existing PCL or .NET Standard library can
optionally be converted to a Shared Project:

After converting to a Shared Project, visit the Project Options > NuGet Package > Reference Assemblies
section and ensure that any required profiles are selected (so that the NuGet continues to be compatible with
projects it was previously used in).
Creating New Platform-Specific Library Projects for
NuGet
Multiplatform Library projects that target specific platforms, like iOS and Android, work best with Shared Projects.

The NuGet can contain both iOS- and Android-specific code, as well as .NET code common to both.

Multiple assemblies are created and built into a single NuGet package. NuGet standards ensure that the package
can be added to all supported project types, such as Xamarin iOS and Android projects.

Steps to Create a Cross-Platform Library NuGet

1. Select File > New Solution (or right click an existing solution and choose Add > New Project).

2. Choose Multiplatform Library from the Multiplatform > Library section:

3. Enter a Name and Description, and choose Platform specific:

4. Complete the wizard. The following projects are added to the solution:

Android Project – Android-specific code can optionally be added to this project.


iOS Project – iOS-specific code can optionally be added to this project.
NuGet Project – No code is added to this project. It references the other projects, and contains the
metadata configuration for the NuGet package output.
Shared Project – Common code should be added to this project, including platform-specific code
inside #if compiler directives.

5. Right-click on the NuGet project and choose Options, then open the NuGet Package > Metadata section
and enter the required metadata (as well as any optional metadata):

6. Also in the Project Options window, open the Reference Assemblies section and choose which PCL
profiles the shared library will support via "bait and switch":
ℹ️ "Bait and switch" means that the PCL assemblies will only contain the API exposed by the
library (it cannot contain the platform-specific code). When the NuGet is added to a Xamarin
project, shared libraries will be compiled against the PCL, but the platform-specific assemblies
contain the code that is actually used by the iOS or Android project.

7. Right-click on the project and choose Create NuGet Package (or build or deploy the solution) and the
.nupkg NuGet package file will be saved in the /bin/ folder (either Debug or Release, depending on
configuration).

Verifying the Output

NuGet packages are also ZIP files, so it's possible to inspect the internal structure of the generated package.

This screenshot shows the contents of a platform-specific NuGet that supports iOS and Android, and had two
reference assemblies selected:
Editing NuGet Metadata
Library project types (such as PCL or .NET Standard, or the new NuGet project type) have a
NuGet Package section in the Project Options window.

The Metadata section configures the values used in the .nuspec NuGet package manifest
file.

Required Information

The General tab contains four fields that must be entered to generate a NuGet package:

ID – The package identifier, which should be unique within Nuget.org (or wherever the
package will be distributed). Follow this guidance and only use characters that are
valid in a URL (no spaces, and avoid most special characters).
Version – Choose a version number consistent with NuGet's versioning rules.
Authors – Comma-separated list of names.
Description – Overview of the package's features which is displayed when users are
selecting the package.

ℹ️ Remember to increment the version number when building new versions for
distribution to NuGet or other users.

For more information, see the Required Elements Reference for more information, as well as
these detailed instructions on Choosing a unique package identifier and setting the version
number and Setting a package type.

⚠️ All fields on this tab must be entered; otherwise, an error message will
appear: "The project does not have NuGet metadata so a NuGet package will
not be created. NuGet package metadata can be specified in the Metadata
section in Project Options"

Optional Metadata

The Details tab contains optional fields to be included in the NuGet package manifest file.

Refer to the Optional Elements Reference for more information about the required and
optional fields.

ℹ️ If the NuGet package is being distributed on NuGet.org it is recommended


to supply as much information as possible.
Rendimiento multiplataforma

Información general
El mal rendimiento de una aplicación se manifiesta de muchas formas. Puede hacer que
parezca que una aplicación deja de responder, puede ocasionar un desplazamiento lento y
puede reducir la duración de la batería. La optimización del rendimiento conlleva mucho
más que la mera implementación de código eficaz. También debe tenerse en cuenta la
experiencia de rendimiento de la aplicación del usuario. Por ejemplo, asegurarse de que las
operaciones se ejecuten sin evitar que el usuario realice otras actividades puede ayudar a
mejorar su experiencia.

Existen varias técnicas para aumentar el rendimiento, y la percepción de rendimiento, de las


aplicaciones compiladas con la plataforma Xamarin. Son los siguientes:

Usar el generador de perfiles


Liberar los recursos de IDisposable
Cancelar la suscripción a eventos
Usar referencias débiles para evitar objetos inmortales
Retrasar el consumo de recursos de la creación de objetos
Implementar operaciones asincrónicas
Usar el recolector de elementos no utilizados SGen
Reducir el tamaño de la aplicación
Optimizar los recursos de imagen
Reducir el período de activación de la aplicación
Reducir la comunicación con servicios web

Este vídeo de Xamarin University gratuito además incluye sugerencias útiles para diseñar
aplicaciones de Xamarin.
Usar el generador de perfiles
Al desarrollar una aplicación, es importante intentar optimizar el código únicamente cuando
ya se ha generado un perfil. La generación de perfiles es una técnica para determinar dónde
tendrán más efecto las optimizaciones de código a la hora de reducir problemas de
rendimiento. El generador de perfiles realiza el seguimiento del consumo de memoria de la
aplicación y registra el tiempo de ejecución de los métodos de la aplicación. Estos datos
ayudan a navegar por las rutas de ejecución de la aplicación y el consumo de recursos de
ejecución del código, por lo que permiten detectar las mejores oportunidades de
optimización.

Xamarin Profiler mide, evalúa y ayuda a detectar problemas relacionados con el rendimiento
en una aplicación. Se puede usar para generar perfiles de aplicaciones de Xamarin.iOS y
Xamarin.Android desde Visual Studio para Mac o Visual Studio. Para más información sobre
Xamarin Profiler, vea Introducción a Xamarin Profiler.

Al generar perfiles de una aplicación, estos son los procedimientos recomendados:

Evite la generación de perfiles de una aplicación en un simulador, ya que este puede


distorsionar el rendimiento de la aplicación.
Lo ideal sería generar perfiles en varios dispositivos, ya que la toma de medidas de
rendimiento en un dispositivo no siempre muestra las características de rendimiento
de otros dispositivos. Como mínimo, la generación de perfiles debe realizarse en un
dispositivo con la menor especificación prevista.
Cierre las demás aplicaciones para garantizar la medición del impacto total de la
aplicación cuyo perfil se está generando, y no del de las otras.

Liberar los recursos de IDisposable


La interfaz IDisposable proporciona un mecanismo para liberar recursos. Proporciona un
método Dispose que debe implementarse para liberar recursos de forma explícita.
IDisposable no es un destructor y solo se debe implementar en los siguientes casos:
Si la clase tiene recursos no administrados. Los recursos típicos no administrados que
exigen liberación incluyen los archivos, las secuencias y las conexiones de red.
Si la clase tiene recursos IDisposable administrados.

Los consumidores del tipo pueden llamar a la implementación IDisposable.Dispose


para liberar recursos cuando ya no se necesite la instancia. Existen dos enfoques para
conseguirlo:

Ajustar el objeto IDisposable en una instrucción using.


Ajustar la llamada a IDisposable.Dispose en un bloque try/finally.

Ajuste del objeto IDisposable en una instrucción using

En el ejemplo de código siguiente se muestra cómo ajustar un objeto IDisposable en una


instrucción using:

public void ReadText (string filename)


{
...
string text;
using (StreamReader reader = new StreamReader (filename)) {
text = reader.ReadToEnd ();
}
...
}

La clase StreamReader implementa IDisposable y la instrucción using proporciona


una sintaxis adecuada que llama al método StreamReader.Dispose en el objeto
StreamReader antes de quede fuera del ámbito. Dentro del bloque using, el objeto
StreamReader es de solo lectura y no se puede reasignar. La instrucción using también
garantiza que se llame al método Dispose aun cuando se produzca una excepción, ya que
el compilador implementa el lenguaje intermedio (IL) para un bloque try/finally.
Ajuste de la llamada a IDisposable.Dispose en un
bloque Try/Finally

En el ejemplo de código siguiente se muestra cómo ajustar la llamada


IDisposable.Dispose en un bloque try/finally:

public void ReadText (string filename)


{
...
string text;
StreamReader reader = null;
try {
reader = new StreamReader (filename);
text = reader.ReadToEnd ();
} finally {
if (reader != null) {
reader.Dispose ();
}
}
...
}

La clase StreamReader implementa IDisposable y el bloque finally llama al método


StreamReader.Dispose para liberar el recurso.

Para más información, vea Interfaz IDisposable.

Cancelar la suscripción a eventos


Para evitar pérdidas de memoria, se debería cancelar la suscripción a eventos antes de que
se elimine el objeto de suscriptor. Hasta que se cancela la suscripción al evento, el
delegado del evento en el objeto de publicación tiene una referencia al delegado que
encapsula el controlador de eventos del suscriptor. Mientras el objeto de publicación
contenga esta referencia, la recolección de elementos no utilizados no recuperará la
memoria del objeto de suscriptor.

En el ejemplo de código siguiente se muestra cómo cancelar la suscripción a un evento:

public class Publisher


{
public event EventHandler MyEvent;

public void OnMyEventFires ()


{
if (MyEvent != null) {
MyEvent (this, EventArgs.Empty);
}
}
}

public class Subscriber : IDisposable


{
readonly Publisher publisher;

public Subscriber (Publisher publish)


{
publisher = publish;
publisher.MyEvent += OnMyEventFires;
}

void OnMyEventFires (object sender, EventArgs e)


{
Debug.WriteLine ("The publisher notified the subscriber of an
event");
}
public void Dispose ()
{
publisher.MyEvent -= OnMyEventFires;
}
}

La clase Subscriber cancela la suscripción al evento en su método Dispose.

También se pueden producir ciclos de referencia al usar controladores de eventos y sintaxis


lambda, ya que las expresiones lambda pueden hacer referencia a objetos activos y
conservarlos. Por lo tanto, se puede almacenar una referencia al método anónimo en un
campo y usarla para cancelar la suscripción al evento, como se muestra en el ejemplo de
código siguiente:

public class Subscriber : IDisposable


{
readonly Publisher publisher;
EventHandler handler;

public Subscriber (Publisher publish)


{
publisher = publish;
handler = (sender, e) => {
Debug.WriteLine ("The publisher notified the subscriber of an
event");
};
publisher.MyEvent += handler;
}

public void Dispose ()


{
publisher.MyEvent -= handler;
}
}

El campo handler mantiene la referencia al método anónimo y se usa para la suscripción a


eventos y su cancelación.

Usar referencias débiles para evitar


objetos inmortales
ℹ️ Los desarrolladores de iOS deben revisar la documentación sobre cómo
evitar referencias circulares en iOS para asegurarse de que sus aplicaciones
usan memoria de forma eficaz.

Retrasar el consumo de recursos de la


creación de objetos
Se puede usar la inicialización diferida para aplazar la creación de un objeto hasta que se
use por primera vez. Esta técnica se usa principalmente para mejorar el rendimiento, evitar
el cálculo y reducir los requisitos de memoria.

Considere el uso de la inicialización diferida para aquellos objetos cuya creación consume
muchos recursos en estos dos escenarios:

La aplicación podría no usar el objeto.


Antes de crear el objeto, deben completarse otras operaciones que consumen
muchos recursos.

Se usa la clase Lazy<T> para definir un tipo con inicialización diferida, como se muestra en
el ejemplo de código siguiente:

void ProcessData(bool dataRequired = false)


{
Lazy<double> data = new Lazy<double>(() =>
{
return ParallelEnumerable.Range(0, 1000)
.Select(d => Compute(d))
.Aggregate((x, y) => x + y);
});

if (dataRequired)
{
if (data.Value > 90)
{
...
}
}
}

double Compute(double x)
{
...
}

La inicialización diferida se produce la primera vez que se accede a la propiedad


Lazy<T>.Value. El tipo encapsulado se crea y se devuelve en el primer acceso y se
almacena para cualquier acceso futuro.

Para más información sobre la inicialización diferida, vea Lazy Initialization (Inicialización
diferida).

Implementar operaciones asincrónicas


.NET proporciona versiones asincrónicas de muchas de sus API. A diferencia de las API
sincrónicas, las API asincrónicas garantizan que el subproceso de ejecución activo nunca
bloquee al subproceso de llamada durante una cantidad considerable de tiempo. Por lo
tanto, al llamar a una API desde el subproceso de IU, use la API asincrónica si está
disponible. Esto mantendrá desbloqueado al subproceso de IU, lo que le ayudará a mejorar
la experiencia del usuario con la aplicación.

Además, las operaciones de larga ejecución deberían ejecutarse en un subproceso en


segundo plano para evitar el bloqueo del subproceso de IU. .NET proporciona las palabras
clave async y await que permiten la escritura de código asincrónico que ejecuta
operaciones de larga ejecución en un subproceso en segundo plano, y accede a los
resultados al finalizar. Pero aunque las operaciones de larga ejecución pueden ejecutarse
asincrónicamente con la palabra clave await, esto no garantiza que la operación se ejecute
en un subproceso en segundo plano. Esto puede realizarse pasando la operación de larga
duración a Task.Run, como se muestra en el ejemplo de código siguiente:

public class FaceDetection


{
...
async void RecognizeFaceButtonClick(object sender, EventArgs e)
{
await Task.Run(() => RecognizeFace ());
...
}

async Task RecognizeFace()


{
...
}
}

El método RecognizeFace se ejecuta en un subproceso en segundo plano, con el método


RecognizeFaceButtonClick en espera hasta que el método RecognizeFace se
completa antes de continuar.

Las operaciones de larga ejecución también deberían permitir la cancelación. Por ejemplo,
la continuación de una operación de larga duración podría ser innecesaria si el usuario se
desplazara dentro de la aplicación. El modelo para implementar la cancelación es el
siguiente:

Cree una instancia CancellationTokenSource. Esta instancia administrará y


enviará notificaciones de cancelación.
Pase el valor de propiedad CancellationTokenSource.Token a cada tarea que
deba cancelarse.
Proporcione un mecanismo para que cada tarea responda a la cancelación.
Llame al método CancellationTokenSource.Cancel para proporcionar una
notificación de cancelación.

⚠️ La clase CancellationTokenSource implementa la interfaz de


IDisposable, y se debería invocar el método
CancellationTokenSource.Dispose una vez que se termine con la
instancia CancellationTokenSource.

Para más información, vea Información general sobre la compatibilidad con Async.

Usar el recolector de elementos no


utilizados SGen
Los lenguajes administrados como C# usan la recolección de elementos no utilizados para
reclamar la memoria asignada a los objetos que ya no están en uso. Los dos recolectores
de elementos no utilizados que emplea la plataforma Xamarin son:

SGen: se trata de un recolector de elementos no utilizados generacional y es el


predeterminado en la plataforma Xamarin.
Boehm: se trata de un recolector de elementos no utilizados no generacional
conservador. Es el predeterminado para las aplicaciones de Xamarin.iOS que usan la
API clásica.
SGen usa uno de tres montones para asignar espacio para los objetos:

Guardería: es donde se asignan los nuevos objetos pequeños. Cuando se queda sin
espacio, se produce una recolección de elementos no utilizados menor. Todos los
objetos activos se mueven al montón principal.
Montón principal: es donde se guardan los objetos de larga ejecución. Si no hay
suficiente memoria en el montón principal, se produce una importante recolección de
elementos no utilizados. Si se produce un error en una recolección de elementos no
utilizados para liberar memoria, SGen le pide más memoria al sistema.
Espacio de objetos grandes: es donde se guardan los objetos que necesitan más de
8000 bytes. Los objetos grandes no se envían a la guardería, sino que se asignan a
este montón.

Una de las ventajas de SGen es que el tiempo necesario para realizar una recolección
menor es proporcional al número de nuevos objetos activos creados desde la última
recolección menor. Esto reduce el impacto de la recolección de elementos no utilizados
sobre el rendimiento de una aplicación, ya que estas recolecciones menores tardan menos
que una recolección importante. La recolección de elementos importante se seguirá
produciendo, pero con menos frecuencia.

Reducción de la presión sobre el recolector de


elementos no utilizados

Cuando SGen inicia una recolección de elementos no utilizados, detiene los subprocesos de
la aplicación mientras reclama memoria. Mientras se está reclamando memoria, la
aplicación puede experimentar una breve pausa o parpadeo de la interfaz de usuario. Cómo
de perceptible sea esta pausa depende de dos factores:

1. Frecuencia: frecuencia con la que se produce la recolección de elementos no


utilizados. La frecuencia de las recolecciones de elementos no utilizados aumenta a
medida que se asigna más memoria entre recolecciones.
2. Duración: tiempo que dura cada recolección de elementos no utilizados. Es
aproximadamente proporcional al número de objetos activos que se recopila.
Colectivamente, esto significa que si se asignan muchos objetos pero no se mantienen
activos, habrá muchas recolecciones de elementos no utilizados breves. Por el contrario, si
se asignan nuevos objetos lentamente y se mantienen activos, habrá menos recolecciones
pero serán más largas.

Para reducir la presión sobre el recolector de elementos no utilizados, siga estas directrices:

Evite la recolección de elementos no utilizados en bucles estrechos mediante los


grupos de objetos. Esto es de especial importancia para los juegos, que necesitan
crear la mayoría de sus objetos por adelantado.
Libere de forma explícita recursos como secuencias, conexiones de red, bloques
grandes de memoria y archivos una vez que ya no sean necesarios. Para más
información, vea Liberar los recursos de IDisposable.
Elimine del Registro los controladores de eventos una vez que ya no sean necesarios
para que los objetos se puedan recopilar. Para más información, vea Cancelar la
suscripción a eventos.

Reducir el tamaño de la aplicación


Es importante entender el proceso de compilación en cada plataforma para comprender de
dónde procede el tamaño del archivo ejecutable de una aplicación:

Las aplicaciones de iOS se compilan Ahead Of Time (AOT) en lenguaje ensamblador


ARM. Se incluye .NET Framework, y las clases no usadas se quitan solo si está
habilitada la opción del enlazador adecuada.
Las aplicaciones de Android se compilan en lenguaje intermedio (IL) y se empaquetan
con MonoVM y compilación Just-In-Time (JIT). Las clases de Framework no usadas
se quitan solo si está habilitada la opción del enlazador adecuada.
Las aplicaciones de Windows Phone se compilan en IL y se ejecutan con el runtime
integrado.

Además, si una aplicación usa mucho los genéricos, el tamaño final del archivo ejecutable
aumentará más, puesto que incluirá versiones compiladas de forma nativa de las
posibilidades del genérico.

Para reducir el tamaño de las aplicaciones, la plataforma Xamarin incluye un enlazador


como parte de las herramientas de compilación. De forma predeterminada, el enlazador
está deshabilitado y debe habilitarse en las opciones del proyecto de la aplicación. Durante
la compilación, lleva a cabo un análisis estático de la aplicación para determinar qué tipos y
miembros usa esta realmente. Luego quita los tipos y los métodos no usados de la
aplicación.

En la siguiente captura de pantalla se muestran las opciones del enlazador en Visual Studio
para Mac para un proyecto de Xamarin.iOS:

En la siguiente captura de pantalla se muestran las opciones del enlazador en Visual Studio
para Mac para un proyecto de Xamarin.Android:

El enlazador proporciona tres opciones distintas para controlar su comportamiento:

Don’t Link (No vincular): no se quita ningún tipo ni método no usado por el
enlazador. Por motivos de rendimiento, esta es la opción predeterminada para las
compilaciones de depuración.
Link Framework SDKs/SDK Assemblies Only (Vincular solo ensamblados de
SDK o SDK de Framework): esta opción solo reduce el tamaño de los ensamblados
enviados por Xamarin. El código de usuario no se verá afectado.
Link All Assemblies (Vincular todos los ensamblados): se trata de una
optimización más agresiva que se dirige a los ensamblados de SDK y al código de
usuario. En el caso de los enlaces, quita los campos de respaldo no usados y aligera
cada instancia (u objetos enlazados), consumiendo menos memoria.

Link All Assemblies (Vincular todos los ensamblados) debe usarse con precaución, ya que
puede interrumpir la aplicación de formas inesperadas. El análisis estático que realiza el
enlazador puede identificar incorrectamente todo el código necesario, lo que daría lugar a
que se quitara demasiado código de la aplicación compilada. Esta situación solo se
manifiesta en runtime cuando se bloquea la aplicación. Por ello es importante probar
exhaustivamente una aplicación después de cambiar el comportamiento del enlazador.

Si las pruebas revelan que el enlazador ha quitado incorrectamente una clase o método, es
posible marcar tipos o métodos a los que no se hace referencia de forma estática pero que
son necesarios para la aplicación mediante uno de los siguientes atributos:

Xamarin.iOS.Foundation.PreserveAttribute: este atributo es para proyectos


de Xamarin.iOS.
Android.Runtime.PreserveAttribute: este atributo es para proyectos de
Xamarin.Android.

Por ejemplo, puede ser necesario conservar los constructores predeterminados de los tipos
cuyas instancias se han creado de forma dinámica. Además, el uso de la serialización XML
puede exigir que se conserven las propiedades de los tipos.

Para más información, vea Linker for iOS (Enlazador para iOS) y Linker for Android
(Enlazador para Android).

Otras técnicas de reducción de tamaño

Hay una gran variedad de arquitecturas de CPU eficaces para los dispositivos móviles. Así,
Xamarin.iOS y Xamarin.Android generan archivos binarios fat que contienen una versión
compilada de la aplicación para cada arquitectura de CPU. Esto garantiza que una
aplicación móvil se pueda ejecutar en un dispositivo independientemente de la arquitectura
de CPU.

Los siguientes pasos pueden usarse para reducir aún más el tamaño del archivo ejecutable
de la aplicación:

Asegúrese de que se genere una compilación de versión.


Reduzca el número de arquitecturas para el que se compila la aplicación a fin de
evitar que se genere un archivo binario FAT.
Asegúrese de que se use el compilador LLVM a fin de generar un archivo ejecutable
más optimizado.
Reduzca el tamaño del código administrado de la aplicación. Esto se puede lograr si
se habilita el enlazador en cada ensamblado (Link All (Vincular todos) para proyectos
de iOS y Link all assemblies (Vincular todos los ensamblados) para proyectos de
Android).

Las aplicaciones de Android también se pueden dividir en un APK independiente para cada
ABI ("arquitectura"). Obtenga más información en esta entrada de blog: How To Keep Your
Android App Size Down (Cómo reducir el tamaño de una aplicación de Android).

Optimizar los recursos de imagen


Las imágenes son uno de los recursos con más consumo usados por las aplicaciones y se
suelen capturar en altas resoluciones. Aunque esto crea imágenes vibrantes llenas de
detalles, las aplicaciones que muestran dichas imágenes normalmente necesitan usar más
CPU para descodificar la imagen y más memoria para almacenar la imagen descodificada.
Es un desperdicio descodificar una imagen de alta resolución en memoria cuando se
reducirá a un tamaño menor para su presentación. Reduzca el uso de CPU y la superficie
de memoria mediante la creación de varias versiones de resolución de imágenes
almacenadas que se acerquen a los tamaños de presentación previstos. Por ejemplo, una
imagen que aparece en una vista de lista probablemente deba tener menos resolución que
una imagen que aparece en pantalla completa. Además, las versiones reducidas de
imágenes de alta resolución pueden cargarse para mostrarse de forma eficaz con una
repercusión mínima en la memoria. Para más información, vea Load Large Bitmaps
Efficiently (Cargar eficazmente mapas de bits grandes).

Independientemente de la resolución de la imagen, mostrar recursos de imagen puede


aumentar considerablemente la superficie de memoria de la aplicación. Por tanto, solo se
deberían crear cuando fuera necesario y deberían liberarse en cuanto la aplicación no los
necesitara.

Reducir el período de activación de la


aplicación
Todas las aplicaciones tienen un período de activación, que es el tiempo entre su inicio y el
momento en que están listas para su uso. Este período de activación proporciona a los
usuarios la primera impresión de la aplicación, por lo que es importante reducirlo, así como
la percepción que los usuarios tienen de él, para que tengan una primera impresión
favorable de la aplicación.

Antes de que una aplicación muestre su interfaz de usuario inicial, debe proporcionar una
pantalla de presentación para indicar al usuario que se está iniciando. Si la aplicación no
puede mostrar rápidamente su interfaz de usuario inicial, se debe usar la pantalla de
presentación para informar al usuario del progreso durante el período de activación, a fin de
ofrecer la seguridad de que la aplicación no se ha bloqueado. Podría hacerse mediante una
barra de progreso o un control similar.

Durante el período de activación, las aplicaciones ejecutan lógica de activación, que suele
incluir la carga y el procesamiento de los recursos. El período de activación se puede
reducir asegurándose de que los recursos necesarios estén empaquetados en la aplicación
en lugar de recuperarse de forma remota. Por ejemplo, en algunas circunstancias puede ser
adecuado durante el período de activación cargar datos de marcador de posición
almacenados localmente. Luego, una vez que aparece la interfaz de usuario inicial y el
usuario puede interactuar con la aplicación, se pueden reemplazar los datos de marcador
de posición progresivamente desde un origen remoto. Además, la lógica de activación de la
aplicación solo debe realizar trabajo necesario para que el usuario pueda empezar a usar la
aplicación. Esto puede ayudar si retrasa la carga de ensamblados adicionales, ya que los
ensamblados se cargan la primera vez que se usan.

Reducir la comunicación con servicios


web
La conexión a un servicio web desde una aplicación puede tener impacto en su rendimiento.
Por ejemplo, un aumento del uso del ancho de banda de red provocará un aumento del uso
de la batería del dispositivo. Además, los usuarios pueden estar usando la aplicación en un
entorno de ancho de banda limitado. Por lo tanto, es razonable limitar el uso de ancho de
banda entre una aplicación y un servicio web.

Un enfoque para reducir el uso de ancho de banda de una aplicación es comprimir los datos
antes de transferirlos a través de una red. Pero el uso adicional de CPU del proceso de
compresión también puede dar lugar a un mayor consumo de batería. Por lo tanto, este
equilibrio se debería evaluar cuidadosamente antes de decidir si se van a mover datos
comprimidos a través de una red.

Otro problema que hay que tener en cuenta es el formato de los datos que se mueven entre
una aplicación y un servicio web. Los dos formatos principales son lenguaje de marcado
extensible (XML) y notación de objetos JavaScript (JSON). XML es un formato de
intercambio de datos basado en texto que genera cargas de datos relativamente grandes,
porque contiene un gran número de caracteres de formato. JSON es un formato de
intercambio de datos basado en texto que genera cargas de datos compactas, lo que
reduce los requisitos de ancho de banda al enviar y recibir datos. Por lo tanto, JSON suele
ser el formato preferido para las aplicaciones móviles.

Se recomienda usar objetos de transferencia de datos (DTO) al transferir datos entre una
aplicación y un servicio web. Un DTO contiene un conjunto de datos para transferir a través
de la red. Al usar DTO, se pueden transmitir más datos en una única llamada remota, lo que
puede ayudar a reducir el número de llamadas remotas realizadas por la aplicación. Por lo
general, una llamada remota con una carga de datos mayor tarda lo mismo que una llamada
que solo lleva una carga de datos pequeña.

Los datos recuperados del servicio web deben almacenarse en caché localmente para
poder usar los datos en caché en lugar de recuperarlos repetidamente del servicio web. Al
adoptar este enfoque también es necesario implementar una estrategia adecuada de
almacenamiento en caché para actualizar los datos en la memoria caché local si cambian
en el servicio web.

Resumen
En este artículo se han descrito y explicado técnicas para aumentar el rendimiento de las
aplicaciones compiladas con la plataforma Xamarin. Colectivamente, estas técnicas pueden
reducir considerablemente la cantidad de trabajo que está realizando una CPU y la cantidad
de memoria consumida por una aplicación.
Instalación de NUnit 2.6.4 mediante NuGet

Información general
Los desarrolladores que escriben pruebas en Visual Studio para Mac o usan
Xamarin.UITest deben usar NUnit 2.6.4, debido a que NUnit 3.0 (o una versión superior) no
es compatible con Visual Studio para Mac ni Xamarin.UITest. Se producirá un error si se
intenta ejecutar pruebas unitarias en Visual Studio para Mac o Xamarin.UITests con NUnit
3.0.

[[ide name="xs"]]

En esta guía se describirá cómo instalar NUnit 2.6.4 mediante NuGet para Visual Studio
para Mac. Con estos pasos también se podrá desinstalar NUnit 3.0, en caso de que sea
necesario.

[[/ide]]

[[ide name="vs"]]

En esta guía se describirá cómo degradar NUnit 3.0 a NUnit 2.6.4 mediante NuGet en
Visual Studio 2015.

[[/ide]]

Requisitos
En esta guía se da por hecho que hay una solución existente con un proyecto de aplicación
móvil y un proyecto de prueba.

[[ide name="xs"]]
Instalación de NUnit 2.6.4 en Visual Studio
para Mac
Los pasos siguientes describen cómo instalar NUnit 2.6.4.

1. Abra el Administrador de paquetes, haga clic con el botón derecho en Paquetes y


seleccione Agregar paquetes en el menú desplegable:

2. Busque NUnit version:2.6.4. Si es necesario, Visual Studio para Mac


desinstalará NUnit 3.0 y, luego, descargará e instalará NUnit 2.6.4. En el cuadro de
diálogo Agregar paquetes, escriba el texto nunit version:2.6.4 en el campo
Buscar que se encuentra en la esquina superior derecha. Seleccione NUnit en los
resultados de la búsqueda y haga clic en el botón Agregar paquete:

Para confirmar que se instaló NUnit 2.6.4, revise el número de versión del paquete de NUnit
en el Panel de solución:

Resumen
En esta guía se ha descrito cómo cambiar NUnit 3.0 a la versión anterior NUnit 2.6.4 en
Visual Studio para Mac mediante la Consola del Administrador de paquetes.

[[/ide]]

[[ide name="vs"]]

Instalación de NUnit 2.6.4 en Visual Studio


Esta sección se centrará en el uso de la Consola del Administrador de paquetes NuGet en
Visual Studio 2015 para desinstalar NUnit 3.0 e instalar NUnit 2.6.4.

1. Inicie la Consola del Administrador de paquetes NuGet. Seleccione Herramientas


> Administrador de paquetes NuGet > Consola del Administrador de paquetes:

2. Compruebe la versión de NUnit. Si quiere, puede comprobar la versión instalada de


NUnit con el comando Get-Package -Project <UITEST PROJECT>:

[PM] Get-Package -Project [TEST PROJECT NAME]

Id Versions
ProjectName
-- --------
-----------
NUnit {3.0.1}
[TEST PROJECT NAME]
Xamarin.UITest {1.2.0}
[TEST PROJECT NAME]

Si la versión es NUnit 3.0 o superior, debe degradarla a la versión NUnit 2.6.4.

1. Desinstale NUnit 3.0. Use el cmdlet Uninstall-Package para desinstalar NUnit


3.0:

<PM> Uninstall-Package NUnit -Project <TEST PROJECT NAME>


Attempting to gather dependencies information for package
'NUnit.3.0.1' with respect to project '<TEST PROJECT NAME>',
targeting '.NETFramework,Version=v4.5'
Resolving actions to uninstall package 'NUnit.3.0.1'
Resolved actions to uninstall package 'NUnit.3.0.1'
Removed package 'NUnit.3.0.1' from 'packages.config'
Successfully uninstalled 'NUnit.3.0.1' from <TEST PROJECT NAME>

2. Instale NUnit 2.6.4. Instale Nunit 2.6.4 con el cmdlet Install-Package, tal como se
muestra en el siguiente fragmento de código:

<PM> Install-Package NUnit -Version 2.6.4 -Project <TEST PROJECT


NAME>
Attempting to gather dependencies information for package
'NUnit.2.6.4' with respect to project '<TEST PROJECT NAME>',
targeting '.NETFramework,Version=v4.5'
Attempting to resolve dependencies for package 'NUnit.2.6.4'
with DependencyBehavior 'Lowest'
Resolving actions to install package 'NUnit.2.6.4'
Resolved actions to install package 'NUnit.2.6.4'
Adding package 'NUnit.2.6.4' to folder
'Z:\Desktop\DowngradeNunit\packages'
Added package 'NUnit.2.6.4' to folder
'Z:\Desktop\DowngradeNunit\packages'
Added package 'NUnit.2.6.4' to 'packages.config'
Successfully installed 'NUnit 2.6.4' to <TEST PROJECT NAME>

Resumen
En esta guía se describió cómo degradar NUnit 3.0 a NUnit 2.6.4 en Visual Studio 2015
mediante la Consola del Administrador de paquetes.

[[/ide]]
Depuración de varios procesos

Información general
Es muy común que las soluciones modernas desarrolladas en Visual Studio para Mac
tengan varios proyectos en distintas plataformas de destino. Por ejemplo, una solución
podría contener un proyecto de aplicación para dispositivos móviles basado en los datos
proporcionados por un proyecto de servicio web. Al desarrollar esta solución, un
desarrollador podría necesitar tener ambos proyectos ejecutándose simultáneamente con el
fin de solucionar errores. A partir de la versión Cycle 9 de Xamarin, ahora es posible que
Visual Studio para Mac depure varios procesos que se ejecutan al mismo tiempo. Esto
permite establecer puntos de interrupción, inspeccionar variables y ver los subprocesos en
más de un proyecto en ejecución. Esto se conoce como depuración de varios procesos.

En esta guía se tratan algunos de los cambios realizados en Visual Studio para Mac para
admitir la depuración de varios procesos, cómo configurar las soluciones para depurar
múltiples procesos y cómo adjuntarlos a procesos existentes con Visual Studio para Mac.

Requisitos
La depuración de varios procesos requiere Visual Studio para Mac.

Cambios en el IDE
Para ayudar a los desarrolladores a depurar varios procesos, Visual Studio para Mac
incluye algunos cambios en la interfaz de usuario. Visual Studio para Mac tiene una barra
de herramientas de depuración actualizada y una nueva sección Configuración de
soluciones en la carpeta Opciones de solución. Además, el panel de subprocesos
muestra ahora los procesos en ejecución y los subprocesos para cada proceso. Visual
Studio para Mac también muestra varios paneles de depuración, uno para cada proceso,
para ciertas cosas como Resultado de la aplicación.

Configuraciones de soluciones

De forma predeterminada, Visual Studio para Mac mostrará un proyecto individual en el


área Configuración de soluciones de la barra de herramientas de depuración. Al iniciar
una sesión de depuración, este es el proyecto que Visual Studio para Mac iniciará y al que
adjuntará el depurador.

Para iniciar y depurar varios procesos en Visual Studio para Mac, es necesario crear una
configuración de soluciones. Una configuración de soluciones describe qué proyectos de
una solución deben incluirse al iniciar una sesión de depuración con un clic en el botón
Iniciar o al pulsar ⌘↩ (Cmd-Entrar). La captura de pantalla siguiente es un ejemplo de una
solución en Visual Studio para Mac que tiene varias configuraciones de soluciones:

Partes de la barra de herramientas de depuración

La barra de herramientas de depuración ha cambiado para permitir que se pueda


seleccionar una configuración de soluciones a través de un menú emergente. En esta
captura de pantalla se muestran las partes de la barra de herramientas de depuración:

1. Configuración de soluciones: para establecer la configuración de soluciones, haga


clic en la configuración de soluciones, en la barra de herramientas de depuración, y
seleccione la configuración en el menú emergente:

2. Destino de compilación: identifica el destino de compilación para los proyectos. Esto


no ha cambiado con relación a versiones anteriores de Visual Studio para Mac.

3. Destinos de dispositivo: esta opción permite seleccionar los dispositivos en los que
se va a ejecutar la solución. Es posible identificar un dispositivo o un emulador
individual para cada proyecto:

Múltiples paneles de depuración

Cuando se inicia la configuración de soluciones múltiples, algunos de los paneles de Visual


Studio para Mac aparecerán varias veces, una para cada proceso. Por ejemplo, en la
captura de pantalla siguiente se muestran dos paneles de Resultado de la aplicación para
una solución que está ejecutando dos proyectos:

Varios procesos y el subproceso activo

Cuando se encuentra un punto de interrupción en un proceso, dicho proceso detendrá la


ejecución, mientras que los demás procesos continúan ejecutándose. En un escenario de
un solo proceso, Visual Studio para Mac puede mostrar fácilmente información como
subprocesos, variables locales o resultado de la aplicación en un único conjunto de paneles.
En cambio, cuando hay varios procesos con múltiples puntos de interrupción, y
posiblemente varios subprocesos, puede resultar abrumador para el desarrollador hacer
frente a la información de una sesión de depuración que está intentando mostrar toda la
información de todos los subprocesos (y procesos) a la vez.

Para solucionar este problema, Visual Studio para Mac solo mostrará la información de un
subproceso a la vez, conocido como el subproceso activo. El primer subproceso que se
detiene en un punto de interrupción se considera el subproceso activo. El subproceso activo
es el subproceso que es el foco de atención del desarrollador. El subproceso activo
dispondrá de comandos de depuración, como Paso a paso por procedimientos ⇧⌘O
(Mayús-Cmd-O).

El panel de subproceso mostrará la información de todos los procesos y subprocesos que


se encuentran bajo comprobación en la configuración de soluciones y proporcionará
indicaciones visuales sobre cuál es el subproceso activo:

Los subprocesos se agrupan por el proceso que los hospeda. El nombre del proyecto y el
identificador del subproceso activo se muestran en negrita, y aparece una flecha hacia la
derecha en el medianil junto al subproceso activo. En la captura de pantalla anterior, el
subproceso n.º 1 en el proceso con identificador 48703 (FirstProject) es el subproceso
activo.

Al depurar varios procesos, es posible cambiar el subproceso activo para ver la información
de depuración de ese proceso (o subproceso) mediante el uso del panel de subproceso.
Para cambiar el subproceso activo, seleccione el subproceso que quiera en el panel de
subproceso y luego haga doble clic en él.

Ejecución paso a paso del código cuando se detienen varios proyectos

Cuando dos (o más) proyectos tienen puntos de interrupción, Visual Studio para Mac
pausará ambos procesos. Solo es posible recorrer el código paso a paso por
procedimientos en el subproceso activo. El otro proceso se pausará hasta que un cambio
de ámbito haga posible que el depurador cambie el foco del subproceso activo. Por ejemplo,
fíjese en la siguiente captura de pantalla en que Visual Studio para Mac depura dos
proyectos:

En esta captura de pantalla, cada solución tiene su propio punto de interrupción. Cuando se
inicia la depuración, el primer punto de interrupción que se encuentra está en la línea 10 de
MainClass en SecondProject. Dado que ambos proyectos tienen puntos de interrupción,
cada proceso se detiene. Una vez que se encuentra el punto de interrupción, cada
invocación del paso a paso por procedimientos provocará que Visual Studio para Mac
recorra el código paso a paso por procedimientos en el subproceso activo.

La ejecución paso a paso del código está limitada al subproceso activo, por lo que Visual
Studio para Mac recorrerá paso a paso, una línea de código a la vez, mientras que el otro
proceso aún está en pausa.

Si tomamos la captura de pantalla anterior como ejemplo, cuando el bucle for ha


finalizado, Visual Studio para Mac permitiría que FirstProject se ejecutara hasta que se
encontrara el punto de interrupción en la línea 11 en MainClass. Para cada comando de
paso a paso por procedimientos, el depurador avanzaría línea a línea en FirstProject,
hasta que los algoritmos heurísticos internos de Visual Studio para Mac vuelvan a cambiar
el subproceso activo a SecondProject.

Si solo uno de los proyectos tuviera establecido un punto de interrupción, únicamente se


pausaría ese proceso. El otro proyecto continuaría ejecutándose hasta que el desarrollador
lo pausara o se agregara un punto de interrupción.

Pausar y reanudar un proceso

Para pausar o reanudar un proceso, haga clic con el botón derecho en el proceso y
seleccione Pausar o Reanudar en el menú contextual:

La apariencia de la barra de herramientas de depuración cambiará según el estado de los


proyectos que se están depurando. Cuando se ejecuten varios proyectos, la barra de
herramientas de depuración mostrará los botones Pausar y Reanudar en los casos en que
haya al menos un proyecto que se esté ejecutando y un proyecto en pausa:

Al hacer clic en el botón Pausar en la barra de herramientas de depuración, se detendrán


todos los procesos que se están depurando, mientras que al hacer clic en el botón
Reanudar se reanudarán todos los procesos en pausa.

Depurar un segundo proyecto

También es posible depurar un segundo proyecto una vez que Visual Studio para Mac inicia
el primer proyecto. Una vez iniciado el primer proyecto, haga clic con el botón derecho*
en el proyecto, en el **Panel de solución, y seleccione Iniciar la depuración de
elemento:

Crear una configuración de soluciones


Una configuración de soluciones indica a Visual Studio para Mac qué proyecto se debe
ejecutar cuando se inicia una sesión de depuración con el botón Iniciar. Puede haber más
de una configuración de soluciones por solución. Esto hace posible especificar qué
proyectos se ejecutan cuando se depura el proyecto.

Para crear una nueva configuración de soluciones en Xamaring Studio:

1. Abra el cuadro de diálogo Opciones de solución en Visual Studio para Mac y


seleccione Ejecutar > Configuraciones:

2. Haga clic en el botón Nuevo, escriba el nombre de la nueva configuración de


soluciones y haga clic en Crear. La nueva configuración de soluciones aparecerá en
la ventana Configuraciones:

3. Seleccione la nueva configuración de ejecución en la lista de configuraciones. En el


cuadro de diálogo Opciones de solución se mostrará cada proyecto de la solución.
Marque cada proyecto que debe iniciarse al iniciar una sesión de depuración:

La configuración de soluciones MultipleProjects aparecerá ahora en la barra de


herramientas de depuración, lo que permite que un desarrollador depure simultáneamente
los dos proyectos.
Resumen
En esta guía se ha tratado la depuración de varios procesos en Visual Studio para Mac. Se
han detallado algunos de los cambios en el IDE para admitir la depuración de varios
procesos y se han descrito algunos de los comportamientos asociados.
Introduction to Continuous Integration
with Xamarin

Developing Xamarin Mobile Applications with


Continuous Integration

Evolve 2016: Continuous Delivery for Mobile Apps: Yes We Can!

Overview

Introduction To Continuous Integration

This section covers the different components involved with continuous integration and their
relationships. It outlines the continuous integration environments that are discussed in the
specific sections below.

Working with Continuous Integration


Environments

Using TeamCity with Xamarin


This guide discusses the steps involved with using TeamCity to compile mobile apps and
then submit them to Xamarin Test Cloud.

Using Jenkins with Xamarin

This guide illustrates how to set up Jenkins as a continuous integration server and automate
compiling mobile apps created with Xamarin. It describes how to install Jenkins on OS X,
configure it, and set up jobs to compile Xamarin.iOS and Xamarin.Android apps when
changes are committed to the version control system.
Introduction to Continuous Integration with
Xamarin

Integrating Xamarin Projects into a Continuous Build Workflow

Overview
It is common on software projects for developers to work in parallel. At some point, it is necessary to
integrate all of these parallel streams of work into one codebase that makes up the final product. In the
early days of software development, this integration was performed at the end of a project, which was a
difficult and risky process.

Continuous Integration (CI) avoid such complexities by merging every developer's changes into the
common code base on a continual basis, usually whenever any developers checks in changes to the
project's shared code repository. Each check-in triggers an automated build and runs automated tests to
verify that the newly introduced code didn’t break any existing code. In this way, CI surfaces errors and
problems immediately and ensures that all team members stay up to date with each others work. This
results in a cohesive and stable codebase.

Continuous integration systems have two main parts:

Version Control – Version Control (VC), also called source control or source code management,
consolidates all of a project's code into a single shared repository and keeps a full history of every
change to every file. This repository, often referred to as the mainline or master branch, contains the
source code that will ultimately be used to build the production or release version of the app. There
are many open source and commercial products for this task, which typically allow teams or
individuals to fork a copy of the code into secondary branches where they can make extensive
changes or conduct experiments without risk to the master branch. Once changes in a secondary
branch are validated, they can then be all together merged back into the master branch.
Continuous Integration Server – The Continuous Integration Server is responsible for collecting all
of a project's artifacts (source code, images, videos, databases, automated tests, etc.), compiling the
app, and running the automated tests. Again, there are many open source and commercial CI server
tools.

Developers typically have a working copy of one or more branches on their workstations, where work is
initially done. Once an appropriate set of work is complete, the changes are "checked into" or "committed"
to the appropriate branch, which propagates them to the working copies of other developers. This is how a
team ensures that they're all working on the same code.

Again, with continuous integration, the act of committing changes causes the CI server to build the project
and run automated tests to verify the correctness of the source code. If there are build errors or test
failures, a CI server notifies the responsible developer (via email, IM, Twitter, Growl, etc.) so he or she can
correct the problem. (CI servers can even refuse the commit if there are failures, which is called a "gated
check-in".)

The following diagram illustrates this process:

Mobile apps introduce unique challenges for continuous integration. Apps may require sensors such as the
GPS or camera that are only available on physical devices. In addition, simulators or emulators are only an
approximation of hardware and may conceal or obscure problems. In the end, it's necessary to test a
mobile app on real hardware to be confident that it's truly customer-ready.

The App Center Test addresses this particular problem by testing apps directly on hundreds of physical
devices. Developers write automated acceptances tests, which allow for powerful UI testing. Once these
tests are uploaded to App Center, the CI server can run them automatically as part of a CI process as
shown in the following diagram:
Components of Continuous Integration
There is an extensive ecosystem of commercial and open-source tools designed to support CI. This section
explains a few of the most common ones.

Version Control

Visual Studio Team Services and Team Foundation Server

Visual Studio Team Services (VSTS) and Team Foundation Server (TFS) are Microsoft's collaborative
tools for continuous integration build services, task tracking, agile planning and reporting tools, and version
control. With version control, VSTS and TFS can work with its own system (Team Foundation Version
Control or TFVC) or with projects hosted on GitHub.

Visual Studio Team Services provides services via the cloud. It's primary advantage is that it requires
no dedicated hardware or infrastructure and can be accessed from anywhere through web browsers
and through popular development tools such as Visual Studio, making it appealing for teams that are
geographically distributed. It is free for teams of five developers or less, after which additional
licenses can be purchased to accommodate a growing team.
TFS is designed for on-premises Windows servers and accessed through a local network or a VPN
connection to that network. Its primary advantage is that you fully control the configuration of the
build servers and can install whatever additional software or services are needed. TFS has a free
entry-level Express edition for small teams.

Both TFS and VSTS are tightly integrated with Visual Studio and allow developers to perform many version
control and CI tasks from within the comfort of a single IDE. The Team Explorer Everywhere plugin for
Eclipse (see below) is also available. Visual Studio for Mac does not offer any support for TFS or VSTS.

Visual Studio Team Service's build system has direct support for Xamarin projects, within which you create
a build definition for each platform you wish to target (Android, iOS, and Windows). The appropriate
Xamarin license is needed for each build definition. It's also possible to connect a local, Xamarin-capable
TFS build server to Visual Studio Team Services for this purpose. With this setup, builds that are queued to
VSTS will be delegated to the local server. For details, refer to Deploy and configure a build server.
Alternately, you can use another build tool such as Jenkins or Team City.

A complete summary of all Application Lifecycle Management (ALM) features of Visual Studio, Visual
Studio Team Services, and Team Foundation Server, see Application Lifecycle Management with Xamarin
Apps on MSDN.

Team Explorer Everywhere

Team Explorer Everywhere brings the power of Team Foundation Server and Visual Studio Team Services
to teams developing outside of Visual Studio. It allows developers to connect to team projects on premises
or in the cloud from Eclipse or the cross-platform command line client for OS X and Linux. Team Explorer
Everywhere provides full access to version control (including Git), work items, and build capabilities for
non-Windows platforms.

Git

Git is a popular open source version control solution that was originally developed to manage the source
code for the Linux kernel. It is a very fast, flexible system that is popular with software projects of all sizes.
It easily scales from single developers with poor Internet access to large teams that span the globe. Git
also makes branching very easy, which in turn can encourage parallel streams of development with
minimal risk.

Git can operate entirely through a web browsers, or through GUI clients that run on Linux, Mac OSX, and
Windows. It is free for public repositories; private repositories require a paid plan.

Visual Studio 2015 and Visual Studio for Mac provide native support for Git; for Visual Studio 2013 and
earlier, Microsoft provides a downloadable extension for Git. As noted above, Visual Studio Team Services
and TFS can use Git for version control instead of TFVC.

Subversion

Subversion (SVN) is a popular, open source version control system that has been in use since 2000. SVN
runs on all modern versions of OS X, Windows, FreeBSD, Linux, and Unix. Visual Studio for Mac has
native support for SVN. There are third party extensions that bring SVN support to Visual Studio.

Continuous Integration Environments

Setting up a continuous integration environment means combining a version control system with a build
service. For the latter, the two most common ones are:

Team Foundation Build is the build system of Visual Studio Team Services and TFS. It is tightly
integrated with Visual Studio, which makes it convenient for developers to trigger builds,
automatically run tests, and see the results.
Jenkins is an open-source CI server that with a rich ecosystem of plugins to support all kinds of
software development. It runs on Windows and Mac OS X. Jenkins is not integrated with any specific
IDE. Instead, it is configured and managed via a web interface. Jenkins CI is also easy to install and
configure which makes it appealing to small teams.

You can use TFS/VSTS by itself, or you can use Jenkins in combination with TFS/VSTS or Git as
described in the following sections.

Visual Studio Team Services and Team Foundation Server

As discussed, Visual Studio Team Services and Team Foundation Server provides both version control
and build services. Build services always require a Xamarin Business or Enterprise license for each target
platform.

With Visual Studio Team Services, you create a separate build definition for each target platform and enter
the appropriate license there. Once configured, VSTS will run builds and tests in the cloud. See Team
Foundation Build for more details.

With Team Foundation Server, you configure a build machine as follows for specific target platforms:

Android and Windows: Install Visual Studio and the Xamarin tools (for Android and Windows both)
and configure with your Xamarin licenses. It is also necessary to move the Android SDK to a shared
location on the server where the TFS build agent can find it. For details, see Configuring TFVC.
iOS and Xamarin: Install Visual Studio and the Xamarin tools on the Windows server with the
appropriate license. Then install Visual Studio for Mac on a network-accessible Mac OS X machine,
which will serve as a build host and create the final app package (IPA for iOS, APP for OS X).

The following diagram illustrates this topography:


It is also possible to link a local TFS server to a Visual Studio Team Services project so that VSTS builds
are delegated to the local server. For details, see Deploy and configure a build server on MSDN.

Visual Studio Team Services and Jenkins

If you use Jenkins to build your apps, you can store your code in Visual Studio Team Services or Team
Foundation Server and continue to use Jenkins for your CI builds. You can trigger a Jenkins build when
you push code to your team project's Git repository or when you check code in to TFVC. For details, see
Jenkins with Visual Studio Team Services.

Git And Jenkins

Another common CI environment can be entirely OS X based. This scenario involves using Git for source
code control and Jenkins for the build server. Both of these are running on a single Mac OS X computer
with Visual Studio for Mac installed. This is very similar to the Visual Studio Team Services + Jenkins
environment discussed in the previous section:
⚠️ Note: Jenkins is not supported by Xamarin.

Summary
This document introduced the concept of continuous integration and the advantages it brings to software
development teams. The importance of version control was discussed along with the role and
responsibilities of the build server. The document then went on to discuss some of the tools that can be use
for source code control and build servers. We also introduced App Center Test, which helps developers
publish great apps by running automated tests that will prove the quality and functionality of their apps.
More detailed documentation on submitting apps and tests to App Center can be found here. Finally, to
help understand how all these tools and components fit together, we outlined several different CI
environments that organizations might establish for continuous integration. For more information using
Visual Studio Team Services and Team Foundation Server with Xamarin projects, see Configuring TFVC
and this Continuous Integration introduction. Likewise, if you're using Jenkins, see Using Jenkins with
Xamarin for detailed information on setting up a continuous integration.
Using Team City with Xamarin

Configuring Team City For Continuous Integration with Xamarin

Overview
As discussed in the Introduction to Continuous Integration guide, continuous integration (CI) is a useful practice
when developing quality mobile applications. There are many viable options for continuous integration server
software; this guide will focus on TeamCity from JetBrains.

There are several different permutations of a TeamCity installation. The following is a list of some of these:

Windows Service – In this scenario, TeamCity starts up when Windows boots as a Windows Service. It
must be paired with a Mac Build Host to compile any iOS applications.

Launch Daemon on OS X – Conceptually, this is very similar to running as a Windows Service described
in the previous step. By default the builds will be run under the root account.

User Account on OS X – It is possible to run TeamCity under a user account that starts up each time the
user logs in.

Of the previous scenarios, running TeamCity under a user account on OS X is the simplest and easiest to setup.

There are several steps involved with setting up TeamCity:

Installing TeamCity – The installation of TeamCity is not covered in this guide. This guide assumes that
TeamCity is installed and running under a user account. Instructions on installing TeamCity can be found in
the TeamCity 8 documentation by JetBrains.

Preparing the Build Server – This step involves installing the necessary software, tools, and certificates
required to build mobile applications and prepare them for distribution.

Creating A Build Script – This step is not strictly necessary, but a build script is a useful aid to building
applications unattended. Using a build script will help with troubleshooting build issues that may arise and
provides a consistent, repeatable way to create the binaries for distribution, even if continuous integration is
not practiced.

Creating A TeamCity Project – Once the previous three steps are completed, we must create a TeamCity
project that will contain all of the meta-data necessary to retrieve the source code, compile the projects,
and submit the tests to Xamarin Test Cloud.
Requirements
Experience with Xamarin Test Cloud is required.

Familiarity with TeamCity 8.1 is required. The installation of TeamCity is beyond the scope of this document. It is
assumed that TeamCity is installed on OS X Mavericks and is running under a regular user account and not the
root account.

The build server should be a stand-alone computer, running OS X, that is dedicated to continuous integration.
Ideally, the build server will not be responsible for any other roles, such as a database server, web server, or
developer workstation.

⚠️ This guide does not cover a "headless" installation of Xamarin.

Preparing the Build Server

A crucial step in configuring a build server is to install all of the necessary tools, software, and certificates to build
the mobile applications. It is important that the build server be able to compile the mobile solution and run any
tests. To minimize configuration issues, the software and tools should be installed in the same user account that
is hosting TeamCity. The following is a list of what is required:

1. Visual Studio for Mac – This includes Xamarin.iOS and Xamarin.Android.


2. Login to the Xamarin Component Store – This is an optional step and is only required if your application
uses Components from the Xamarin Component store. Proactively logging into the Component store at this
point will prevent any issues when a TeamCity build tries to compile the application.
3. Xcode – Xcode is required to compile and sign iOS applications.
4. Xcode Command Line Tools – This is described in step 1 of the Installation section of the Updating Ruby
with rbenv guide.
5. Signing Identity & Provisioning Profiles – Import the certificates and provisioning profile via XCode.
Please see Apple’s guide on Exporting Signing Identities and Provisioning Profiles for more details.
6. Android Keystores – Copy the required Android keystores to a directory that the TeamCity user has
access to, i.e. ~/Documents/keystores/MyAndroidApp1.
7. Calabash – This is an optional step if your application has tests written using Calabash. Please see the
Installing Calabash on OS X Mavericks guide and the Updating Ruby with rbenv guide for more
information.

The following diagram illustrates all of these components:


Once all of the software has been installed, log in to the user account and confirm that all of the software has
been properly installed and is working. This should involve compiling the solution and submitting the application
to Test Cloud. This can be greatly simplified by running the build script, as described in the next section.

Create a Build Script


Although it is entirely possible for TeamCity to handle all aspects of compiling and submitting the mobile
applications to Test Cloud by itself, it is strongly recommended to create a build script. A build script provides the
following advantages:

1. Documentation – A build script serves as a form of documentation on how the software is built. This
removes some of the “magic” that is associated with deploying the application and allows developers to
concentrate on functionality.
2. Repeatability – A build script ensures that each time the application is compiled and deployed, it happens
in exactly the same way, regardless of who or what does the work. This repeatable consistency removes
any issues or errors that might creep in due to an incorrectly executed build or human error.
3. Versioning – A build script can be included in the source control system. This means that changes to the
build script can be tracked, monitored, and corrected if errors or inaccuracies are found.
4. Prepare the Environment – A build script can include logic to install any required 3rd party dependencies.
This will ensure that the applications are built with the proper components.

The build script can be as simple as a Powershell file (on Windows) or a bash script (on OS X). When creating
the build script, there are several choices for scripting languages:

Rake – this is a Domain Specific Language (DSL) for building projects, based on Ruby. Rake has the
advantage of popularity and a rich ecosystem of libraries.

psake – this is a Windows Powershell library for building software

FAKE – this is a DSL based in F# which makes it possible to utilize existing .NET libraries if necessary.

Which scripting language is used depends on your preferences and requirements. The TaskyPro-Calabash
example contains an example of using Rake as a build script.

ℹ️ It is possible to use an XML based build system such as MSBuild or NAnt, but these lack the
expressiveness and maintainability of a DSL that is dedicated to building software.

Parameterizing The Build Script

The process of building and testing software requires information that should be kept secret. In particular creating
an APK may require a password for the keystore and/or the key alias in the keystore. Likewise, Test Cloud
requires an API key that is unique to a developer. These types of values should not be hard coded in the build
script. Instead they should be passed as variables to the build script.

Less sensitive are values such as the iOS device ID or the Android device ID that identify what devices Test
Cloud should use for test runs. These are not values that need to be protected, but they may change from build
to build.

Storing these types of variables outside of the build script also makes it easier to share the build script within an
organization, with developers for example. Developers may use the exact same script as the build server, but can
use their own keystores and API keys.

There are two possible options for storing these sensitive values:

A configuration file – To protect the Test Cloud API key this value should not be checked into version
control. The file can be created for each machine. How values are read from this file depends on the
scripting language used.

Environment variables – these can be easily set on a per-machine basis and ared independent of the
underlying scripting language.

There are advantages and disadvantages to each of these choices. TeamCity works nicely with environment
variables, so this guide will recommend this technique when creating build scripts.

Build Steps

The build script must be able to perform the following steps:

Compile the Application – This includes signing the application with the correct provisioning profile.

Submit the Application to Xamarin Test Cloud – This includes signing and zip aligning the APK with the
appropriate keystore.

These two steps will be explained in more detail below.

Compiling a Xamarin.iOS Application

Compiling a Xamarin.Android Application

To compile an Android application, use xbuild (or msbuild on Windows):

/Library/Frameworks/Mono.framework/Commands/xbuild /t:SignAndroidPackage
/p:Configuration=Release /path/to/android.csproj

Notice that to compile the Xamarin Android application xbuild uses the project, and that to build the iOS
application xbuild requires the solution.

Submitting Xamarin.UITests to Test Cloud

UITests are submitted using the test-cloud.exe application, as shown in the following snippet:

test-cloud.exe <path-to-apk-or-ipa-file> <test-cloud-team-api-key> --devices


<device-selection-id> --assembly-dir <path-to-tests-containing-test-assemblies> --
nunit-xml report.xml --user <email>
When the test is run, the test results will be returned in the form of an NUnit style XML file called report.xml.
TeamCity will display the information in the Build Log.

For more information about how to submit UITests to Test Cloud, consult Xamarin’s guide on Submitting Tests to
Test Cloud.

Submitting Calabash Tests to Test Cloud

Calabash tests are submitted using the test-cloud gem, as shown in the following snippet:

test-cloud submit /path/to/APK-or-IPA <test-cloud-team-api-key> --devices <device-


id> --user <email>

To submit an Android application to Test Cloud, it is necessary to first rebuild the APK test server using calabash-
android:

$ calabash-android build </path/to/signed/APK>


$ test-cloud submit /path/to/APK <test-cloud-team-api-key> --devices
<ANDROID_DEVICE_ID> --profile=android --config=config/cucumber.yml --pretty

For more information on submitting Calabash tests, please consult Xamarin’s guide on Submitting Calabash
Tests to Test Cloud.

Creating a TeamCity Project

Once TeamCity is installed and Visual Studio for Mac can build your project, it is time to create a project in
TeamCity to build the project and submit it to Test Cloud.

1. Started by logging into TeamCity via the web browser. Navigate to the Root Project:
Underneath the Root Project, create a new sub-project:

2. Once the sub-project has been created, add a new Build Configuration:

3. Attach a VCS project to the Build Configuration. This is done via the Version Control Setting screen:
If there is no VCS project created, you have the option to create one from the New VCS Root page shown
below:
Once the VCS root has been attached, TeamCity will checkout the project and try to auto detect build
steps. If you are familiar with TeamCity, then you can select one of the detected build steps. It is safe to
ignore the detected build steps for now.

4. Next, configure a Build Trigger. This will queue up a build when certain conditions are met, such as when a
user commits code to the repository. The following screenshot shows how to add a build trigger:

An example of configuring a build trigger can be seen in the following screenshot:


5. The previous section, Parameterizing the Build Script, suggested storing some values as environment
variables. These variables can be added to the build configuration via the Parameters screen. Add the
variables for the Test Cloud API Key, the iOS device ID, and the Android Device ID as shown in the
screenshot below:

6. The final step is to add a build step that will invoke the build script to compile the application and enqueue
the application to Test Cloud. The following screenshot is an example of a build step that uses a Rakefile to
build an application:
7. At this point, the build configuration is complete. It is a good idea to trigger a build to confirm that the
project is properly configured. A good way to do this is to commit a small, insignificant change to the
repository. TeamCity should detect the commit and start a build.

8. Once the build has completed, inspect the build log and see if there are any problems or warnings with the
build that require attention.

Summary

This guide covered how to use TeamCity to build Xamarin Mobile applications and then submit them to Test
Cloud. We discussed creating a build script to automate the build process. The build script takes care of
compiling the application, submitting to Test Cloud, and waiting for the results

Then we covered how to create a project in TeamCity that will queue a build each time a developer commits code
and will call the build script.
Using Jenkins with Xamarin

Configuring Jenkins to Power a Xamarin Continuous Integration on


OS

Overview
Introduction to Continuous Integration with Xamarin introduces continuous integration as a useful software
development practice that provides early warning of broken or incompatible code. CI allows developers to
address issues and problems as they arise, and keeps the software in a suitable state for deployment. This
walkthrough covers how to use the content from both documents together.

This guide shows how to install Jenkins on a dedicated computer running OS X, and configure it to run
automatically when the computer starts up. Once Jenkins is installed, we will install additional plugins to support
MS Build. Jenkins supports Git out of the box. If TFS is being used for source code control, an additional plugin
and command line utilities must also be installed.

Once Jenkins is configured and any necessary plugins have been installed, we will create one or more jobs to
compile the Xamarin.Android and Xamarin.iOS projects. A job is a collection of steps and metadata required to
perform some work. A job typically consists of the following:

Source Code Management (SCM) – This is a meta-data entry in the Jenkins configuration files that
contains information on how to connect to source code control and what files to retrieve.
Triggers – Triggers are used to start a job based on certain actions, such as when a developer commits
changes to the source code repository.
Build Instructions – This is a plugin or a script that will compile the source code and produce a binary that
can be installed on mobile devices.
Optional Build Actions – This could include running unit tests, performing static analysis on the code,
signing code, or starting another job to perform other build related work.
Notifications – A job may send out some kind of notification about the status of a build.
Security – Although optional, it is strongly recommended that the Jenkins security features also be
enabled.

This guide will walk through how to setup a Jenkins server covering each of these points. By the end of it, we
should have a good understanding of how to setup and configure Jenkins to create IPA and APK’s for our
Xamarin mobile projects.
Requirements
The ideal build server is a stand-alone computer dedicated to the sole purpose of building and possibly testing
the application. A dedicated computer ensures that artifacts that might be required for other roles (such as that of
a web server) do not contaminate the build. For example, if the build server is also acting as a web server, the
web server may require a conflicting version of some common library. Because of this conflict the web server
may not function properly or Jenkins may create builds that do not work when deployed to users.

The build server for Xamarin mobile apps is set up very much like a developer’s workstation. It has a user
account in which Jenkins, Visual Studio for Mac, and Xamarin.iOS and Xamarin.Android will be installed. All of
the code signing certificates, provisioning profiles, and key stores must be installed as well. Typically the build
server's user account is separate from your developer accounts - be sure to install and configure all the software,
keys, and certificates while logged in with the build server user account.

The following diagram illustrates all of these elements on a typical Jenkins build server:
iOS applications can only be built and signed on a computer running Mac OS X. A Mac Mini is a reasonable
lower-cost option, but any computer capable of running OS X 10.10 (Yosemite) or higher is sufficient.

If TFS is being used for source code control, you will want to install Team Explorer Everywhere, available from
Microsoft. Team Explorer Everywhere provides cross-platform access to TFS at the Terminal in OS X.

Installing Jenkins
The first task to using Jenkins is to install it. There are three ways to run Jenkins on OS X:

As a daemon, running in the background.


Inside a servlet container such as Tomcat, Jetty, or JBoss.
As a normal process running under a user account.

Most traditional continuous integration applications run in the background, either as a daemon (on OS X or *nix)
or as a service (on Windows). This is suitable for scenarios where there is no GUI interaction required, and where
the setup of the build environment can be easily performed. Mobile apps also require keystores and signing
certificates that might be problematic to access when Jenkins is running as a daemon. Because of these
concerns, this document focuses on the third scenario – running Jenkins under a user account on the build
server.

Jenkins.App is a handy way to install Jenkins. This is an AppleScript wrapper that simplifies the starting and
stopping of a Jenkins server. Instead of running in a bash shell, Jenkins runs as an app with icon in the Dock, as
shown in the following screenshot:
Starting or stopping Jenkins is as simple as starting or stopping Jenkins.App.

To install Jenkins.App, download the latest version from the project’s download page, pictured in the screenshot
below:
Extract the zip file to the /Applications folder on your build server, and start it just like any other OS X
application. The first time you start up Jenkins.App, it will present a dialog informing you that it will download
Jenkins:

Once Jenkins.App has finished its download, it will display another dialog asking you if you would like to
customize the Jenkins startup, as seen in the following screenshot:

Customizing Jenkins is optional and does not have to be performed each time the app is started – the default
settings for Jenkins will work for most situations.

If it is necessary to customize Jenkins, click on the Change defaults button. This will present you with two
consecutive dialogs: one that asks for Java command line parameters, and another that asks for Jenkins
command line parameters. The following two screenshots show these two dialogs:
Once Jenkins is running, you may want to set it as a login item so that it will start up each time the user logins in
to the computer. You can do this by right-clicking on the Jenkins icon in the Dock and choosing Options…Open
at Login, as shown in the following screenshot:

This will cause Jenkins.App to automatically launch each time the user logs in, but not when the computer boots
up. It is possible to specify a user account that OS X will use to automatically login with at boot time. Open the
System Preferences, and select the User & Groups icon as shown in this screenshot:
Click on the Login Options button, and then choose the account that OS X will use for login at boot time.

At this point Jenkins has been installed. However, if we want to build Xamarin mobile applications, we will need
to install some plugins.

Installing Plugins

When the Jenkins.App installer has completed, it will start Jenkins and launch the web browser with the URL
http://localhost:8080, as shown in the screenshot below:
From this page, select Jenkins > Manage Jenkins > Manage Plugins from the menu in the upper left hand
corner, as shown in the screenshot below:

This will display the Jenkins Plugin Manager page. If you click on the Available tab, you will see a list of over
600 plugins that can be downloaded and installed. This is pictured in the screenshot below:

Scrolling through all 600 plugins to find a few can be tedious and error prone. Jenkins provides a Filter search
field in the upper right-hand corner of the interface. Using this Filter field to search will simplify locating and
installed one or all of the following plugins:

Jenkins MSBuild Plugin – This plugin makes it possible to build Visual Studio and Visual Studio for Mac
solutions (.sln) and projects (.csproj).
Environment Injector Plugin – This is an optional but useful plugin that makes it possible to set
environment variables at the job and build level. It also offers extra protection for variables such as the
passwords used to code sign the application. It is sometimes abbreviated as the EnvInject Plugin .
Team Foundation Server Plugin – This is an optional plugin that is only required if you are using Team
Foundation Server or Team Foundation Services for source code control.

Jenkins supports Git without any extra plugins.

After installing all of the plugins, you’ll want to restart Jenkins and configure the global settings for each plugin.
The global settings for a plugin can be found by selecting Jenkins > Manage Jenkins > Configure System from
the upper left hand corner, as shown in the screenshot below:

When you select this menu option, you will be taken to the Configure System [Jenkins] page. This page
contains sections to configure Jenkins itself and to set some of the global plugin values. The screenshot below
illustrates an example of this page:
Configuring the MSBuild Plugin

The MSBuild plugin must be configured to use /Library/Frameworks/Mono.framework/Commands/xbuild to


compile Visual Studio for Mac solution and project files. Scroll down the Configure System [Jenkins] page until
the Add MSBuild button appears, as shown in the screenshot below:

Click on this button, and fill out the Name and Path to MSBuild fields on the form that appears. The name of
your MSBuild installation should be something meaningful, while the Path to MSBuild should be the path to
xbuild, which is typically /Library/Frameworks/Mono.framework/Commands/xbuild. After we save the
changes by clicking the Save or the Apply button at the bottom of the page, Jenkins will be able to use xbuild to
compile your solutions.

Configuring the TFS Plugin

This section is mandatory if you intend to use TFS for your source code control.

In order for an OS X workstation to interact with a TFS server, Team Explorer Everywhere must be installed on
the workstation. Team Explorer Everywhere is a set of tools from Microsoft that includes a cross-platform
command line client for accessing TFS. Team Explorer Everywhere can be downloaded from Microsoft and
installed in three steps:

1. Unzip the archive file to a directory that is accessible to the user account. For example, you might unzip the
file to ~/tee.

2. Configure the shell or system path to include the folder that holds the files that were unzipped in step one
above. For example,

echo export PATH~/tee/:$PATH' >> ~/.bash_profile

3. To confirm that Team Explorer Everywhere is installed, open a terminal session, and execute the tf
command. If tf is properly configured, you will see the following output in your terminal session:

$ tf
Team Explorer Everywhere Command Line Client (version 11.0.0.201306181526)

Available commands and their options:

Once the command line client for TFS is installed, Jenkins must be configured with the full path to the tf
command line client. Scroll down the Configure System [Jenkins] page until you find the Team Foundation
Server section, as shown in the following screenshot:
Enter the full path to the tf command, and click the Save button.

Configure Jenkins Security

When first installed, Jenkins has security disabled, so it is possible for any user to set up and run any kind of job
anonymously. This section covers how to configure security using the Jenkins user database to configure
authentication and authorization.

Security settings can be found by selecting Jenkins > Manage Jenkins > Configure Global Security, as shown
in this screenshot:
On the Configure Global Security page, check the Enable Security checkbox and the Access Control form
should appear, similar to the next screenshot:

Toggle the radio button for Jenkins’ own user database in the Security Realm Section, and ensure that Allow
users to sign up is also checked, as illustrated in the following screenshot:
Finally, restart Jenkins and create a new account. The first account that is created is the root account, and this
account will be automatically promoted to an administrator. Navigate back to the Configure Global Security
page, and check off the Matrix-based security radio button. The root account should be granted full access, and
the anonymous account should be given read-only access, as shown in the following screenshot:
Once these settings are saved and Jenkins is restarted, security will be turned on.

Disabling Security

In the event of a forgotten password or Jenkins-wide lockout, it is possible to disable security by following these
steps:

1. Stop Jenkins. If you are using Jenkins.app, you can do this by right-clicking on the Jenkins.App icon in the
Dock, and selecting Quit from the menu that pops up:


2. Open the file ~/.jenkins/config.xml in a text editor.


3. Change the value of the <usesecurity></usesecurity> element from true to false.
4. Delete the <authorizationstrategy></authorizationstrategy> and the <securityrealm>
</securityrealm> elements from the file.
5. Restart Jenkins.

Setting up a Job
At the top level, Jenkins organizes all of the various tasks required to build software into a job. A job also has
metadata associated with it, providing information about the build such as how to get the source code, how often
the build should run, any special variables that are necessary for building, and how to notify developers if the
build fails.

Jobs are created by selecting Jenkins > New Job from the menu in the upper right hand corner, as shown in the
following screenshot:

This will display the New Job [Jenkins] page. Enter a name for the job, and select the Build a free-style
software project radio button. The following screenshot shows an example of this:
Clicking the OK button presents the configuration page for the job. This should resemble the following
screenshot:
Jenkins organizes jobs in a directory on the hard disk located at the following path: ~/.jenkins/jobs/[JOB NAME]

This folder contains all the files and artifacts specific to the job such as logs, configuration files, and the source
code that needs to be compiled.

Once the initial job has been created, it must be configured with one or more of the following:

The source code management system must be specified.


One or more build actions must be added to the project. These are the steps or tasks required to build the
application.
The job must be assigned one build trigger – a set of instructions informing Jenkins how often to retrieve
the code and build the final project.

Configuring Source Code Control

The first task Jenkins does is retrieve the source code from the source code management system. Jenkins
supports many of the popular source code management systems available today. This section covers two
popular systems, Git and Team Foundation Server. Each of these source code management systems is
discussed in more detail in the sections below.

Using Git for Source Code Control

If you are using TFS for source code control, skip this section and proceed to the next section using TFS.

Jenkins supports Git out of the box – no extra plugins are necessary. To use Git, click on the Git radio button and
enter the URL for the Git repository, as shown in the following screenshot:
Once the changes are saved, Git configuration is complete.

Using TFS for Source Code Management

This section only applies to TFS users.

Click on the Team Foundation Server radio button and the TFS configuration section should appear, similar to
what is in the following screenshot:
Provide the necessary information for TFS. The following screenshot shows an example of the completed form:

Testing The Source Code Control Configuration

Once the appropriate source code control has been configured, click Save to save the changes. This will return
you to the home page for the job, which will resemble the following screenshot:
The simplest way to validate that the source code control is properly configured is to trigger a build manually,
even though there are no build actions specified. To start a build manually, the home page of the job has a Build
Now link in the menu on the left hand side, as shown in the screenshot below:

When a build has been started, the Build History dialog displays a flashing blue circle, a progress bar, the build
number and the time that the build started, similar to the following screenshot:
If the job succeeds, a blue circle will be displayed. If the job fails, a red circle will be displayed.

To help with troubleshooting problems that might arise as part of the build, Jenkins will capture all of the console
output for the job. To see the console output, click on the job in Build History, and then on the Console Output
link in the left hand menu. The following screenshot shows the Console Output link, as well as some of the
output from a successful job:

Location of Build Artifacts

Jenkins will retrieve the entire source code into a special folder called a workspace. This directory can be found
inside the folder at the following location:

~/.jenkins/jobs/[JOB NAME]/workspace

The path to the workspace will be stored in an environment variable named $WORKSPACE.

It is possible to browse the workspace folder in Jenkins by navigating to the landing page for a job, and then
clicking on the Workspace link in the left hand menu. The following screenshot shows an example of the
workspace for a job named HelloWorld:
Build Triggers

There are several different strategies for initiating builds in Jenkins – these are known as build triggers. A build
trigger helps Jenkins decide when to start a job and build the project. Two of the more common build triggers are:

Build periodically – This trigger causes Jenkins to start a job at specified intervals, such as every two
hours or at midnight on weekdays. The build will start regardless of whether there have been any changes
in the source code repository.
Poll SCM – This trigger will poll source code control on a regular basis. If any changes have been
committed to the source code repository, Jenkins will start a new build.

Polling SCM is a popular trigger because it provides quick feedback when a developer commits changes that
cause the build to break. This is useful for alerting teams that some recently committed code is causing
problems, and lets the developers address the problem while the changes are still fresh in mind.

Periodic builds are often used to create a version of the application that can be distributed to testers. For
example, a periodic build might be scheduled for Friday evening so that members of the QA team can test the
work of the previous week.

Compiling a Xamarin.iOS Applications

Xamarin.iOS projects can be compiled at the command line using xbuild or msbuild. The shell command will
execute in the context of the user account that is running Jenkins. It is important that the user account has
access to the provisioning profile so that the application can be properly packaged for distribution. It is possible to
add this shell command to the job configuration page.
Scroll down to the Build section. Click the Add build step button and select Execute shell, as illustrated by the
following screenshot:

Building a Xamarin.Android Project

Building a Xamarin.Android project is very similar in concept to building a Xamarin.iOS project. To create an APK
from a Xamarin.Android project, Jenkins must be configured to perform the following two steps:

Compile the project using the MSBuild plugin


Sign and zip align the APK with a valid release keystore.

These two steps will be covered in more detail in the next two sections.

Creating the APK

Click on the Add build step button, and select Build a Visual Studio project or solution using MSBuild, as
shown in the screenshot below:
Once the build step is added to the project, fill in the form fields that appear. The following screenshot is one
example of the completed form:

This build step will execute xbuild in the $WORKSPACE folder. The MSBuild Build File is set to the
Xamarin.Android.csproj file. The Command Line Arguments specify a release build of the target
PackageForAndroid. The product of this step will be an APK that at the following location:

$WORKSPACE/[PROJECT NAME]/bin/Release

The following screenshot shows an example of this APK:


This APK is not ready for deployment, as it has not been signed with a private keystore and must be zip aligned.

Signing and Zipaligning the APK for Release

Signing and zipaligning the APK are technically two separate tasks that are performed by two separate command
line tools from the Android SDK. However, it is convenient to perform them in one build action. For more
information about signing and zipaligning an APK, see Xamarin’s documentation on preparing an Android
application for release.

Both of these commands require command line parameters that may vary from project to project. In addition,
some of these command line parameters are passwords that should not appear in the console output when the
build is running. We’ll store some of these command line parameters in environment variables. The environment
variables required for signing and/or zip aligning are described in the table below:

Environment
Description
Variable

KEYSTORE_FILE This is the path to the keystore for signing the APK

KEYSTORE_ALIAS The key in the keystore that will be used to sign the APK.

INPUT_APK The APK that is created by `xbuild`.

SIGNED_APK The signed APK produced by `jarsigner`.

FINAL_APK This is the zip aligned APK that is produced by `zipalign`.

This is the password that is used to access the contents of the keystore for singing the
STORE_PASS
file.

As described in the Requirements section, these environment variables can be set during the build using the
EnvInject plugin. The job should have a new build step added based on the Inject environment variables, as
shown in the next screenshot:

In the Properties Content form field that will appear, environment variables are added, one per line, in the
following format:

ENVIRONMENT_VARIABLE_NAME = value
The following screenshot shows the environment variables that are required for signing the APK:

Notice that some of the environment variables for the APK files are built on the WORKSPACE environment
variable.

The final environment variable is the password to access the contents of the keystore: STORE_PASS. Passwords
are sensitive values that should be obscured or omitted in log files. The EnvInject plugin can be configured to
protect these values so that they do not show in logs.

Immediately before the Build section of the job configuration is a Build Environment section. When the Inject
passwords checkbox is toggled, some form fields to appear. These form fields are used to capture the name
and value of the environment variable. The following screenshot is an example of adding the STORE_PASS
environment variable:

Once the environment variables have been initialized, the next step is to add a build step for signing and zip
aligning the APK. Immediately after the build step to insert the environment variables will be another Execute
shell command build that will execute jarsigner and zipalign. Each command will take up one line, as
shown in the following snippet:

jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore $KEYSTORE_FILE -


storepass $STORE_PASS -signedjar $SIGNED_APK $INPUT_APK $KEYSTORE_ALIAS
zipalign -f -v 4 $SIGNED_APK $FINAL_APK

The following screenshot shows an example of how to enter the jarsigner and zipalign commands into the
step:

Once all the build actions are in place, it is good practice to trigger a manual build to verify everything is working.
If the build fails, the Console Output should be reviewed for information on what caused the build to fail.

Submitting Tests to Test Cloud

Automated tests can be submitted to Test Cloud using shell commands. For more information about setting up a
Test Run in Xamarin Test Cloud, we have guides for using Xamarin.UITest or Calabash.

Summary
In this guide we introduced Jenkins as a build server on Mac OS X, and configured it to compile and prepare
Xamarin mobile applications for release. We installed Jenkins on a Mac OS X computer along with several
plugins to support the build process. We created and configured a job that will pull code from either TFS or Git,
and then compile that code into a release ready application. We also explored two different ways to schedule
when jobs should be run.
F#
F# combines the succinctness, expressivity and composability of type-inferred functional
programming, the compile-time safety of strongly-typed code, and the runtime support,
libraries, interoperability, tools, and object model of .NET.

F# is now available "out of the box" as a programming language to Xamarin users on all of
the Xamarin-supported platforms: Android, OS X, and iOS.

Getting Started with F#


F# Samples

F# Features in Visual Studio for Mac


There are a number of new F# features available in Visual Studio for Mac, including:

F# 4 support
F# PCL support
F# Shared Project support
Code navigation improvements
Syntax highlighting in F# Interactive
F# templates for Xamarin.Forms projects
and a lot more...
Getting Started with F#

Requirements
F# is included by default in Visual Studio for Mac.

On Windows, you must install standalone F# compiler tools, per the instructions on the FSharp.org site.

Creating an F# Project
Creating a new F# application is done in the same New Project window used for C#.

In Visual Studio for Mac choose File > New Solution. In the New Project dialog, select a project template.
Use the drop-down to the right of the template to choose the language you wish to use:

Select your project type and click Next to name and create it.

You are now ready to start creating some great F# applications!

Learning to use F

An F# tutorial can also be created from within the New Solution dialog in Visual Studio for Mac. Navigate
to Other > .NET > F# Tutorial, as detailed in the image below:
This opens a new interactive solution. Exploring this is a great way to get to grips with the basics of the
language.

Check out the list of samples to see F# in action.

References

There is a plethora of information online for getting up to speed with the F# language, covering all
proficiencies. Listed below are a few of our recommendations:
F# Open Organization
F# Learning Portal
Visual F# Development Portal
Visual F# Code Gallery
Visual F# Math/Stats Programming
Visual F# Charting
F# Samples
This page links to some F# samples using Xamarin.

iOS

The FSSceneKit City sample shows how to create a randomly generated city using SceneKit
and F#. There's also an "Oculus Thrift" (Google Cardboard) Edition.

Shallow demonstrates a fun swipe-user-interface built with F# for iOS.

Mac

FSEvent Watcher is a sample Mac OS X app written with F#.


Xamarin.Forms

A number of samples for the Xamarin.Forms book have been ported to F#. These links take
you to the github location for each chapter:

Chapter 2. Anatomy of an app


Chapter 3. Deeper into text
Chapter 4. Scrolling the stack
Chapter 5. Dealing with sizes
Chapter 6. Button clicks
Chapter 7. XAML vs. code
Chapter 8. Code and XAML in harmony
Getting Started with ASP.NET Core

Overview
Visual Studio for Mac makes it easy to develop your app’s service with its support for the latest ASP.NET
Core Web development platform. ASP.NET Core runs on .NET Core, the latest evolution of the .NET
Framework and runtime. It’s been tuned for fast performance, factored for small install sizes, and re-
imagined to run on Linux and macOS, as well as Windows.

Installing .NET Core


.NET Core is automatically installed when you install Visual Studio for Mac.

Creating an ASP.NET Core app in Visual Studio


for Mac
Open Visual Studio for Mac. On the welcome page select New Project...

This will display the New Project dialog, allowing you to select a template to create your application.

There are a number of projects that will provide you with a pre-built template to start building your
ASP.NET Core Application. These are:

.NET Core > ASP.NET Core Empty Web Application (illustrated in the screenshot below)
Multiplatform > App > Connected App

Select the ASP.NET Core Empty Web Application and press Next. Give the Project and Name and press
Create. This creates a new ASP.NET Core app, that should look similar to the image below:
This creates a web application with two default files: Program.cs and Startup.cs, and a Dependencies
folder, which contains your project’s NuGet package dependencies such as ASP.NET Core, the .NET Core
framework, and the MSBuild targets that build the project:

Program.cs

Open and inspect the Program.cs file in your project. Notice that two things are happening in the Main
method – the entry into your app:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

host.Run();
}

An ASP.NET Core app creates a web server in its main method by configuring and launching a host via an
instance of WebHostBuilder. This builder provides methods to allow the host to be configured. In the
template app the following configurations are used:

UseKestrel: Specifies the Kestrel server will be used by the app


UseContentRoot(Directory.GetCurrentDirectory()): Uses the web project's root folder
as the app's content root when the app is started from this folder
.UseIISIntegration(): Specifies that the app should work with IIS. To use IIS with ASP.NET
Core both UseKestrel and UseIISIntegration need to be specified.

.UseStartup<Startup>(): Specifies the Startup class.

The Build and Run methods build the IWebHost that will host the app and start it listening for
incoming HTTP requests.

Startup.cs

The Startup class for your app is specified in the UseStartup() method on the WebHostBuilder. It is in
this class that you will specify the request handling pipeline, and where you configure any services.

Open and inspect the Startup.cs file in your project:

public class Startup


{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();

if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.Run(async (context) =>


{
await context.Response.WriteAsync("Hello World!");
});
}
}

This Startup class must always adhere to the following rules:

It must always be public


It must contain the two public methods: ConfigureServices and Configure

The ConfigureServices method defines the services that will be used by your app.

The Configure allows you to compose your request pipeline using Middleware. These are components
used within an ASP.NET application pipeline to handle requests and responses. The HTTP pipeline
consists of a nuber of request delegates, called in sequence. Each delegate can choose to either handle
the request itself, or pass it to the next delegate.

You can configure delegates by using the Run,Map, and Use methods on IApplicationBuilder, but
the Run method will never call a next delegate and should always be used at the end of your pipeline.

The Configure method of the pre-built template is built to do a few things. First, it configures an exception
handling page for use during development. Then, it sends a response to the requesting web page with a
simple "Hello World".

This simple Hello, World project can run now without any additional code being added. To run the app, and
view it in your browser, press the Play (Triangular) button in the toolbar:
Visual Studio for Mac uses a random port to launch your web project. To find out what port this is, open the
Application Output, which is listed under View > Pads. You should find output similar to that shown below:

Open your browser of choice, and enter http://localhost:5000/, replacing the 5000 with the port
that Visual Studio output in step 5. You should see the text Hello World:

Troubleshooting
If you need to install .NET Core manually on macOS 10.11 and higher, do the following:

1. Before you start installing .NET Core, ensure that you have updated all OS updates to the latest
stable version. You can check this by going to the App Store application, and selecting the Updates
tab.

2. Follow the steps listed on the .NET Core site.

Make sure to complete all four steps successfully to ensure that .NET Core is installed successfully.
Summary
This guide gave an introduction to ASP.NET Core. It describes what it is, when to use it, and provided
information on using it in Visual Studio for Mac. For more information on the next steps from here, refer to
the ASP.NET Core docs, and this article on Creating Backend Services for Native Mobile Applications
which shows how to build a REST service using ASP.NET Core for a Xamarin.Forms app.
Advanced
This section contains documents that explain some more advanced cross-platform
application features and concepts.

Async Support Overview

Version 5 of C# introduced two new keywords to express asynchronous operations: async


and await. These keywords let you write simple code that utilizes the Task Parallel Library to
execute long running operations (such as network access) in another thread and easily
access the results on completion. The latest versions of Xamarin.iOS and Xamarin.Android
support async and await - this document provides explanations and an example of using the
new syntax with Xamarin.

Available Assemblies

Xamarin.iOS, Xamarin.Android, and Xamarin.Mac all ship with over a dozen assemblies.
Just as Silverlight is an extended subset of the desktop .NET assemblies, Xamarin platforms
is also an extended subset of several Silverlight and desktop .NET assemblies.

This guide provides a list of all available assemblies shipped with each platform, and show
which can be used on each platform.

C# 6 Language Features Overview

The latest version of the C# language – version 6 – continues to evolve the language to
have less boilerplate, improved clarity, and more consistency. Cleaner initialization syntax,
the ability to use await in catch/finally blocks, and the null-conditional ? operator are
especially useful.

Custom Linker Configuration


If the default set of options is not enough, you can drive the linking process with an XML file
that describes what you want from the linker.

Building HTML views using Razor Templates

Xamarin enables developers to leverage the Razor templating engine, originally introduced
with ASP.NET MVC, along with C# to easily combine data with HTML, Javascript and CSS
without the hassle of manually building HTML strings in code. This article demonstrates how
to use Razor templates with Xamarin for Android and iOS.

Manually Creating NuGet Packages for Xamarin

Tips for creating NuGet packages that work with the Xamarin platform.
Async Support Overview

Using C# 5 async and await syntax with Xamarin

Xamarin's Async support is built on the Mono 3.0 foundation and upgrades the API profile
from the being a Mobile-friendly version of Silverlight to be a mobile-friendly version of .NET
4.5.

Overview
This document introduces the new async and await keywords then walks through some
simple examples implementing asynchronous methods in Xamarin.iOS and
Xamarin.Android.

For a more complete discussion of the new asynchronous features of C# 5 (including lots of
samples and different usage scenarios) refer to the MSDN documentation Asynchronous
Programming with Async and Await.

The sample application makes a simple asynchronous web request (without blocking the
main thread) then updates the UI with the downloaded html and character count.
Xamarin's async support is built on the Mono 3.0 foundation and upgrades the API profile
from the being a mobile-friendly version of Silverlight to be a mobile-friendly version of .NET
4.5.

Requirements
C# 5 features require Mono 3.0 that is included in Xamarin.iOS 6.4 and Xamarin.Android
4.8. You will be prompted to upgrade your Mono, Xamarin.iOS, Xamarin.Android and
Xamarin.Mac to take advantage of it.

Using async & await


async and await are new C# language features that work in conjunction with the Task
Parallel Library to make it easy to write threaded code to perform long-running tasks without
blocking the main thread of your application.

async

Declaration

The async keyword is placed in a method declaration (or on a lambda or anonymous


method) to indicate that it contains code that can run asynchronously, ie. not block the
caller’s thread.

A method marked with async should contain at least one await expression or statement. If
no awaits are present in the method then it will run synchronously (the same as if there
were no async modifier). This will also result in a compiler warning (but not an error).
Return Types

An async method should return a Task, Task<TResult> or void.

Specify the Task return type if the method does not return any other value.

Specify Task<TResult> if the method needs to return a value, where TResult is the type
being returned (such as an int, for example).

The void return type is used mainly for event handlers which require it. Code that calls void-
returning asynchronous methods can’t await on the result.

Parameters

Asynchronous methods cannot declare ref or out parameters.

await

The await operator can be applied to a Task inside a method marked as async. It causes the
method to stop execution at that point and wait until the task completes.

Using await does not block the caller’s thread – rather control is returned to the caller. This
means that the calling thread is not blocked, so for example the user interface thread would
not be blocked when awaiting a task.

When the task completes, the method resumes executing at the same point in the code. This
includes returning to the try scope of a try-catch-finally block (if one is present). await cannot
be used in a catch or finally block.

Read more about await on MSDN.

Exception Handling

Exceptions that occur inside an async method are stored in the task and thrown when the
task is awaited. These exceptions can be caught and handled inside a try-catch block.
Cancellation

Asynchronous methods that take a long time to complete should support cancellation.
Typically, cancellation is invoked as follows:

A CancellationTokenSource object is created.


The CancellationTokenSource.Token instance is passed to a cancellable
asynchronous method.
Cancellation is requested by calling the CancellationTokenSource.Cancel
method.

The task then cancels itself and acknowledges the cancellation.

For more information about cancellation, see how to cancel an asynchronous task on
MSDN.

Example

Download the example Xamarin solution (for both iOS and Android) to see a working
example of async and await in mobile apps. The example code is discussed in more detail
in this section.

Writing an async method

The following method demonstrates how to code an async method with an awaited task:

public async Task<int> DownloadHomepage()


{
var httpClient = new HttpClient(); // Xamarin supports
HttpClient!

Task<string> contentsTask =
httpClient.GetStringAsync("http://xamarin.com"); // async method!
// await! control returns to the caller and the task continues
to run on another thread
string contents = await contentsTask;

ResultEditText.Text += "DownloadHomepage method continues after


async call. . . . .\n";

// After contentTask completes, you can calculate the length of


the string.
int exampleInt = contents.Length;

ResultEditText.Text += "Downloaded the html and found out the


length.\n\n\n";

ResultEditText.Text += contents; // just dump the entire HTML

return exampleInt; // Task<TResult> returns an object of type


TResult, in this case int
}

Note these points:

The method declaration includes the async keyword.


The return type is Task<int> so calling code can access the int value that is
calculated in this method.
The return statement is return exampleInt; which is an integer object – the fact
that the method returns Task<int> is part of the language improvements.

Calling an async method 1

This button click event handler can be found in the Android sample application to call the
method discussed above:

GetButton.Click += async (sender, e) => {


Task<int> sizeTask = DownloadHomepage();

ResultTextView.Text = "loading...";
ResultEditText.Text = "loading...\n";

// await! control returns to the caller


var intResult = await sizeTask;

// when the Task<int> returns, the value is available and we can


display on the UI
ResultTextView.Text = "Length: " + intResult ;
// "returns" void, since it's an event handler
};

Notes:

The anonymous delegate has the async keyword prefix.


The asynchronous method DownloadHomepage returns a Task that is stored in the
sizeTask variable.
The code awaits on the sizeTask variable. This is the location that the method is
suspended and control is returned to the calling code until the asynchronous task
finishes on its own thread.
Execution does not pause when the task is created on the first line of the method,
despite the task being created there. The await keyword signifies the location where
execution is paused.
When the asynchronous task finishes, intResult is set and execution continues on the
original thread, from the await line.

Calling an async method 2

In the iOS sample application the example is written slightly differently to demonstrate an
alternative approach. Rather than use an anonymous delegate this example declares an
async event handler that is assigned like a regular event handler:
GetButton.TouchUpInside += HandleTouchUpInside;

The event handler method is then defined as shown here:

async void HandleTouchUpInside (object sender, EventArgs e)


{
ResultLabel.Text = "loading...";
ResultTextView.Text = "loading...\n";

// await! control returns to the caller


var intResult = await DownloadHomepage();

// when the Task<int> returns, the value is available and we can


display on the UI
ResultLabel.Text = "Length: " + intResult ;
}

Some important points:

The method is marked as async but returns void . This is typically only done for
event handlers (otherwise you’d return a Task or Task<TResult> ).
The code await s on the DownloadHomepage method directly on an assignment to a
variable ( intResult ) unlike the previous example where we used an intermediate
Task<int> variable to reference the task. This is the location where control is
returned to the caller until the asynchronous method has completed on another thread.
When the asynchronous method completes and returns, execution resumes at the
await which means the integer result is returned and then rendered in a UI widget.

Summary
Using async and await greatly simplifies the code required to spawn long-running operations
on background threads without blocking the main thread. They also make it easy to access
the results when the task has completed.

This document has given an overview of the new language keywords and examples for both
Xamarin.iOS and Xamarin.Android.
C# 6 New Features Overview

Using C# 6 with Xamarin

Overview
This document introduces the new features of C# 6. It is fully supported by the mono
compiler and developers can start using the new features across all the Xamarin target
platforms.

This article includes brief snippets of the C# 6 code that illustrate basic use. The sample
application is a command-line program that runs across all Xamarin target platforms and
exercises the various features.

Requirements

Development Environment

Mac

Visual Studio for Mac has support for C# 6: you can build and compile Xamarin apps
using C# 6 features. Read more about Visual Studio for Mac.

Windows

Visual Studio 2015 and 2017 and above have full support for C# 6. Earlier versions of
Visual Studio (eg. 2013, 2012) will not support C# 6.

Xamarin Studio for Windows does not support C# 6 features in the editor.
Compiler

The Mono C# 6 compiler is included in Mono 4.0 and later, which is freely available for
download. Visual Studio for Mac automatically updates the Mono installation on your system.

Windows users must have Visual Studio 2015 or 2017^ installed to compile C# 6 code (even
if you choose Xamarin Studio for Windows as your IDE).

^ or Microsoft Build Tools 2015 for command line compilation or build servers, for example.

Using C# 6
The C# 6 compiler is used in all recent versions of Visual Studio for Mac. Those using
command-line compilers should confirm that mcs --version returns 4.0 or higher. Visual
Studio for Mac users can check if they have Mono 4 (or newer) installed by referring to
About Visual Studio for Mac > Visual Studio for Mac > Show Details.

Less Boilerplate

using static

Enumerations, and certain classes such as System.Math, are primarily holders of static
values and functions. In C# 6, you can import all static members of a type with a single
using static statement. Compare a typical trigonometric function in C# 5 and C# 6:

// Classic C#
class MyClass
{
public static Tuple<double,double> SolarAngleOld(double
latitude, double declination, double hourAngle)
{
var tmp = Math.Sin (latitude) * Math.Sin (declination) +
Math.Cos (latitude) * Math.Cos (declination) * Math.Cos (hourAngle);
return Tuple.Create (Math.Asin (tmp), Math.Acos (tmp));
}
}

// C# 6
using static System.Math;

class MyClass
{
public static Tuple<double, double> SolarAngleNew(double
latitude, double declination, double hourAngle)
{
var tmp = Asin (latitude) * Sin (declination) + Cos
(latitude) * Cos (declination) * Cos (hourAngle);
return Tuple.Create (Asin (tmp), Acos (tmp));
}
}

using static does not make public const fields, such as Math.PI and Math.E, directly
accessible:

for (var angle = 0.0; angle <= Math.PI * 2.0; angle += Math.PI / 8)
... //PI is const, not static, so requires Math.PI

using static with Extension Methods

The using static facility operates a little differently with extension methods. Although
extension methods are written using static, they don’t make sense without an instance on
which to operate. So when using static is used with a type that defines extension
methods, the extension methods become available on their target type (the method's this
type). For instance, using static System.Linq.Enumerable can be used to extend
the API of IEnumerable<T> objects without bringing in all of the LINQ types:
using static System.Linq.Enumerable;
using static System.String;

class Program
{
static void Main()
{
var values = new int[] { 1, 2, 3, 4 };
var evenValues = values.Where (i => i % 2 == 0);
System.Console.WriteLine (Join(",", evenValues));
}
}

The previous example demonstrates the difference in behavior: the extension method
Enumerable.Where is associated with the array, while the static method String.Join
can be called without reference to the String type.

nameof Expressions

Sometimes, you want to refer to the name you’ve given a variable or field. In C# 6,
nameof(someVariableOrFieldOrType) will return the string
"someVariableOrFieldOrType". For instance, when throwing an
ArgumentException you’re very likely to want to name which argument is invalid:

throw new ArgumentException ("Problem with " +


nameof(myInvalidArgument))

The chief advantage of nameof expressions is that they are type-checked and are
compatible with tool-powered refactoring. The type-checking of nameof expressions is
particularly welcome in situations where a string is used to dynamically associate types.
For instance, in iOS a string is used to specify the type used to prototype
UITableViewCell objects in a UITableView. nameof can assure this association does
not fail due to a misspelling or sloppy refactoring:

public override UITableViewCell GetCell (UITableView tableView,


NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (nameof(CellTypeA),
indexPath);
cell.TextLabel.Text = objects [indexPath.Row].ToString ();
return cell;
}

Although you can pass a qualified name to nameof, only the final element (after the last .) is
returned. For instance, you can add a data binding in Xamarin.Forms:

var myReactiveInstance = new ReactiveType ();


var myLabelOld.BindingContext = myReactiveInstance;
var myLabelNew.BindingContext = myReactiveInstance;
var myLabelOld.SetBinding (Label.TextProperty, "StringField");
var myLabelNew.SetBinding (Label.TextProperty,
nameof(ReactiveType.StringField));

The two calls to SetBinding are passing identical values:


nameof(ReactiveType.StringField) is "StringField", not
"ReactiveType.StringField" as you might initially expect.

Null-conditional Operator
Earlier updates to C# introduced the concepts of nullable types and the null-coalescing
operator ?? to reduce the amount of boilerplate code when handling nullable values. C# 6
continues this theme with the "null-conditional operator" ?.. When used on an object on the
right-hand side of an expression, the null-conditional operator returns the member value if
the object is not null and null otherwise:
var ss = new string[] { "Foo", null };
var length0 = ss [0]?.Length; // 3
var length1 = ss [1]?.Length; // null
var lengths = ss.Select (s => s?.Length ?? 0); //[3, 0]

(Both length0 and length1 are inferred to be of type int?)

The last line in the previous example shows the ? null-conditional operator in combination
with the ?? null-coalescing operator. The new C# 6 null-conditional operator returns null on
the 2nd element in the array, at which point the null-coalescing operator kicks in and
supplies a 0 to the lengths array (whether that's appropriate or not is, of course, problem-
specific).

The null-conditional operator should tremendously reduce the amount of boilerplate null-
checking necessary in many, many applications.

There are some limitations on the null-conditional operator due to ambiguities. You cannot
immediately follow a ? with a parenthesized argument list, as you might hope to do with a
delegate:

SomeDelegate?("Some Argument") // Not allowed

However, Invoke can be used to separate the ? from the argument list and is still a marked
improvement over a null-checking block of boilerplate:

public event EventHandler HandoffOccurred;


public override bool ContinueUserActivity (UIApplication
application, NSUserActivity userActivity,
UIApplicationRestorationHandler completionHandler)
{
HandoffOccurred?.Invoke (this, userActivity.UserInfo);
return true;
}
String Interpolation
The String.Format function has traditionally used indices as placeholders in the format
string, e.g., String.Format("Expected: {0} Received: {1}.", expected,
received). Of course, adding a new value has always involved an annoying little task of
counting up arguments, renumbering placeholders, and inserting the new argument in the
right sequence in the argument list.

C# 6's new string interpolation feature greatly improves upon String.Format. Now, you
can directly name variables in a string prefixed with a $. For instance:

$"Expected: {expected} Received: {received}."

Variables are, of course, checked and a misspelled or non-available variable will cause a
compiler error.

The placeholders do not need to be simple variables, they can be any expression. Within
these placeholders, you can use quotation marks without escaping those quotations. For
instance, note the "s" in the following:

var s = $"Timestamp: {DateTime.Now.ToString ("s",


System.Globalization.CultureInfo.InvariantCulture )}"

String interpolation supports the alignment and formatting syntax of String.Format. Just
as you previously wrote {index, alignment:format}, in C# 6 you write
{placeholder, alignment:format}:

using static System.Linq.Enumerable;


using System;

class Program
{
static void Main ()
{
var values = new int[] { 1, 2, 3, 4, 12, 123456 };
foreach (var s in values.Select (i => $"The value is {
i,10:N2}.")) {
Console.WriteLine (s);
}
Console.WriteLine ($"Minimum is { values.Min(i => i):N2}.");
}
}

results in:

The value is 1.00.


The value is 2.00.
The value is 3.00.
The value is 4.00.
The value is 12.00.
The value is 123,456.00.
Minimum is 1.00.

String interpolation is syntactic sugar for String.Format: it cannot be used with @"" string
literals and is not compatible with const, even if no placeholders are used:

const string s = $"Foo"; //Error : const requires value

In the common use-case of building function arguments with string interpolation, you still
need to be careful about escaping, encoding, and culture issues. SQL and URL queries are,
of course, critical to sanitize. As with String.Format, string interpolation uses the
CultureInfo.CurrentCulture. Using CultureInfo.InvariantCulture is a little
more wordy:

Thread.CurrentThread.CurrentCulture = new CultureInfo ("de");


Console.WriteLine ($"Today is: {DateTime.Now}"); //"21.05.2015
13:52:51"
Console.WriteLine ($"Today is:
{DateTime.Now.ToString(CultureInfo.InvariantCulture)}");
//"05/21/2015 13:52:51"

Initialization
C# 6 provides a number of concise ways to specify properties, fields, and members.

Auto-property Initialization

Auto-properties can now be initialized in the same concise manner as fields. Immutable
auto-properties can be written with only a getter:

class ToDo
{
public DateTime Due { get; set; } = DateTime.Now.AddDays(1);
public DateTime Created { get; } = DateTime.Now;

In the constructor, you can set the value of a getter-only auto-property:

class ToDo
{
public DateTime Due { get; set; } = DateTime.Now.AddDays(1);
public DateTime Created { get; } = DateTime.Now;
public string Description { get; }

public ToDo (string description)


{
this.Description = description; //Can assign (only in
constructor!)
}

This initialization of auto-properties is both a general space-saving feature and a boon to


developers wishing to emphasize immutability in their objects.
Index Initializers

C# 6 introduces index initializers, which allow you to set both the key and value in types that
have an indexer. Typically, this is for Dictionary-style data structures:

partial void ActivateHandoffClicked (WatchKit.WKInterfaceButton


sender)
{
var userInfo = new NSMutableDictionary {
["Created"] = NSDate.Now,
["Due"] = NSDate.Now.AddSeconds(60 * 60 * 24),
["Task"] = Description
};
UpdateUserActivity ("com.xamarin.ToDo.edit", userInfo, null);
statusLabel.SetText ("Check phone");
}

Expression-bodied Function Members

Lambda functions have several benefits, one of which is simply saving space. Similarly,
expression-bodied class members allow small functions to be expressed a little more
succinctly than was possible in previous versions of C# 6.

Expression-bodied function members use the lambda arrow syntax rather than the traditional
block syntax:

public override string ToString () => $"{FirstName} {LastName}";

Notice that the lambda-arrow syntax does not use an explicit return. For functions that
return void, the expression must also be a statement:

public void Log(string message) => System.Console.WriteLine($"


{DateTime.Now.ToString ("s",
System.Globalization.CultureInfo.InvariantCulture )}: {message}");
Expression-bodied members are still subject to the rule that async is supported for methods
but not properties:

//A method, so async is valid


public async Task DelayInSeconds(int seconds) => await
Task.Delay(seconds * 1000);
//The following property will not compile
public async Task<int> LeisureHours => await Task.FromResult<char>
(DateTime.Now.DayOfWeek.ToString().First()) == 'S' ? 16 : 5;

Exceptions
There's no two ways about it: exception-handling is hard to get right. New features in C# 6
make exception-handling more flexible and consistent.

Exception Filters

By definition, exceptions occur in unusual circumstances, and it can be very difficult to


reason and code about all the ways an exception of a particular type might occur. C# 6
introduces the ability to guard an execution handler with a runtime-evaluated filter. This is
done by adding a when (bool) pattern after the normal catch(ExceptionType)
declaration. In the following, a filter distinguishes a parse error relating to the date
parameter as opposed to other parsing errors.

public void ExceptionFilters(string aFloat, string date, string


anInt)
{
try
{
var f = Double.Parse(aFloat);
var d = DateTime.Parse(date);
var n = Int32.Parse(anInt);
} catch (FormatException e) when (e.Message.IndexOf("DateTime")
> -1) {
Console.WriteLine ($"Problem parsing \"{nameof(date)}\"
argument");
} catch (FormatException x) {
Console.WriteLine ("Problem parsing some other argument");
}
}

await in catch...finally…

The async capabilities introduced in C# 5 have been a game-changer for the language. In
C# 5, await was not allowed in catch and finally blocks, an annoyance given the value
of the async/await capability. C# 6 removes this limitation, allowing asynchronous results
to be awaited consistently through the program as shown in the following snippet:

async void SomeMethod()


{
try {
//...etc...
} catch (Exception x) {
var diagnosticData = await GenerateDiagnosticsAsync (x);
Logger.log (diagnosticData);
} finally {
await someObject.FinalizeAsync ();
}
}

Summary
The C# language continues to evolve to make developers more productive while also
promoting good practices and supporting tooling. This document has given an overview of
the new language features in C# 6 and has briefly demonstrated how they are used.
Accessibility
Accessibility refers to the concept of designing app user interfaces that work well operating
system display- and input-assistance features such as large type, high contrast, zoom in,
screen reading (text-to-speech), visual or haptic feedback cues, and alternative input
methods.

Desktop and mobile platforms like iOS, Android, and Windows provide built in APIs that help
developers build accessible apps, such as Google TalkBack and Apple's VoiceOver.

Platform-Specific APIs
To implement the guidelines in this document, use the APIs provided by each platform:

Android Accessibility
iOS Accessibility
OS X Accessibility
Xamarin.Forms

Accessibility Checklist
Follow these tips to ensure that your apps are accessible to the widest audience possible.
Check out the Android Accessibility Testing Checklist and Apple's Accessibility page for
additional information.

Support large fonts and high contrast

Avoid hardcoding control dimensions and, instead, prefer layouts that can resize to
accommodate larger font sizes. Test color schemes in high-contrast mode to ensure that
they are readable.
Make the user interface self-describing

Tag all the elements of your user-interface with descriptive text and hints that are compatible
with the screen reading APIs on each platform.

Ensure that images and icons have an alternate text description

Images and icons that are part of the application user interface (such as buttons or indicators
of status, for example) should be tagged with an accessible description.

Design the visual tree with accessible navigation in mind

Use appropriate layout controls or APIs so that navigating between controls using alternate
input methods follows the same logical flow as using the touch screen.

Exclude unnecessary elements from screen readers (decorative images or labels for fields
that are already accessible, for example).

Don't rely on audio or color cues alone

Avoid situations where the sole indication of progress, completion, or some other state is a
sound or color-change. Either design the user interface to include clear visual cues (with
sound and color for reinforcement only), or add specific accessibility indicators.

When choosing colors, try to avoid a palette that is hard to distinguish for users with color
blindness.

Captioning for video, text for audio

Provide captions for video content, and a readable script for audio content. It's also helpful to
provide controls that adjust the speed of audio or video content, and ensure that volume and
play/pause buttons are easy to find and use.

Localize

Accessibility descriptions can (and should) be localized where the application supports
multiple languages.
Localization
This guide introduces the concepts behind internationalization and localization and links to
instructions on how to produce Xamarin mobile applications using those concepts.

If you want to skip straight to the technical details of localizing Xamarin apps, start with one
of these platform-specific how-to articles:

Xamarin.Forms cross-platform localization using RESX files.


Xamarin.iOS native platform localization.
Xamarin.Android native platform localization.

i18n and L10n

Internationalization is the process of making your code capable of displaying different


languages and adapting its display for different locales (such as number and date
formatting). This is also referred to as globalization.

Localization is the step that follows – creating resources (such as strings and images) for
each language and bundling them with the internationalize app.

Internationalization it is often shortened to i18n – shorthand for 18 letters between "i" and
"n". Localization is similarly shortened to L10n – for 10 letters between "L" and "n".

Overview
This document introduces the concepts associated with internationalization and localization,
and how they apply to mobile application development in general. When designing and
building an application, things that you might previously have hardcoded but which must
parameterized for localization include:

Screen layouts and text,


Icons, graphics and colors,
Video and sound files,
Dynamic text and text-formatting (such as numbers, currency and dates),
Layout changes for right-to-left (RTL) languages, and
Data sorting.

Regardless of which mobile platforms your app targets these tips will help you build a high-
quality localized app.

Design Considerations
Architecting an application so that it is possible to localize its content is called
internationalization. Doing internationalization properly is more than just allowing for different
language strings to be loaded at runtime – a well-designed app should allow for all resources
to be changed based on language and locale (including images, sounds and videos) and
can adapt formatting and layout to cope with different sized strings.

This section discusses some design considerations to be taken into account when building
an internationalized application.

Layouts and string length

Chinese and Japanese strings can be very short – sometimes one or two characters can be
meaningful enough for an input field label.

German strings (for example) can be very long; sometimes a relatively short word in English
becomes very long in other languages – either becoming clipped or else unexpectedly
reflowing your layout.

Compare the string lengths for a few items on the iOS home screen in English, German, and
Japanese:
Notice that Settings in English (8 characters) requires 13 characters for the German
translation but only 2 characters in Japanese.

Layouts where the display label and input field are side-by-side are difficult to work with
when the label length can vary greatly. Often a layout where the label is displayed above a
field is easier to localize because the full width of the screen is available for both the label
and the input.

As a general rule, if you are building fixed layouts (especially side-by-side elements) allow at
least 50% more width than your English strings require for labels and text. This won’t solve
every problem but will provide a buffer that will work in many cases.

Input validation

Beware of assumptions when writing validation rules. It might seem valid to require a text
field input to "require" at least three characters in English, since a single letter very rarely has
any meaning. In Chinese and Japanese however a single character might be a valid input,
and a validation message "at least 3 characters is required" does not make sense for those
languages.

Other seemingly simple tasks like validating an email address or website URL become more
complicated with the characters are not limited to the ASCII subset.

Write your validation rules with internationalization in mind – either choose the least
restrictive rules, or write the logic so that it works differently for each language.

Images and Color

Not every image needs to change based on a user’s language choice. Many icons or photos
will be suitable for all users, not matter what language they speak. Some resources make
sense to localize though, such as:

Images depicting people or specific locations – your app may feel more relevant to
users if it shows local people/locations.
Icons – Some iconography can be culture-specific and you can make your app easier
to use by localizing the imagery to reflect local understanding.
Colors – Some cultures understand colors differently – red might mean warning in one
region, but good luck in another. Check with native speakers when designing your app
to determine whether you should be building a mechanism to localize colors.

Videos and Sound

Videos and sound present special challenges when localizing an application, because while
it’s relatively easy to get strings translated, recording multiple voiceover tracks or video clips
can be both expensive and difficult.

Multiple copies of video and sound files may also significantly increase the size of your
application (especially if you are localizing into a large number of languages or have lots of
media files). You might consider downloading only the required language assets after the
user has installed your app, but this could also result in a poor user experience on slow
networks.

There are often multiple ways to solve localization issues – the most important thing is to
consider them up-front and ensure your application is designed to take care of them.

Dates, Times, Numbers and Currency

If you’re using .NET formatting functions, remember to specify the culture so that decimal
separators are parsed correctly (and avoid conversion exceptions being thrown). For
example both 1.99 and 1,99 are valid decimal representations depending on your locale.

When the data is coming from a known source (ie. from your own code or a web-service that
you control) you can hardcode a culture identifier that matches the formatting such as the
InvariantCulture which will work for standard English language formatting.

double.Parse("1,999.99", CultureInfo.InvariantCulture);

If the data is being input by the app user, parse it using a CultureInfo instance that reflects
their locale:

double.Parse("1 999,99", CultureInfo.CreateSpecificCulture("fr-


FR"));

See the Parsing Numeric Strings and Parsing Date and Time Strings MSDN articles for
additional information.

Right-to-left (RTL) Languages

Some languages, such as Arabic, Hebrew, and Urdu (for example), are read from right to
left. Applications that support these languages should use screen designs that adapt for
right-to-left readers, for example:

Text should be right-aligned.


Labels should appear to the right of input fields.
Default button placement is generally reversed.
Hierarchical navigation swiping and animation (and other navigation metaphors and
animations) that use direction for context should also be reversed.

Both iOS and Android support right-to-left layouts and font rendering, with built-in features
that help to make the above adjustments. Xamarin.Forms does not currently automatically
support RTL rendering.

Sorting

Different languages define the sort order of their alphabets differently, even when they use
the same character set.

See the Detail of String Comparison in Best Practices for Using Strings in the .NET
Framework for an example where language (CultureInfo) affects the sort order.
It’s unlikely the built-in database capabilities on the mobile platforms will support language-
specific sort ordering so you may be required to implement additional code in your business
logic.

Text search

Ensure you write and test your search algorithm with multiple languages in mind. Things to
consider include:

Auto-complete – if you have built an auto-complete function ensure it sources


suggestions relevant to the user’s language.
Matching query to data – will search queries entered in a specific language be
executed against just content written in that language, or against all content in your
app?
Stemming – if your search is built to search for similar words, word roots and other
search optimizations, are those optimizations built for all the languages you support?
Sorting – make sure the results are sorted correctly (see above).

Data from external sources

Many applications download data from external sources, from Twitter and RSS feeds to
weather, news, or stock prices. When displaying this to a user you need to consider the
possibility that you will display a screen of irrelevant or unreadable information to them.

There are few strategies you can use to try and ensure your app displays data relevant to
the user:

Different sources – your application might download the data from a different source
depending on the user’s language or locale. Locale news, weather and stock prices
might make more sense than something downloaded from a North American feed.
Localized display – if you are displaying a Twitter or photo feed, you should display the
metadata (such as the time taken) in his or her own language, even if the content itself
remains in the original language.
Translation – you could build a translation option into your app to do a machine
translation of incoming data. This could be automatic or at the user’s discretion – just
be sure to notify the user if this is taking place, since machine translations are never
perfect!

This could also affect external links to audio tracks or videos – when designing your
application be sure to plan ahead for sourcing translated content or ensuring that users are
adequately informed by the user interface when content will not be presented in their
language.

Don’t over-translate

Some strings in your app might not need translating, or at the very least need special
attention by the translator. Examples might include:

URLs – if you list a URL, it may or may not need to be adjusted by language. For
example, facebook.com doesn’t require translation it auto-detects language at the
main site. Other sites have locale-specific content and you might want to offer a
different URL, such as yahoo.com versus yahoo.fr or yahoo.it.
Telephone numbers – especially those with different country-codes or numbers for
callers that speak a particular language.
Contact details – addresses and other information might vary by language or locale.
Trademarks & product names – some strings don’t need translating because they’re
always written in same language.

Finally, be sure to include detailed instructions for the translator if certain strings require
special treatment.

Formatted text

Not usually a problem with mobile apps because strings generally aren’t richly formatted.
However if rich text (such as bold or italic formatting) is required in your app ensure the
translator knows how to input the formatting, your strings files store it correctly and it is
formatted properly before being displayed to the user (ie. don’t accidentally let the formatting
codes themselves be presented to the user).

Translation Tips
Translating the strings used by an application is considered to be part of the localization
process. Typically this task will be outsourced to a translation service and performed by
multilingual staff that may not know your application or your business.

The following tips will help you produce strings that are easier to translate accurately and
therefore improve the quality of your localized apps.

Localize complete strings, not words

Sometimes developers take the approach of trying to specify single words or sentence
'snippets' so that they can re-use them throughout the application. For example, for the text
"You have 5 messages." they might specify the following strings for translation

Bad:

"You have"
"no"
"message"
"messages"

and then attempt to create the correct phrase on-the-fly in code using string concatenation:

Bad:

"You have" + " " + numMsgs + " " + "messages"


"You have" + " no " + "messages"

This is discouraged because it will not necessarily work for all languages and will be
difficult for the translator to understand the context of each short segment. It also leads to re-
use of translated strings, which can cause problems later if they are used in different
contexts (and then get updated).
Allow for parameter re-ordering

Some programming languages require extra syntax to specify the order of parameters in a
string, however .NET already supports the concept of numbered placeholders, so

Good:

"a {0} b {1} cde {3}"

could be translated the following (where the position and order of the placeholders is
changed)

"{2} {3} f g h {0}"

and the tokens will be ordered as the translator intended. Be sure to include an explanation
of what each placeholder contains when sending the string to a translator.

Use multiple strings for cardinality

Avoid strings like "You have {0} message/s." Use specific strings for each state to
provide a better user experience:

Good:

"You have no messages."


"You have 1 messages."
"You have 2 messages."
"You have {0} messages."

You will have to write code in your app to evaluate the number being displayed and choose
the appropriate string. Some platforms (including iOS and Android) have built-in features to
automatically choose the best plural string based on the preferences for the current
language/locale.

Allowing for gender


Latin-based languages sometimes use different words depending on the gender of the
subject. If your app knows about gender, you should allow the translated strings to reflect
this.

There is also the more obvious case even in English, where strings refer to a specific person
or user of your app. For example, some sites show messages like "Bob commented on
his post" so you need strings for both a male, female, and non-binary or unknown
gender:

Good:

"{0} commented on his post"


"{0} commented on her post"
"{0} commented on their post"

Don’t reuse strings

Or more accurately, don’t reuse strings just because they are similar when the string itself
has a different purpose or meaning.

For example: imagine you have an on/off switch in your app and the switch control needs the
text for ‘on’ and ‘off’ to be localized. You also display the value of that setting elsewhere in
the app in a text label. You should use different strings for the switch display versus the
switch’s status (even if they are the same string in your default language) – for example:

• "On" – displayed on the switch itself • "Off" – displayed on the switch itself • "On" –
displayed in a label • "Off" – displayed in a label

This provides maximum flexibility for the translator:

• For design reasons, perhaps the switch itself uses lowercase "on" and "off" but the display
label uses upper case "On" and "Off". • Some languages might need the switch value to be
abbreviated to fit in the user interface control, while the complete (translated) word can
appear in the label. • Alternatively, for some languages the rendering of your switch might be
use "I" and "O" for cultural familiarity, but you might still want the label to read "On" or "Off".
Translation Services

Machine translation

For testing purposes it is can help to use one of the many online translation tools to include
some localized text in your app during development.

Bing Translator

Google Translate

There are many others available. The quality of machine translation generally isn't
considered good enough to release an application without first being reviewed and tested by
professional translators or native speakers.

Professional translation

There are also professional translation services that will take your strings and distribute them
to their own translators, providing you with finished translations for a fee.

One of the best-known services is LionBridge. Most professional services support all the
common file types including strings, XML, RESX and POT/PO.

Summary
This article introduced some of the concepts that you should be familiar with before
internationalizing your app and then localizing your resources, and also covered how to
change language preferences for each platform.

These concepts can be applied to the various platform-specific and cross-platform


internationalization techniques that are possible with Xamarin.

Continue reading technical details for the platform you are interested in:

Xamarin.Forms cross-platform localization using RESX files.


Xamarin.iOS native platform localization.
Xamarin.Android native platform localization.
Custom Linker Configuration
If the default set of options is not enough, you can drive the linking process with an XML file
that describes what you want from the linker.

You can provide extra definitions to the linker to ensure the type, methods and/or fields are
not eliminated from your application. In your own code the preferred way is to use the
[Preserve] custom attribute, as discussed in the Linking on iOS and Linking on Android
guides. However if you need some definitions from the SDK or product assemblies then
using an XML file might be your best solution (versus adding code that will ensure the linker
won't eliminate what you need).

To do this, you define an XML file with the top-level element which contains assembly nodes
which in turn contain type nodes, which in turn contain method and field nodes.

Once you have this linker description file, add it to your project and:

For Android : set the Build Action to LinkDescription


For iOS : set the Build Action to LinkDescription

The following example shows what the XML file looks like:

<linker>
<assembly fullname="mscorlib">
<type fullname="System.Environment">
<field name="mono_corlib_version" />
<method name="get_StackTrace" />
</type>
</assembly>
<assembly fullname="My.Own.Assembly">
<type fullname="Foo" preserve="fields">
<method name=".ctor" />
</type>
<type fullname="Bar">
<method signature="System.Void
.ctor(System.String)" />
<field signature="System.String _blah" />
</type>
<namespace fullname="My.Own.Namespace" />
<type fullname="My.Other*" />
</assembly>
</linker>

In the above example, the linker will read and apply the instructions on the mscorlib.dll
(shipped with Mono for Android) and My.Own.Assembly (user code) assemblies.

The first section, for mscorlib.dll, will ensure that the System.Environment type will
preserve its field named mono_corlib_version and its get_StackTrace method. Note
the getter and/or setter method names must be used as the linker works on IL and does not
understand C# properties.

The second section, for My.Own.Assembly.dll, will ensure that the Foo type will preserve
all its fields (i.e. the preserve="fields" attribute) and all its constructors (i.e. all the
methods named .ctor in IL). The Bar type will preserve specific signatures (not names) for
one constructor (that accepts a single string parameter) and for a specific string field _blah.
The My.Own.Namespace namespace will preserve all the types it contains. Lastly, any type
whose full name (including the namespace) matches the wildcard pattern "My.Other*" will
preserve all of its fields and methods. The wildcard character * can be included multiple
times within a "type fullname" pattern.
Building HTML views using Razor Templates

Using Razor to build hybrid apps with C#

Overview
In the mobile development world the term “hybrid app” typically refers to an application that presents some
(or all) of its screens as HTML pages inside a hosted web viewer control.

There are some development environments that let you build your mobile app entirely in HTML and
Javascript, however those apps can suffer from performance problems when trying to accomplish complex
processing or UI effects and are also limited in the platform features they can access.

Xamarin offers the best of both worlds, especially when utilizing the Razor HTML templating engine. With
Xamarin you have the flexibility to build cross-platform templated HTML views that use Javascript and
CSS, but also have complete access to the underlying platform APIs and fast processing using C#.

This document explains how to use the Razor templating engine build HTML+Javascript+CSS views that
can be used across mobile platforms using Xamarin.

Using Web Views Programmatically


Before we learn about Razor this section covers how to use web views to display HTML content directly –
specifically HTML content that is generated within an app.

Xamarin provides complete access to the underlying platform APIs on both iOS and Android, so it is easy
to create and display HTML using C#. The basic syntax for each platform is shown below.

iOS

Displaying HTML in a UIWebView control in Xamarin.iOS also takes just a few lines of code:

var webView = new UIWebView (View.Bounds);


View.AddSubview(webView);
string contentDirectoryPath = Path.Combine (NSBundle.MainBundle.BundlePath,
"Content/");
var html = "<html><h1>Hello</h1><p>World</p></html>";
webView.LoadHtmlString(html, NSBundle.MainBundle.BundleUrl);

See the iOS UIWebView recipes for more details on using the UIWebView control.

Android

Displaying HTML in a WebView control using Xamarin.Android is accomplished in just a few lines of code:

// webView is declared in an AXML layout file


var webView = FindViewById<WebView> (Resource.Id.webView);
var html = "<html><h1>Hello</h1><p>World</p></html>";
webView.LoadDataWithBaseURL("file:///android_asset/", html, "text/html", "UTF-
8", null);

See the Android WebView recipes for more details on using the WebView control.

Specifying the Base Directory

On both platforms there is a parameter that specifies the base directory for the HTML page. This is the
location on the device’s file system that is used to resolve relative references to resources like images and
CSS files. For example, tags like

<link rel="stylesheet" href="style.css" />


<img src="monkey.jpg" />
<script type="text/javascript" src="jscript.js">

refer to these files: style.css, monkey.jpg and jscript.js. The base directory setting tells the web view
where these files are located so they can be loaded into the page.

iOS

The template output is rendered in iOS with the following C# code:

webView.LoadHtmlString (page, NSBundle.MainBundle.BundleUrl);

The base directory is specified as NSBundle.MainBundle.BundleUrl which refers to the directory that
the application is installed in. All the files in the Resources folder are copied to this location, such as the
style.css file shown here:
The Build Action for all static content files should be BundleResource:

Android

Android also requires a base directory to be passed as a parameter when html strings are displayed in a
web view.

webView.LoadDataWithBaseURL("file:///android_asset/", page, "text/html", "UTF-


8", null);

The special string file:///android_asset/ refers to the Android Assets folder in your app, shown here
containing the style.css file.

The Build Action for all static content files should be AndroidAsset.

Calling C# from HTML and Javascript

When an html page is loaded into a web view, it treats the links and forms as it would if the page was
loaded from a server. This means that if the user clicks a link or submits a form the web view will attempt to
navigate to the specified target.

If the link is to an external server (such as google.com) then the web view will attempt to load the external
website (assuming there is an internet connection).

<a href="http://google.com/">Google</a>

If the link is relative then the web view will attempt to load that content from the base directory. Obviously
no network connection is required for this to work, as the content is stored in the app on the device.

<a href="somepage.html">Local content</a>

Form actions follow the same rule.

<form method="get" action="http://google.com/"></form>


<form method="get" action="somepage.html"></form>

You’re not going to host a web server on the client; however, you can use the same server communication
techniques employed in today’s responsive design patterns to call services over HTTP GET, and handle
responses asynchronously by emitting Javascript (or calling Javascript already hosted in the web view).
This enables you to easily pass data from the HTML back into C# code for processing then display the
results back on the HTML page.

Both iOS and Android provide a mechanism for application code to intercept these navigation events so
that app code can respond (if required). This feature is crucial to building hybrid apps because it lets native
code interact with the web view.

iOS

The ShouldStartLoad event on the web view in iOS can be overridden to allow application code to handle a
navigation request (such as a link click). The method parameters supply all the information

bool HandleShouldStartLoad (UIWebView webView, NSUrlRequest request,


UIWebViewNavigationType navigationType) {
// return true if handled in code
// return false to let the web view follow the link
}

and then assign the event handler:

webView.ShouldStartLoad += HandleShouldStartLoad;
Android

On Android simply subclass WebViewClient and then implement code to respond to the navigation request.

class HybridWebViewClient : WebViewClient {


public override bool ShouldOverrideUrlLoading (WebView webView, string url)
{
// return true if handled in code
// return false to let the web view follow the link
}
}

and then set the client on the web view:

webView.SetWebViewClient (new HybridWebViewClient ());

Calling Javascript from C

In addition to telling a web view to load a new HTML page, C# code can also run Javascript within the
currently displayed page. Entire Javascript code blocks can be created using C# strings and executed, or
you can craft method calls to Javascript already available on the page via script tags.

Android

Create the Javascript code to be executed and then prefix it with “javascript:” and instruct the web view to
load that string:

var js = "alert('test');";
webView.LoadUrl ("javascript:" + js);

iOS

iOS web views provide a method specifically to call Javascript:

var js = "alert('test');";
webView.EvaluateJavascript (js);

Summary

This section has introduced the features of the web view controls on both Android and iOS that let us build
hybrid applications with Xamarin, including:
The ability to load HTML from strings generated in code,
The ability to reference local files (CSS, Javascript, Images or other HTML files),
The ability to intercept navigation requests in C# code,
The ability to call Javascript from C# code.

The next section introduces Razor, which makes it easy to create the HTML to use in hybrid apps.

What is Razor?
Razor is a templating engine that was introduced with ASP.NET MVC, originally to run on the server and
generate HTML to be served to web browsers.

The Razor templating engine extends standard HTML syntax with C# so that you can express the layout
and incorporate CSS stylesheets and Javascript easily. The template can reference a Model class, which
can be any custom type and whose properties can be accessed directly from the template. One of its main
advantages is the ability to mix HTML and C# syntax easily.

Razor templates are not limited to server-side use, they can also be included in Xamarin apps. Using Razor
templates along with the ability to work with web views programmatically enables sophisticated cross-
platform hybrid applications to be built with Xamarin.

Razor Template Basics

Razor template files have a .cshtml file extension. They can be added to a Xamarin project from the Text
Templating section in the New File dialog:

A simple Razor template ( RazorView.cshtml) is shown below.

@model string
<html>
<body>
<h1>@Model</h1>
</body>
</html>

Notice the following differences from a regular HTML file:

The @ symbol has special meaning in Razor templates – it indicates that the following expression is
C# to be evaluated.
@model directive always appears as the first line of a Razor template file.
The @model directive should be followed by a Type. In this example a simple string is being passed
to the template, but this could be any custom class.
When @Model is referenced throughout the template, it provides a reference to the object passed to
the template when it is generated (in this example it will be a string).
The IDE will automatically generate partial class for templates (files with the .cshtml extension). You

can view this code but it should not be edited. The partial class is named
RazorView to match the .cshtml template file name. It is this name that is used to refer to the
template in C# code.
@using statements can also be included at the top of a Razor template to include additional
namespaces.

The final HTML output can then be generated with the following C# code. Note that we specify the Model to
be a string “Hello World” which will be incorporated into the rendered template output.

var template = new RazorView () { Model = "Hello World" };


var page = template.GenerateString ();

Here is the output shown in a web view on the iOS Simulator and Android Emulator:

More Razor Syntax

In this section we’re going to introduce some basic Razor syntax to help you get started using it. The
examples in this section populate the following class with data and display it using Razor:
public class Monkey {
public string Name { get; set; }
public DateTime Birthday { get; set; }
public List<string> FavoriteFoods { get; set; }
}

All examples use the following data initialization code

var animal = new Monkey {


Name = "Rupert",
Birthday=new DateTime(2011, 04, 01),
FavoriteFoods = new List<string>
{"Bananas", "Banana Split", "Banana Smoothie"}
};

Displaying Model Properties

When the model is a class with properties, they are easily referenced in the Razor template as shown in
this example template:

@model Monkey
<html>
<body>
<h1>@Model.Name</h1>
<p>Birthday: @(Model.Birthday.ToString("d MMMM yyyy"))</p>
</body>
</html>

This can be rendered to a string using the following code:

var template = new RazorView () { Model = animal };


var page = template.GenerateString ();

The final output is shown here in a web view on the iOS Simulator and Android Emulator:
C# statements

More complex C# can be included in the template, such as the Model property updates and the Age
calculation in this example:

@model Monkey
<html>
<body>
@{
Model.Name = "Rupert X. Monkey";
Model.Birthday = new DateTime(2011,3,1);
}
<h1>@Model.Name</h1>
<p>Birthday: @Model.Birthday.ToString("d MMMM yyyy")</p>
<p>Age: @(Math.Floor(DateTime.Now.Date.Subtract
(Model.Birthday.Date).TotalDays/365)) years old</p>
</body>
</html>

You can write complex single-line C# expressions (like formatting the age) by surrounding the code with
@().

Multiple C# statements can be written by surrounding them with @{}.

If-else statements

Code branches can be expressed with @if as shown in this template example.

@model Monkey
<html>
<body>
<h1>@Model.Name</h1>
<p>Birthday: @(Model.Birthday.ToString("d MMMM yyyy"))</p>
<p>Age: @(Math.Floor(DateTime.Now.Date.Subtract
(Model.Birthday.Date).TotalDays/365)) years old</p>
<p>Favorite Foods:</p>
@if (Model.FavoriteFoods.Count == 0) {
<p>No favorites</p>
} else {
<p>@Model.FavoriteFoods.Count favorites</p>
}
</body>
</html>

Loops

Looping constructs like foreach can also be added. The @ prefix can be used on the loop variable (
@food in this case) to render it in HTML.

@model Monkey
<html>
<body>
<h1>@Model.Name</h1>
<p>Birthday: @Model.Birthday.ToString("d MMMM yyyy")</p>
<p>Age: @(Math.Floor(DateTime.Now.Date.Subtract
(Model.Birthday.Date).TotalDays/365)) years old</p>
<p>Favorite Foods:</p>
@if (Model.FavoriteFoods.Count == 0) {
<p>No favorites</p>
} else {
<ul>
@foreach (var food in @Model.FavoriteFoods) {
<li>@food</li>
}
</ul>
}
</body>
</html>

The output of the above template is shown running on the iOS Simulator and Android Emulator:
This section has covered the basics of using Razor templates to render simple read-only views. The next
section explains how to build more complete apps using Razor that can accept user-input and interoperate
between Javascript in the HTML view and C#.

Using Razor Templates with Xamarin


This section explains how to use build your own hybrid application using the solution templates in Visual
Studio for Mac. There are three templates available from the File > New > Solution... window:

Android > App > Android WebView Application


iOS > App > WebView Application
ASP.NET MVC Project

The New Solution window looks like this for iPhone and Android projects - the solution description on the
right highlights support for the Razor templating engine.
Note that you can easily add a .cshtml Razor template to any existing Xamarin project, it is not necessary
to use these solution templates. iOS projects do not require a Storyboard to use Razor either; simply add a
UIWebView control to any view programmatically and you can render Razor templates entire in C# code.

The default template solution contents for iPhone and Android projects are shown below:

The templates give you ready-to-go application infrastructure to load a Razor template with a data model
object, process user input and communicate back to the user via Javascript.

The important parts of the solution are:

Static content such as the style.css file.


Razor .cshtml template files like RazorView.cshtml .
Model classes that are referenced in the Razor templates such as ExampleModel.cs .
The platform-specific class that creates the web view and renders the template, such as the
MainActivity on Android and the iPhoneHybridViewController on iOS.

The following section explains how the projects work.

Static Content
Static content includes CSS stylesheets, images, Javascript files or other content that can be linked from or
referenced by an HTML file being displayed in a web view.

The template projects include a minimal style sheet to demonstrate how to include static content in your
hybrid app. The CSS stylesheet is referenced in the template like this:

<link rel="stylesheet" href="style.css" />

You can add whatever stylesheet and Javascript files you need, including frameworks like JQuery.

Razor cshtml Templates

The template includes a Razor .cshtml file that has pre-written code to help communicate data between
the HTML/Javascript and C#. This will let you build sophisticated hybrid apps that don’t just display read-
only data from the Model, but also accept user-input in the HTML and pass it back to C# code for
processing or storage.

Rendering the template

Calling the GenerateString on a template renders HTML ready for display in a web view. If the template
uses a model then it should be supplied prior to rendering. This diagram illustrates how rendering works –
not that the static resources are resolved by the web view at runtime, using the supplied base directory to
find the specified files.
Calling C# code from the template

Communication from a rendered web view calling back to C# is done by setting the URL for the web view,
and then intercepting the request in C# to handle the native request without reloading the web view.

An example can be seen in how RazorView’s button is handled. The button has the following HTML:

<input type="button" name="UpdateLabel" value="Click"


onclick="InvokeCSharpWithFormValues(this)" />

The InvokeCSharpWithFormValues Javascript function reads all of the values from the HTML Form
and sets the location.href for the web view:

location.href = "hybrid:" + elm.name + "?" + qs;

This attempts to navigate the web view to a URL with a custom scheme that we’ve made up (hybrid:)

hybrid:UpdateLabel?textbox=SomeValue&UpdateLabel=Click

When the native web view processes this navigation request, we have the opportunity to intercept it. In
iOS, this is done by handling the UIWebView’s HandleShouldStartLoad event. In Android, we simply
subclass the WebViewClient used in the form, and override ShouldOverrideUrlLoading.

The internals of these two navigation interceptors is essentially the same.

First, we check the URL that web view is attempting to load, and if it doesn’t start with our custom scheme
(hybrid:), we allow the navigation to occur as normal.

For our custom URL scheme, we treat everything in the URL between the scheme and the “?” as the
method name to be handled (in this case, “UpdateLabel”). Everything in the query string will be treated as
the parameters to the method call:

var resources = url.Substring(scheme.Length).Split('?');


var method = resources [0];
var parameters = System.Web.HttpUtility.ParseQueryString(resources[1]);

UpdateLabel in this sample does a minimal amount of string manipulation on the textbox parameter
(prepending “C# says’” to the string), and then calls back to the web view.

At the end of our URL handling, we abort the navigation so that the web view does not attempt to finish
navigating to our custom URL.
Manipulating the template from C

Communication to a rendered HTML web view from C# is done by calling Javascript in the web view. On
iOS, this is done by calling EvaluateJavascript on the UIWebView:

webView.EvaluateJavascript (js);

On Android, Javascript can be invoked in the web view by loading the Javascript as a URL using the
"javascript:" URL scheme:

webView.LoadUrl ("javascript:" + js);

Making an app truly hybrid


These templates do not make use of native controls on each platform – the entire screen is filled with a
single web view.

HTML can be great for prototyping, and displaying the kinds of things the web is best at such as rich text
and responsive layout. However not all tasks are suited to HTML and Javascript – scrolling through long
lists of data, for example, performs better using native UI controls (such as UITableView on iOS or ListView
on Android).

The web views in the template can easily be augmented with platform-specific controls – simply edit the
MainStoryboard.storyboard in the iOS designer or the Resources/layout/Main.axml on Android.

RazorTodo Sample

The RazorTodo repository contains two separate solutions to show the differences between a completely
HTML-driven app and an app that combines HTML with native controls:

RazorTodo - Completely HTML-driven app using Razor templates.


RazorNativeTodo - Uses native list view controls for iOS and Android but displays the edit screen
with HTML and Razor.

These Xamarin apps run on both iOS and Android, utilizing Portable Class Libraries (PCLs) to share
common code such as the database and model classes. Razor .cshtml templates can also be included in
the PCL so they’re easily shared across platforms.

Both sample apps incorporate Twitter sharing and text-to-speech APIs from the native platform,
demonstrating that hybrid applications with Xamarin still have access to all the underlying functionality from
HTML Razor template-driven views.

The RazorTodo app uses HTML Razor templates for the list and edit views. This means we can build the
app almost completely in a shared Portable Class Library (including the database and .cshtml Razor
templates). The screenshots below show the iOS and Android apps.

The RazorNativeTodo app uses an HTML Razor template for the edit view, but implements a native
scrolling list on each platform. This provides a number of benefits including:

Performance - the native scrolling controls use virtualization to ensure fast, smooth scrolling even
with very long lists of data.
Native experience - platform-specific UI elements are easily enabled, such as the fast-scrolling index
support in iOS and Android.

A key benefit of building hybrid apps with Xamarin is that you can start with a completely HTML-driven user
interface (like the first sample) and then add platform-specific functionality when required (as the second
sample shows). The native list screens and HTML Razor edit screens on both iOS and Android are shown
below.
Summary
This article has explained the features of the web view controls available on iOS and Android that facilitate
building hybrid applications.

It then discussed the Razor templating engine and the syntax that can be used to generate HTML easily in
Xamarin apps using .cshtml Razor template files. It also described the Visual Studio for Mac solution
templates that let you quickly get started building hybrid applications with Xamarin.

Finally it introduced the RazorTodo samples which demonstrate how to combine web views with native
user interfaces and APIs.
Manually Creating NuGet Packages for
Xamarin
ℹ️ Xamarin Studio 6.2 (and Visual Studio for Mac) includes the ability to
automatically generate NuGet packages from PCL, .NET Standard, or Shared
Projects. Refer to the Multiplatform Libraries for Code Sharing guide for more
details.

NuGet Package Xamarin Profiles


The NuGet website's Supporting Multiple .NET Framework Versions and Profiles discusses
how to support different Microsoft frameworks and profiles but does not include the target
framework names used by Xamarin.

The main Xamarin target frameworks in use today are:

MonoAndroid - Xamarin.Android
Xamarin.iOS - Xamarin.iOS Unified API (supports 64-bit)
Xamarin.Mac - Xamarin.Mac's mobile profile, which is equivalent to the Xamarin.iOS
and Xamarin.Android API surface.

There is also a target for the older iOS Classic API:

MonoTouch - iOS Classic API

A .nuspec file that targeted all these would look something like:

<files>
<file src="Mac\bin\Release\*.dll" target="lib\Xamarin.Mac20" />
<file src="iOS\bin\Release\*.dll" target="lib\Xamarin.iOS10" />
<file src="Android\bin\Release\*.dll" target="lib\MonoAndroid10"
/>
<file src="iOSClassic\bin\Release\*.dll"
target="lib\MonoTouch10" />
</files>

The above ignores any portable class libraries.

Most .nuspec files specify the version number of the target framework but it is optional if
your assembly works with all versions of that target framework. So if your target was
lib\MonoAndroid this would mean it works with any version of Xamarin.Android.

You can specify the version with a set of numbers without a decimal point or you can specify
it using decimal points. Without the decimal point NuGet will just take each number and turn
it into a version by inserting a '.' between each digit.

In the above "MonoAndroid10" means "Android 1.0". This just means the project's target
framework needs to be MonoAndroid version 1.0 or higher. The version is specified in the
<TargetFrameworkVersion> element in the project file.

To clarify:

MonoAndroid403 matches Android 4.0.3 and newer (ie API level 15)
Xamarin.iOS10 matches Xamarin.iOS 1.0 and newer
Xamarin.iOS1.0 also matches Xamarin.iOS 1.0 and newer

PCL NuGets with Platform Dependencies


PCL Profiles are limited in what .NET framework APIs they can access, and they certainly
can't access platform-specific code. These 3rd-party links discuss different approaches for
creating NuGet packages that use PCL and native APIs to provide compatibility for Xamarin
and other platforms:

How to Make Portable Class Libraries Work for You


The Bait and Switch PCL Trick
Creating a NuGet PCL that works with Xamarin.iOS
This external list of PCL Profiles with their NuGet target name is also a useful reference.

Examples
Some open-source examples that you can refer to:

ModernHttpClient – Write your app using System.Net.Http, but drop this library in and
it will go drastically faster (view source).
Splat – A library to make things cross-platform that should be (view source).
NGraphics - A cross platform library for rendering vector graphics on .NET (view
source).
Updating Component References to NuGet
This guide explains how to update existing Xamarin solutions to change Component references to NuGet
packages.

Components that contain NuGet packages


Components with NuGet replacements

Most components fall into one of the above categories. If you are using a component that does not appear to
have an equivalent NuGet package, read the components without a NuGet migration path section below.

Refer to these pages for more detailed instructions for adding NuGet packages on Windows or Mac.

Components that contain NuGet packages

Many components already contain NuGet packages, and the migration path is simply to delete the component
reference.

You can determine whether the component already includes a NuGet package by double-clicking on the
component in the solution:

The Packages tab will list any NuGet packages included in the component:
Note that the Assemblies tab will be empty:

Updating the Solution

To update your solution, delete the Component entry from the solution:

The NuGet package will remain listed in the Packages node and your app will compile and run as usual. In
future, updates to this package will be performed via the Nuget update feature:

Components with NuGet replacements

If the component info page Assemblies tab contains entries as shown below, you will need to find the
equivalent NuGet package manually.
Note that the Packages tab will probably be empty:

It may contain NuGet dependencies, but these can be ignored.

To confirm a replacement NuGet package exists, search on NuGet.org, using the component name, or
alternatively by author.

As an example, you can find the popular sqlite-net-pcl package by searching for:

sqlite-net-pcl – the product name.


praeclarum – the author's profile.

Updating the Solution

Once you have confirmed the component is available in NuGet, follow these steps:

Delete the component

Right click on the component in the solution and choose Remove:


This will delete the component and any references. This will break your build, until you add the equivalent
NuGet package to replace it.

Add the NuGet package

1. Right-click on the Packages node and choose Add Packages....

2. Search for the NuGet replacement by name or author:

3. Press Add Package.

The NuGet package will be added to your project, along with any dependencies. This should fix the build. If the
build continues to fail, investigate each error to see if there were API differences between the component and
the NuGet package.

Components without a NuGet migration path

Don't be concerned if you don't immediately find a replacement for components used in your application.
Existing components will continue to work in Visual Studio 15.5, and the Components node will appear in your
solution as usual.
Future Visual Studio releases, however, will not restore or update components. This means if you open the
solution on a new computer, the component will not be downloaded and installed; and the author will not be
able to provide you with updates. You should plan to:

Extract the assemblies from the component and reference them directly in your project.
Contact the component author and ask about plans to migrate to NuGet.
Investigate alternative NuGet packages, or seek the source code if the component is open-source.

Many component vendors are still working on migrating to NuGet, and others (including commercially available
products) may be investigating alternative delivery options.
iOS and Mac

Code Sharing

For elements of your code that have no user interface elements the best way to share code
between iOS and Mac is still the use of Portable Class Libraries.

For code that has to do some user interface work and yet, you want to share, you should use
Shared Projects which allow you to place code to share in a single project and have it
compiled with both Mac and iOS when referenced.

Unified API

The Unified API for iOS and Mac projects uses the same namespaces for frameworks so
that the same code file can be used across both platforms, for seamless code-sharing. It
also enables both 32 and 64 bit builds. The Unified API has been the template default since
early 2015, and is recommended for all new projects - only Unified API projects can be
submitted to the App Store.

Classic APIs

ℹ️ Classic Profile Deprecation: As new platforms are added in Xamarin.iOS


we are starting to gradually deprecate features from the classic profile
(monotouch.dll). For example, the non-NRC (new-ref-count) option was
removed. NRC has always been enabled for all unified applications (i.e. non-
NRC was never an option) and has no known issues. Future releases will
remove the option of using Boehm as the garbage collector. This was also an
option never available to unified applications. The complete removal of classic
support is scheduled for fall 2016 with the release of Xamarin.iOS 10.0.

The original (non-Unified) Xamarin.iOS and Xamarin.Mac APIs made code-sharing more
difficult because native frameworks had either MonoTouch. or MonoMac. namespace
prefixes. We provided some empty namespaces that allows developers to share code by
adding using statements that reference both MonoMac and MonoTouch namespaces on
the same file, but this was a little ugly. The Classic API should only continue to be used in
legacy apps that are internally distributed (upgrading to the Unified API is recommended).

Updating from Classic to the Unified API

There are detailed instructions for updating any application from the Classic to the Unified
API.

Binding Objective-C Libraries

Xamarin lets you bring native libraries into your apps with bindings. This section explains:

how bindings work,


how to manually build a binding project that lets you bring Objective-C code into
Xamarin, and
how to use our Objective Sharpie tool to help automate the process.

Native References

Mac/iOS Native Types

To support 32 and 64 bit code transparently from C# and F#, we are introducing new data
types. Learn about them here.

Building 32 and 64 bit apps

What you need to know to support 32 and 64 bit applications.

Working with Native Types in Cross-Platform Apps

This article covers using the new iOS Unified API Native types (nint, nuint, nfloat) in a
cross-platform application where code is shared with non-iOS devices such as Android or
Windows Phone OSes. It provides insight into when the Native types should be used and
provides several possible solutions to cases where the new type must be used with cross-
platform code.

HttpClient Stack and SSL/TLS Implementation Selector

The new HttpClient Stack Selector controls which HttpClient implementation to use in your
Xamarin.iOS, Xamarin.tvOS and Xamarin.Mac app. You can now switch to an
implementation that uses iOS’s, tvOS's or OS X's native transports (NSUrlSession or
CFNetwork depending on the OS).

SSL (Secure Socket Layer) and its successor, TLS (Transport Layer Security), provide
support for HTTP and other network connections via
System.Net.Security.SslStream. The new SSL/TLS implementation build option
switches between Mono’s own TLS stack, and one powered by Apple’s TLS stack present in
Mac and iOS.
Apple Account Management

Overview
The Apple account management interface provides a way to view all development teams associated with an
Apple ID. It also allows you to view more details about each team by displaying a list of Signing Identities and
Provisioning Profiles that are installed on your machine.

Authentication of your Apple ID is performed on the command line with fastlane. fastlane must be installed on
your machine for you to be successfully authenticated. More information on fastlane and how to install it is
detailed in the fastlane guides.

The Apple Account dialog in Visual Studio for Mac allows you to do the following:

Create and Manage Certificates


Create and Manage Provisioning Profiles

Information on how to do this is described in this guide.

You can also use the iOS Bundle Signing tools to do the following:

Add a new signing identity to an existing profile


Provision new devices

For more information on using these features, refer to the Device Provisioning guide. ️

Requirements
Apple account management is available on Visual Studio for Mac. It is not currently available on Visual Studio for
Windows.

You must have an Apple Developer account to use this feature. More information on Apple developer accounts is
available in the Device Provisioning guide.

Ensure you are connected to the internet. This is because fastlane communicates directly with the Apple
Developer portal.
Ensure you have fastlane tools installed.
Ensure you have the latest fastlane tools from https://download.fastlane.tools.
Before you begin, make sure to accept any user license agreements in the developer portal.
Adding an Apple developer account
1. To open the account management dialog go to Visual Studio > Preferences > Apple Developer
Account:

2. Press the + button to display the sign in dialog, as depicted below:

3. Enter your Apple ID and Password and click the Sign In button. This will save your credentials in the
secure Keychain on this machine. fastlane is used to handle your credentials securely and pass them to
Apple's developer portal.

4. Select Always Allow on the alert dialog to allow Visual Studio to use your credentials :

5. Once your account has been added successfully, you'll see your Apple ID and any teams that your Apple
ID is part of.
6. Select any team and press the View Details… button. This will display a list of all Signing Identities and
Provisioning Profiles that are installed on your machine:

Managing Signing Identities and Provisioning


Profiles
The team details dialog displays a list of Signing Identities, organized by type. The Status column advises you if
the certificate is:

Valid – The signing identity (both the certificate and the private key) is installed on your machine and it has
not expired.

Not in Keychain – There is a valid signing identity on Apple's server. To install this on your machine, it
must be exported from another machine. You cannot download the signing identity from the Apple
Developer Portal as it will not contain the private key.
Private key is missing – A Certificate with no private key is installed in the keychain.

Expired – The Certificate is expired. You should remove this from your keychain.

Create a Signing Identities

To create a new signing identity, select the Create new Certificate drop-down button and select the type that
you require. If you have the correct permissions a new signing identity will appear after a few seconds.

If an option in the drop-down is greyed out and unselected, as illustrated below, it means that you do not have the
correct team permissions to create this type of certificate.

Download Provisioning Profiles

The team details dialog also displays a list of all provisioning profiles connected to your developer account. You
can download all provisioning profiles to your local machine by pressing the Download all Profiles button
iOS Bundle Signing
For information on deploying your app to a device, refer to the device provisioning guide.

Troubleshooting
View Details dialog is empty

This is currently a known issue, relating to bug #53906. Make sure that you are using the latest stable version of
Visual Studio for Mac

If you are experiencing issues logging in your account, please try the following:

Open the keychain application and under Category select Passwords. Search for deliver., and delete all
entries.

"Error Adding Account. Please Sign in with an app-specific password"

This is because 2 factor authentication is enabled on your account. Make sure that you are using the latest stable
version of Visual Studio for Mac

Failed to create new certificate

"You have reached the limit for certificates of this type"

The maximum number of certificates allowed have been generated. To fix this, browse to the Apple Developer
Center and revoke one of the Production Certificates.

Known Issues:
Sometimes the View Details dialog can take an inordinate amount of time to fetch the signing identities and
profiles.
Often the focus may not return to Visual Studio for Mac after entering your details, causing your account
not to be added. If this is the case, try the process again.
Provisioning profiles created in Visual Studio for Mac will not take into account entitlements selected in your
projects (Entitlements.plist). This functionality will be added in future versions of the IDE.
Distribution provisioning profiles by default will target App Store. In House or Ad Hoc profiles should be
created manually.
Unified API
To
improve
code
sharing
between
Mac
and
iOS
and
to
enable
developers
to
have
a
single
code
base
that
works
on
32
and
64
bits,
in
early
2015
we
introduced
a
new
API
in
both
Xamarin.Mac
and
Xamarin.iOS
products
called
the
Unified
API.

⚠️
Classic Profile Deprecation:
As
new
platforms
are
added
in
Xamarin.iOS
we
are
starting
to
gradually
deprecate
features
from
the
classic
profile
(monotouch.dll).
For
example,
the
non-NRC
(new-ref-count)
option
was
removed.
NRC
has
always
been
enabled
for
all
unified
applications
(i.e.
non-NRC
was
never
an
option)
and
has
no
known
issues.
Future
releases
will
remove
the
option
of
using
Boehm
as
the
garbage
collector.
This
was
also
an
option
never
available
to
unified
applications.
The
complete
removal
of
classic
support
is
scheduled
for
next
fall
with
the
release
of
Xamarin.iOS
10.0.

Overview

Describes
the
rationale
behind
the
Unified
API
and
explains
the
differences
from
the
Classic
API
in
detail.
Refer
to
this
page
to
understand
the
changes
that
have
been
made
in
the
Unified
API.

Updating Classic API-based Apps

Follow
the
relevant
instructions
for
your
platform:

Update
Existing
Apps
Update
Existing
iOS
Apps
Update
Existing
Mac
Apps
Update
Existing
Xamarin.Forms
Apps
Migrating
a
Binding
to
the
Unified
API

Tips for Updating Code to the Unified API

Regardless
of
what
applications
you
are
migrating,
check
out
these
tips
to
help
you
successfully
update
to
the
Unified
API.
The Road to 64 Bits
For
background
on
supporting
32
and
64
bit
applications
and
information
about
frameworks
see
the
32
and
64
bit
Platform
Considerations.

New Data Types

At
the
core
of
the
difference,
both
Mac
and
iOS
APIs
use
an
architecture-specific
data
types
that
are
always
32
bit
on
32
bit
platforms
and
64
bit
on
64
bit
platforms.

For
example,
Objective-C
maps
the
NSInteger
data
type
to
int32_t
on
32
bit
systems
and
to
int64_t
on
64
bit
systems.

To
match
this
behavior,
on
our
Unified
API,
we
are
replacing
the
previous
uses
of
int
(which
in
.NET
is
defined
as
always
being
System.Int32)
to
a
new
data
type:
System.nint.
You
can
think
of
the
"n"
as
meaning
"native",
so
the
native
integer
type
of
the
platform.

We
are
introducing
nint,
nuint
and
nfloat
as
well
providing
data
types
built
on
top
of
them
where
necessary.

To
learn
more
about
these
data
type
changes,
see
the
Native
Types
document.

How to detect the architecture of iOS apps


There
might
be
situations
where
your
application
needs
to
know
if
it
is
running
on
a
32
bit
or
a
64
bit
iOS
system.
The
following
code
can
be
used
to
check
the
architecture:

if (IntPtr.Size == 4) {
Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
Console.WriteLine ("64-bit App");
}

Xamarin.iOS.dll``Xamarin.Mac.dll

Library Split
From
this
point
on,
our
APIs
will
be
surfaced
in
two
ways:

Classic API:
Limited
to
32-bits
(only)
and
exposed
in
the
monotouch.dll
and
XamMac.dll
assemblies.
Unified API:
Support
both
32
and
64
bit
development
with
a
single
API
available
in
the
Xamarin.iOS.dll
and
Xamarin.Mac.dll
assemblies.

This
means
that
for
Enterprise
developers
(not
targetting
the
App
Store),
you
can
continue
using
the
existing
Classic
APIs,
as
we
will
keep
maintaining
them
forever,
or
you
can
upgrade
to
the
new
APIs.

Namespace Changes

To
reduce
the
friction
to
share
code
between
our
Mac
and
iOS
products,
we
are
changing
the
namespaces
for
the
APIs
in
the
products.

We
are
dropping
the
prefix
"MonoTouch"
from
our
iOS
product
and
"MonoMac"
from
our
Mac
product
on
the
data
types.

This
makes
it
simpler
to
share
code
between
the
Mac
and
iOS
platforms
without
resorting
to
conditional
compilation
and
will
reduce
the
noise
at
the
top
of
your
source
code
files.

Classic API:
Namespaces
use
MonoTouch.
or
MonoMac.
prefix.
Unified API:
No
namespace
prefix

API Changes

The
Unified
API
removes
deprecated
methods
and
there
are
a
few
instances
where
there
were
typos
in
the
API
names
when
they
were
bound
to
the
original
MonoTouch
and
MonoMac
namespaces
in
the
Classic
APIs.
These
instances
have
been
corrected
in
the
new
Unified
APIs
and
will
need
to
be
updated
in
your
component,
iOS
and
Mac
applications.
Here
is
a
list
of
the
most
common
ones
you
might
run
into:

Classic API Method Name Unified API Method Name

UINavigationController.PushViewControllerAnimated() UINavigationController.PushViewController()

UINavigationController.PopViewControllerAnimated() UINavigationController.PopViewController()

CGContext.SetRGBFillColor() CGContext.SetFillColor()
NetworkReachability.SetCallback() NetworkReachability.SetNotification()

CGContext.SetShadowWithColor CGContext.SetShadow

UIView.StringSize UIKit.UIStringDrawing.StringSize

For
a
full
list
of
changes
when
switching
from
the
Classic
to
the
Unified
API,
please
see
our
Classic
(monotouch.dll)
vs
Unified
(Xamarin.iOS.dll)
API
differences
documentation.

Updating to Unified

Several
old/broken/deprecated
API
in
classic
are
not
available
in
the
Unified
API.
It
can
be
easier
to
fix
the
CS0616
warnings
before
starting
your
(manual
or
automated)
upgrade
since
you'll
have
the
[Obsolete]
attribute
message
(part
of
the
warning)
to
guide
you
to
the
right
API.

Note
that
we
are
publishing
a
diff
of
the
classic
vs
unified
API
changes
that
can
be
used
either
before
or
after
your
project
updates.
Still
fixing
the
obsoletes
calls
in
Classic
will
often
be
a
time
saver
(less
documentation
lookups).

Follow
these
instructions
to
update
existing
iOS
apps,
or
Mac
apps
to
the
Unified
API.
Review
the
remainder
of
this
page,
and
these
tips
for
additional
information
on
migrating
your
code.

NuGet

NuGet
packages
that
previously
supported
Xamarin.iOS
via
the
Classic
API
published
their
assemblies
using
the
Monotouch10
platform
moniker.

The
Unified
API
introduces
a
new
platform
identifier
for
compatible
packages
-
Xamarin.iOS10.
Existing
NuGet
packages
will
need
to
be
updated
to
add
support
for
this
platform,
by
building
against
the
Unified
API.

⚠️
NOTE:
If
you
have
an
error
in
the
form
"Error 3 Cannot include both 'monotouch.dll'
and 'Xamarin.iOS.dll' in the same Xamarin.iOS project - 'Xamarin.iOS.dll' is referenced
explicitly, while 'monotouch.dll' is referenced by 'xxx, Version=0.0.000, Culture=neutral,
PublicKeyToken=null'"
after
converting
your
application
to
the
Unified
APIs,
it
is
typically
due
to
having
either
a
component
or
NuGet
Package
in
the
project
that
has
not
been
updated
to
the
Unified
API.
You'll
need
to
remove
the
existing
component/NuGet,
update
to
a
version
that
supports
the
Unified
APIs
and
do
a
clean
build.
The Road to 64 Bits
For
background
on
supporting
32
and
64
bit
applications
and
information
about
frameworks
see
the
32
and
64
bit
Platform
Considerations.

New Data Types

At
the
core
of
the
difference,
both
Mac
and
iOS
APIs
use
an
architecture-specific
data
types
that
are
always
32
bit
on
32
bit
platforms
and
64
bit
on
64
bit
platforms.

For
example,
Objective-C
maps
the
NSInteger
data
type
to
int32_t
on
32
bit
systems
and
to
int64_t
on
64
bit
systems.

To
match
this
behavior,
on
our
Unified
API,
we
are
replacing
the
previous
uses
of
int
(which
in
.NET
is
defined
as
always
being
System.Int32)
to
a
new
data
type:
System.nint.
You
can
think
of
the
"n"
as
meaning
"native",
so
the
native
integer
type
of
the
platform.

We
are
introducing
nint,
nuint
and
nfloat
as
well
providing
data
types
built
on
top
of
them
where
necessary.

To
learn
more
about
these
data
type
changes,
see
the
Native
Types
document.

How to detect the architecture of iOS apps


There
might
be
situations
where
your
application
needs
to
know
if
it
is
running
on
a
32
bit
or
a
64
bit
iOS
system.
The
following
code
can
be
used
to
check
the
architecture:

if (IntPtr.Size == 4) {
Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
Console.WriteLine ("64-bit App");
}

Arrays and System.Collections.Generic


Because
C#
indexers
expect
a
type
of
int,
you'll
have
to
explicitly
cast
nint
values
to
int
to
access
the
elements
in
a
collection
or
array.
For
example:

public List<string> Names = new List<string>();


...

public string GetName(nint index) {


return Names[(int)index];
}

This
is
expected
behavior,
because
the
cast
from
int
to
nint
is
lossy
on
64
bit,
an
implicit
conversion
is
not
done.

Converting DateTime to NSDate


When
using
the
Unified
APIs,
the
implicit
conversion
of
DateTime
to
NSDate
values
is
no
longer
performed.
These
values
will
need
to
be
explicitly
converted
from
one
type
to
another.
The
following
extension
methods
can
be
used
to
automate
this
process:

public static DateTime NSDateToDateTime(this NSDate date)


{
// NSDate has a wider range than DateTime, so clip
// the converted date to DateTime.Min|MaxValue.
double secs = date.SecondsSinceReferenceDate;
if (secs < -63113904000)
return DateTime.MinValue;
if (secs > 252423993599)
return DateTime.MaxValue;
return (DateTime) date;
}

public static NSDate DateTimeToNSDate(this DateTime date)


{
if (date.Kind == DateTimeKind.Unspecified)
date = DateTime.SpecifyKind (date, /* DateTimeKind.Local or
DateTimeKind.Utc, this depends on each app */)
return (NSDate) date;
}

Deprecated APIs and Typos


Inside
Xamarin.iOS
classic
API
(monotouch.dll)
the
[Obsolete]
attribute
was
used
in
two
different
ways:

Deprecated iOS API:


This
is
when
Apple
hints
to
you
to
stop
using
an
API
because
it's
being
superseded
by
a
newer
one.
The
Classic
API
is
still
fine
and
often
required
(if
you
support
the
older
version
of
iOS).
Such
API
(and
the
[Obsolete]
attribute)
are
included
into
the
new
Xamarin.iOS
assemblies.
Incorrect API
Some
API
had
typos
on
their
names.

For
the
original
assemblies
(monotouch.dll
and
XamMac.dll)
we
kept
the
old
code
available
for
compatibility
but
they
have
been
removed
from
the
Unified
API
assemblies
(Xamarin.iOS.dll
and
Xamarin.Mac)

NSObject subclasses .ctor(IntPtr)


Every
NSObject
subclass
has
a
constructor
that
accepts
an
IntPtr.
This
is
how
we
can
instantiate
a
new
managed
instance
from
a
native
ObjC
handle.

In
classic
this
was
a
public
constructor.
However
it
was
easy
to
misuse
this
feature
in
user
code,
e.g.
creating
several
managed
instances
for
a
single
ObjC
instance
or
creating
a
managed
instance
that
would
lack
the
expected
managed
state
(for
subclasses).

To
avoid
those
kind
of
problems
the
IntPtr
constructors
are
now
protected
in
unified
API,
to
be
used
only
for
subclassing.
This
will
ensure
the
correct/safe
API
is
used
to
create
managed
instance
from
handles,
i.e.

var label = Runtime.GetNSObject<UILabel> (handle);

This
API
will
return
an
existing
managed
instance
(if
it
already
exists)
or
will
create
a
new
one
(when
required).
It
is
already
available
in
both
classic
and
unified
API.

Note
that
the
.ctor(NSObjectFlag)
is
now
also
protected
but
this
one
was
rarely
used
outside
of
subclassing.
NSAction Replaced with Action
With
the
Unified
APIs,
NSAction
has
been
removed
in
favor
of
the
standard
.NET
Action.
This
is
a
big
improvement
because
Action
is
a
common
.NET
type,
whereas
NSAction
was
specific
to
Xamarin.iOS.
They
both
do
exactly
the
same
thing,
but
they
were
distinct
and
incompatible
types
and
resulted
in
more
code
having
to
be
written
to
achieve
the
same
result.

For
example,
if
your
existing
Xamarin
application
included
the
following
code:

UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new


NSAction (delegate() {
ShowDropDownAnimated (tblDataView);
}));

It
can
now
be
replaced
with
a
simple
lambda:

UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() =>


ShowDropDownAnimated(tblDataView));

Previously
that
would
be
a
compiler
error
because
an
Action
can't
be
assigned
to
NSAction,
but
since
UITapGestureRecognizer
now
takes
an
Action
instead
of
an
NSAction
it
is
valid
in
the
Unified
APIs.

Custom delegates replaced with Action


In
unified
some
simple
(e.g.
one
parameter)
.net
delegates
were
replaced
with
Action<T>.
E.g.

public delegate void NSNotificationHandler (NSNotification notification);

can
now
be
used
as
an
Action<NSNotification>.
This
promote
code
reuse
and
reduce
code
duplication
inside
both
Xamarin.iOS
and
your
own
applications.

Task replaced with Task>


In
classic
there
were
some
async
APIs
returning
Task<bool>.
However
some
of
them
where
are
to
use
when
an
NSError
was
part
of
the
signature,
i.e.
the
bool
was
already
true
and
you
had
to
catch
an
exception
to
get
the
NSError.

Since
some
errors
are
very
common
and
the
return
value
was
not
useful
this
pattern
was
changed
in
unified
to
return
a
Task<Tuple<Boolean,NSError>>.
This
allows
you
to
check
both
the
success
and
any
error
that
could
have
happened
during
the
async
call.

NSString vs string
In
a
few
cases
some
constants
had
to
be
changed
from
string
to
NSString,
e.g.
UITableViewCell

Classic

public virtual string ReuseIdentifier { get; }

Unified

public virtual NSString ReuseIdentifier { get; }

In
general
we
prefer
the
.NET
System.String
type.
However,
despite
Apple
guidelines,
some
native
API
are
comparing
constant
pointers
(not
the
string
itself)
and
this
can
only
work
when
we
expose
the
constants
as
NSString.

Objective-C Protocols
The
original
MonoTouch
did
not
have
full
support
for
ObjC
protocols
and
some,
non-optimal,
API
were
added
to
support
the
most
common
scenario.
This
limitation
does
not
exists
anymore
but,
for
backward
compatibility,
several
APIs
are
kept
around
inside
monotouch.dll
and
XamMac.dll.

These
limitations
have
been
removed
and
cleaned
up
on
the
Unified
APIs.
Most
changes
will
look
like
this:

Classic

public virtual AVAssetResourceLoaderDelegate Delegate { get; }

Unified
public virtual IAVAssetResourceLoaderDelegate Delegate { get; }

The
I
prefix
means
unified
expose
an
interface,
instead
of
a
specific
type,
for
the
ObjC
protocol.
This
will
ease
cases
where
you
do
not
want
to
subclass
the
specific
type
that
Xamarin.iOS
provided.

It
also
allowed
some
API
to
be
more
precise
and
easy
to
use,
e.g.:

Classic

public virtual void SelectionDidChange (NSObject uiTextInput);

Unified

public virtual void SelectionDidChange (IUITextInput uiTextInput);

Such
API
are
now
easier
to
us,
without
refering
to
documentation,
and
your
IDE
code
completion
will
provide
you
with
more
useful
suggestions
based
on
the
protocol/interface.

NSCoding Protocol

Our
original
binding
included
an
.ctor(NSCoder)
for
every
type
-
even
if
it
did
not
support
the
NSCoding
protocol.
A
single
Encode(NSCoder)
method
was
present
in
the
NSObject
to
encode
the
object.
But
this
method
would
only
work
if
the
instance
conformed
to
NSCoding
protocol.

On
the
Unified
API
we
have
fixed
this.
The
new
assemblies
will
only
have
the
.ctor(NSCoder)
if
the
type
conforms
to
NSCoding.
Also
such
types
now
have
an
Encode(NSCoder)
method
which
conforms
to
the
INSCoding
interface.

Low
Impact:
In
most
cases
this
change
won’t
affect
applications
as
the
old,
removed,
constructors
could
not
be
used.

Further Tips

Additional
changes
to
be
aware
of
are
listed
in
the
tips
for
updating
apps
to
the
Unified
API.

Sample Code
As
of
July
31st,
we
have
published
ports
of
the
iOS
samples
to
this
new
API
on
the
magic-types
branch
at
monotouch-samples.

For
Mac,
we
are
checking
samples
in
both
the
mac-samples
repo
(showing
new
APIs
in
Mavericks/Yosemite)
as
well
as
32/64
bit
samples
in
the
magic-types
branch
mac-samples.
-->
Unified API Overview
To improve code sharing between Mac and iOS and to enable developers to have a single code base
that works on 32 and 64 bits, in early 2015 we introduced a new API in both Xamarin.Mac and
Xamarin.iOS products called the Unified API.

⚠️ Classic Profile Deprecation: As new platforms are added in Xamarin.iOS we are


starting to gradually deprecate features from the classic profile (monotouch.dll). For
example, the non-NRC (new-ref-count) option was removed. NRC has always been
enabled for all unified applications (i.e. non-NRC was never an option) and has no known
issues. Future releases will remove the option of using Boehm as the garbage collector.
This was also an option never available to unified applications. The complete removal of
classic support is scheduled for next fall with the release of Xamarin.iOS 10.0.

iOS
The Xamarin.iOS.dll assembly shipped with Xamarin.iOS 8.6 is our first stable and supported
version of the Unified API for iOS. Previous preview versions of the unified API are close but not fully
compatible.

Mac
The Xamarin.Mac.dll assembly in the stable channel of Xamarin.Mac is our first stable and
supported version of the Unified API for Mac. Previous preview versions of the unified API are close
but not fully compatible.

Runtime Defaults
The Unified API by default uses the SGen garbage collector and the New Reference Counting
system for tracking object ownership. This same feature has been ported to Xamarin.Mac.

This solves a number of problems that developers faced with the old system and also ease memory
management.
Note that it is possible to enable New Refcount even for the Classic API, but the default is
conservative and does not require users to make any changes. With the Unified API, we took the
opportunity of changing the default and give developers all the improvements at the same time that
they refactor and re-test their code.

Library Split
From this point on, our APIs will be surfaced in two ways:

Classic API: Limited to 32-bits (only) and exposed in the monotouch.dll and XamMac.dll
assemblies.
Unified API: Support both 32 and 64 bit development with a single API available in the
Xamarin.iOS.dll and Xamarin.Mac.dll assemblies.

This means that for Enterprise developers (not targetting the App Store), you can continue using the
existing Classic APIs, as we will keep maintaining them forever, or you can upgrade to the new APIs.

Namespace Changes

To reduce the friction to share code between our Mac and iOS products, we are changing the
namespaces for the APIs in the products.

We are dropping the prefix "MonoTouch" from our iOS product and "MonoMac" from our Mac product
on the data types.

This makes it simpler to share code between the Mac and iOS platforms without resorting to
conditional compilation and will reduce the noise at the top of your source code files.

Classic API: Namespaces use MonoTouch. or MonoMac. prefix.


Unified API: No namespace prefix

API Changes

The Unified API removes deprecated methods and there are a few instances where there were typos
in the API names when they were bound to the original MonoTouch and MonoMac namespaces in
the Classic APIs. These instances have been corrected in the new Unified APIs and will need to be
updated in your component, iOS and Mac applications. Here is a list of the most common ones you
might run into:

Classic API Method Name Unified API Method Name

UINavigationController.PushViewControllerAnimated() UINavigationController.PushViewController()

UINavigationController.PopViewControllerAnimated() UINavigationController.PopViewController()

CGContext.SetRGBFillColor() CGContext.SetFillColor()

NetworkReachability.SetCallback() NetworkReachability.SetNotification()

CGContext.SetShadowWithColor CGContext.SetShadow

UIView.StringSize UIKit.UIStringDrawing.StringSize

For a full list of changes when switching from the Classic to the Unified API, please see our Classic
(monotouch.dll) vs Unified (Xamarin.iOS.dll) API differences documentation.

Updating to Unified

Several old/broken/deprecated API in classic are not available in the Unified API. It can be easier to
fix the CS0616 warnings before starting your (manual or automated) upgrade since you'll have the
[Obsolete] attribute message (part of the warning) to guide you to the right API.

Note that we are publishing a diff of the classic vs unified API changes that can be used either before
or after your project updates. Still fixing the obsoletes calls in Classic will often be a time saver (less
documentation lookups).

Follow these instructions to update existing iOS apps, or Mac apps to the Unified API. Review the
remainder of this page, and these tips for additional information on migrating your code.

Components and NuGet


Most existing components and NuGet packages will need to be updated to support the Unified API.
Components built against the Classic API cannot be referenced from a Unified API project.

Existing components that did not have any references to monotouch.dll (or XamMac.dll) should
not require updates.
Components

iOS components in the Xamarin Component Store must be updated to work with Unified API projects.
Xamarin is working to update the components we publish and encourage other authors to do the
same.

NuGet

NuGet packages that previously supported Xamarin.iOS via the Classic API published their
assemblies using the Monotouch10 platform moniker.

The Unified API introduces a new platform identifier for compatible packages - Xamarin.iOS10.
Existing NuGet packages will need to be updated to add support for this platform, by building against
the Unified API.

⚠️ NOTE: If you have an error in the form "Error 3 Cannot include both 'monotouch.dll'
and 'Xamarin.iOS.dll' in the same Xamarin.iOS project - 'Xamarin.iOS.dll' is referenced
explicitly, while 'monotouch.dll' is referenced by 'xxx, Version=0.0.000, Culture=neutral,
PublicKeyToken=null'" after converting your application to the Unified APIs, it is typically
due to having either a component or NuGet Package in the project that has not been
updated to the Unified API. You'll need to remove the existing component/NuGet, update
to a version that supports the Unified APIs and do a clean build.

Arrays and System.Collections.Generic


Because C# indexers expect a type of int, you'll have to explicitly cast nint values to int to
access the elements in a collection or array. For example:

public List<string> Names = new List<string>();


...

public string GetName(nint index) {


return Names[(int)index];
}

This is expected behavior, because the cast from int to nint is lossy on 64 bit, an implicit
conversion is not done.

Converting DateTime to NSDate


When using the Unified APIs, the implicit conversion of DateTime to NSDate values is no longer
performed. These values will need to be explicitly converted from one type to another. The following
extension methods can be used to automate this process:

public static DateTime NSDateToDateTime(this NSDate date)


{
// NSDate has a wider range than DateTime, so clip
// the converted date to DateTime.Min|MaxValue.
double secs = date.SecondsSinceReferenceDate;
if (secs < -63113904000)
return DateTime.MinValue;
if (secs > 252423993599)
return DateTime.MaxValue;
return (DateTime) date;
}

public static NSDate DateTimeToNSDate(this DateTime date)


{
if (date.Kind == DateTimeKind.Unspecified)
date = DateTime.SpecifyKind (date, /* DateTimeKind.Local or
DateTimeKind.Utc, this depends on each app */)
return (NSDate) date;
}

Deprecated APIs and Typos


Inside Xamarin.iOS classic API (monotouch.dll) the [Obsolete] attribute was used in two different
ways:

Deprecated iOS API: This is when Apple hints to you to stop using an API because it's being
superseded by a newer one. The Classic API is still fine and often required (if you support the
older version of iOS). Such API (and the [Obsolete] attribute) are included into the new
Xamarin.iOS assemblies.
Incorrect API Some API had typos on their names.

For the original assemblies (monotouch.dll and XamMac.dll) we kept the old code available for
compatibility but they have been removed from the Unified API assemblies (Xamarin.iOS.dll and
Xamarin.Mac)

NSObject subclasses .ctor(IntPtr)


Every NSObject subclass has a constructor that accepts an IntPtr. This is how we can instantiate
a new managed instance from a native ObjC handle.

In classic this was a public constructor. However it was easy to misuse this feature in user code,
e.g. creating several managed instances for a single ObjC instance or creating a managed instance
that would lack the expected managed state (for subclasses).

To avoid those kind of problems the IntPtr constructors are now protected in unified API, to be
used only for subclassing. This will ensure the correct/safe API is used to create managed instance
from handles, i.e.

var label = Runtime.GetNSObject<UILabel> (handle);

This API will return an existing managed instance (if it already exists) or will create a new one (when
required). It is already available in both classic and unified API.

Note that the .ctor(NSObjectFlag) is now also protected but this one was rarely used outside
of subclassing.

NSAction Replaced with Action


With the Unified APIs, NSAction has been removed in favor of the standard .NET Action. This is a
big improvement because Action is a common .NET type, whereas NSAction was specific to
Xamarin.iOS. They both do exactly the same thing, but they were distinct and incompatible types and
resulted in more code having to be written to achieve the same result.

For example, if your existing Xamarin application included the following code:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new
NSAction (delegate() {
ShowDropDownAnimated (tblDataView);
}));

It can now be replaced with a simple lambda:

UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() =>


ShowDropDownAnimated(tblDataView));

Previously that would be a compiler error because an Action can't be assigned to NSAction, but
since UITapGestureRecognizer now takes an Action instead of an NSAction it is valid in the
Unified APIs.

Custom delegates replaced with Action


In unified some simple (e.g. one parameter) .net delegates were replaced with Action<T>. E.g.

public delegate void NSNotificationHandler (NSNotification notification);

can now be used as an Action<NSNotification>. This promote code reuse and reduce code
duplication inside both Xamarin.iOS and your own applications.

Task replaced with Task>


In classic there were some async APIs returning Task<bool>. However some of them where are to
use when an NSError was part of the signature, i.e. the bool was already true and you had to
catch an exception to get the NSError.

Since some errors are very common and the return value was not useful this pattern was changed in
unified to return a Task<Tuple<Boolean,NSError>>. This allows you to check both the success
and any error that could have happened during the async call.

NSString vs string
In a few cases some constants had to be changed from string to NSString, e.g.
UITableViewCell

Classic

public virtual string ReuseIdentifier { get; }

Unified

public virtual NSString ReuseIdentifier { get; }

In general we prefer the .NET System.String type. However, despite Apple guidelines, some
native API are comparing constant pointers (not the string itself) and this can only work when we
expose the constants as NSString.

Objective-C Protocols
The original MonoTouch did not have full support for ObjC protocols and some, non-optimal, API
were added to support the most common scenario. This limitation does not exists anymore but, for
backward compatibility, several APIs are kept around inside monotouch.dll and XamMac.dll.

These limitations have been removed and cleaned up on the Unified APIs. Most changes will look like
this:

Classic

public virtual AVAssetResourceLoaderDelegate Delegate { get; }

Unified

public virtual IAVAssetResourceLoaderDelegate Delegate { get; }

The I prefix means unified expose an interface, instead of a specific type, for the ObjC protocol. This
will ease cases where you do not want to subclass the specific type that Xamarin.iOS provided.

It also allowed some API to be more precise and easy to use, e.g.:

Classic

public virtual void SelectionDidChange (NSObject uiTextInput);


Unified

public virtual void SelectionDidChange (IUITextInput uiTextInput);

Such API are now easier to us, without refering to documentation, and your IDE code completion will
provide you with more useful suggestions based on the protocol/interface.

NSCoding Protocol

Our original binding included an .ctor(NSCoder) for every type - even if it did not support the
NSCoding protocol. A single Encode(NSCoder) method was present in the NSObject to encode
the object. But this method would only work if the instance conformed to NSCoding protocol.

On the Unified API we have fixed this. The new assemblies will only have the .ctor(NSCoder) if
the type conforms to NSCoding. Also such types now have an Encode(NSCoder) method which
conforms to the INSCoding interface.

Low Impact: In most cases this change won’t affect applications as the old, removed, constructors
could not be used.

Further Tips

Additional changes to be aware of are listed in the tips for updating apps to the Unified API.

Sample Code
As of July 31st, we have published ports of the iOS samples to this new API on the magic-types
branch at monotouch-samples.

For Mac, we are checking samples in both the mac-samples repo (showing new APIs in
Mavericks/Yosemite) as well as 32/64 bit samples in the magic-types branch mac-samples.
Updating Existing iOS Apps
Updating an existing app to use the Unified API requires changes to the project file itself as well as to the
namespaces and APIs used in the application code.

The Road to 64 Bits


The new Unified APIs are required to support 64 bit device architectures from a Xamarin.iOS mobile
application. As of February 1st, 2015 Apple requires that all new app submissions to the iTunes App Store
support 64 bit architectures.

Xamarin provides tooling for both Visual Studio for Mac and Visual Studio to automate the migration
process from the Classic API to the Unified API or you can convert the project files manually. While the
using the automatic tooling is highly suggested, this article will cover both methods.

Before You Start...

Before you update your existing code to the Unified API, it is highly recommended that you eliminate all
compilation warnings. Many warnings in the Classic API will become errors once you migrate to Unified.
Fixing them before you start is easier because the compiler messages from the Classic API often provide
hints on what to update.

Automated Updating
Once the warnings have been fixed, select an existing iOS project in Visual Studio for Mac or Visual Studio
and choose Migrate to Xamarin.iOS Unified API from the Project menu. For example:
You'll need to agree to this warning before the automated migration will run (obviously you should ensure
you have backups/source control before embarking on this adventure):

The tool basically automates all the steps outlined in the Update Manually section presented below and is
the suggested method of converting an existing Xamarin.iOS project to the Unified API.

Steps to Update Manually


Again, once the warnings have been fixed, follow these steps to manually update Xamarin.iOS apps to use
the new Unified API:

1. Update Project Type & Build Target

Change the project flavor in your csproj files from 6BC8ED88-2882-458C-8E55-DFD12B67127B to


FEACFBD2-3405-455C-9665-78FE426C6842. Edit the csproj file in a text editor, replacing the first item
in the <ProjectTypeGuids> element as shown:

Change the Import element that contains Xamarin.MonoTouch.CSharp.targets to


Xamarin.iOS.CSharp.targets as shown:

2. Update Project References

Expand the iOS application project's References node. It will initially show a *broken- monotouch
reference similar to this screenshot (because we just changed the project type):

Right-click on the iOS application project to Edit References, then click on the monotouch reference and
delete it using the red "X" button.

Now scroll to the end of the references list and tick the Xamarin.iOS assembly.

Press OK to save the project references changes.


3. Remove MonoTouch from Namespaces

Remove the MonoTouch prefix from namespaces in using statements or wherever a classname has
been fully qualified (eg. MonoTouch.UIKit becomes just UIKit).

4. Remap Types

Native types have been introduced which replace some Types that were previously used, such as
instances of System.Drawing.RectangleF with CoreGraphics.CGRect (for example). The full list of
types can be found on the native types page.

5. Fix Method Overrides

Some UIKit methods have had their signature changed to use the new native types (such as nint). If
custom subclasses override these methods the signatures will no longer match and will result in errors. Fix
these method overrides by changing the subclass to match the new signature using native types.

Examples include changing public override int NumberOfSections (UITableView


tableView) to return nint and changing both return type and parameter types in public override
int RowsInSection (UITableView tableView, int section) to nint.

Considerations
The following considerations should be taken into account when converting an existing Xamarin.iOS
project from the Classic API to the new Unified API if that app relies on one or more Component or NuGet
Package.

Components

Any component that you have included in your application will also need to be updated to the Unified API
or you will get a conflict when you try to compile. For any included component, replace the current version
with a new version from the Xamarin Component Store that supports the Unified API and do a clean build.
Any component that has not yet been converted by the author, will display a 32 bit only warning in the
component store.

NuGet Support
While we contributed changes to NuGet to work with the Unified API support, there has not been a new
release of NuGet, so we are evaluating how to get NuGet to recognize the new APIs.

Until that time, just like the components, you'll need to switch any NuGet Package you have included in
your project to a version that supports the Unified APIs and do a clean build afterwards.

⚠️ NOTE: If you have an error in the form "Error 3 Cannot include both 'monotouch.dll' and
'Xamarin.iOS.dll' in the same Xamarin.iOS project - 'Xamarin.iOS.dll' is referenced explicitly,
while 'monotouch.dll' is referenced by 'xxx, Version=0.0.000, Culture=neutral,
PublicKeyToken=null'" after converting your application to the Unified APIs, it is typically due to
having either a component or NuGet Package in the project that has not been updated to the
Unified API. You'll need to remove the existing component/NuGet, update to a version that
supports the Unified APIs and do a clean build.

Enabling 64 Bit Builds of Xamarin.iOS Apps


For a Xamarin.iOS mobile application that has been converted to the Unified API, the developer still needs
to enable the building of the application for 64 bit machines from the app's Options. Please see the
Enabling 64 Bit Builds of Xamarin.iOS Apps of the 32/64 bit Platform Considerations document for
detailed instructions on enabling 64 bit builds.

Finishing Up
Whether or not you choose to use the automatic or manual method to convert your Xamarin.iOS
application from the Classic to the Unified APIs, there are several instances that will require further, manual
intervention. Please see our Tips for Updating Code to the Unified API document for known issues and
work arounds.
Updating Existing Mac Apps
Updating an existing app to use the Unified API requires changes to the project file itself as well as to the
namespaces and APIs used in the application code.

The Road to 64 Bits


The new Unified APIs are required to support 64 bit device architectures from a Xamarin.Mac application.
As of February 1st, 2015 Apple requires that all new app submissions to the Mac App Store support 64 bit
architectures.

Xamarin provides tooling for both Visual Studio for Mac and Visual Studio to automate the migration
process from the Classic API to the Unified API or you can convert the project files manually. While the
using the automatic tooling is highly suggested, this article will cover both methods.

Before You Start...

Before you update your existing code to the Unified API, it is highly recommended that you eliminate all
compilation warnings. Many warnings in the Classic API will become errors once you migrate to Unified.
Fixing them before you start is easier because the compiler messages from the Classic API often provide
hints on what to update.

Automated Updating
Once the warnings have been fixed, select an existing Mac project in Visual Studio for Mac or Visual Studio
and choose Migrate to Xamarin.Mac Unified API from the Project menu. For example:
You'll need to agree to this warning before the automated migration will run (obviously you should ensure
you have backups/source control before embarking on this adventure):

There are two supported Target Framework types that can be selected when using the Unified API in a
Xamarin.Mac application:

Xamarin.Mac Mobile Framework - This is the same tuned .NET framework used by Xamarin.iOS
and Xamarin.Android supporting a subset of the full Desktop framework. This is the recommended
framework because it provides smaller average binaries due to superior linking behavior.
Xamarin.Mac .NET 4.5 Framework - This framework is again, a subset of the Desktop framework.
However, it trims off far less of the full Desktop framework than the Mobile framework and should
"just work" with most NuGet Packages or 3rd party libraries. This allows the developer to consume
standard Desktop assemblies while still using a supported framework, but this option produces
larger application bundles. This is the recommended framework where 3rd party .NET assemblies
are being used that are not compatible with the Xamarin.Mac Mobile Framework. For a list of
supported assemblies, please see our Assemblies documentation.

For detailed information on Target Frameworks and the implications of selecting a specific target for your
Xamarin.Mac application, please see our Target Frameworks documentation.

The tool basically automates all the steps outlined in the Update Manually section presented below and is
the suggested method of converting an existing Xamarin.Mac project to the Unified API.

Steps to Update Manually


Again, once the warnings have been fixed, follow these steps to manually update Xamarin.Mac apps to use
the new Unified API:

1. Update Project Type & Build Target

Change the project flavor in your csproj files from 42C0BBD9-55CE-4FC1-8D90-A7348ABAFB23 to


A3F8F2AB-B479-4A4A-A458-A89E7DC349F1. Edit the csproj file in a text editor, replacing the first item
in the <ProjectTypeGuids> element as shown:

Change the Import element that contains Xamarin.Mac.targets to Xamarin.Mac.CSharp.targets


as shown:

Add the following lines of code after the <AssemblyName> element:

<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<TargetFrameworkIdentifier>Xamarin.Mac</TargetFrameworkIdentifier>

Example:
2. Update Project References

Expand the Mac application project's References node. It will initially show a *broken- XamMac reference
similar to this screenshot (because we just changed the project type):

Click the Gear Icon beside the XamMac entry and select Delete to remove the broken reference.

Next, right-click on the References folder in the Solution Explorer and select Edit References. Scroll to
the bottom of the list of references and place a check besides Xamarin.Mac.
Press OK to save the project references changes.

3. Remove MonoMac from Namespaces

Remove the MonoMac prefix from namespaces in using statements or wherever a classname has been
fully qualified (eg. MonoMac.AppKit becomes just AppKit).

4. Remap Types

Native types have been introduced which replace some Types that were previously used, such as
instances of System.Drawing.RectangleF with CoreGraphics.CGRect (for example). The full list of
types can be found on the native types page.

5. Fix Method Overrides

Some AppKit methods have had their signature changed to use the new native types (such as nint). If
custom subclasses override these methods the signatures will no longer match and will result in errors. Fix
these method overrides by changing the subclass to match the new signature using native types.

Considerations
The following considerations should be taken into account when converting an existing Xamarin.Mac
project from the Classic API to the new Unified API if that app relies on one or more Component or NuGet
Package.

Components

Any component that you have included in your application will also need to be updated to the Unified API
or you will get a conflict when you try to compile. For any included component, replace the current version
with a new version from the Xamarin Component Store that supports the Unified API and do a clean build.
Any component that has not yet been converted by the author, will display a 32 bit only warning in the
component store.

NuGet Support

While we contributed changes to NuGet to work with the Unified API support, there has not been a new
release of NuGet, so we are evaluating how to get NuGet to recognize the new APIs.

Until that time, just like the components, you'll need to switch any NuGet Package you have included in
your project to a version that supports the Unified APIs and do a clean build afterwards.

⚠️ NOTE: If you have an error in the form "Error 3 Cannot include both 'monomac.dll' and
'Xamarin.Mac.dll' in the same Xamarin.Mac project - 'Xamarin.Mac.dll' is referenced explicitly,
while 'monomac.dll' is referenced by 'xxx, Version=0.0.000, Culture=neutral,
PublicKeyToken=null'" after converting your application to the Unified APIs, it is typically due to
having either a component or NuGet Package in the project that has not been updated to the
Unified API. You'll need to remove the existing component/NuGet, update to a version that
supports the Unified APIs and do a clean build.

Enabling 64 Bit Builds of Xamarin.Mac Apps


For a Xamarin.Mac mobile application that has been converted to the Unified API, the developer still needs
to enable the building of the application for 64 bit machines from the app's Options. Please see the
Enabling 64 Bit Builds of Xamarin.Mac Apps of the 32/64 bit Platform Considerations document for
detailed instructions on enabling 64 bit builds.

Finishing Up
Whether or not you choose to use the automatic or manual method to convert your Xamarin.Mac
application from the Classic to the Unified APIs, there are several instances that will require further, manual
intervention. Please see our Tips for Updating Code to the Unified API document for known issues and
work arounds.
Updating Existing Xamarin.Forms Apps
⚠️ Because Xamarin.Forms 1.3.1 is the first release that supports the Unified API, the entire
solution should be updated to use the latest version at the same time as migrating the iOS app to
Unified. This means that in addition to updating the iOS project for Unified support, you'll also need
to edit code in all the projects in the solution.

The update is performed in two steps:

1. Migrate the iOS app to the Unified API using Visual Studio for Mac's build in migration tool.

Use the migration tool to automatically update the project.

Update iOS native APIs as outlined in the instructions to update iOS apps (specifically in custom
renderer or dependency service code).

2. Update the entire solution to Xamarin.Forms version 1.3.

1. Install the Xamarin.Forms 1.3.1 NuGet package.

2. Update the App class in the shared code.

3. Update the AppDelegate in the iOS project.

4. Update the MainActivity in the Android project.

5. Update the MainPage in the Windows Phone project.

1. iOS App (Unified Migration)


Part of the migration requires upgrading Xamarin.Forms to version 1.3, which supports the Unified API. In order
for the correct assembly references to be created, we first need to update the iOS project to use the Unified
API.

Migration Tool

Click on the iOS project so that it's selected, then choose Project > Migrate to Xamarin.iOS Unified API... and
agree to the warning message that appears.
This will automatically:

Change the project type to support the Unified 64-bit API.


Change the framework reference to Xamarin.iOS (replacing the old monotouch reference).
Change the namespace references in the code to remove the MonoTouch prefix.
Update the csproj file to use the correct build targets for the Unified API.

Clean and Build the project to ensure there are no other errors to fix. No further action should be required.
These steps are explained in more detail in the Unified API docs.

Update native iOS APIs (if required)

If you have added additional iOS native code (such as custom renderers or dependency services) you may
need to perform additional manual code fixes. Re-compile your app and refer to the Updating Existing iOS Apps
instructions for additional information on changes that may be required. These tips will also help identify
changes that are required.

2. Xamarin.Forms 1.3.1 Update


Once the iOS app has been updated to the Unified API, the rest of the solution needs to be updated to
Xamarin.Forms version 1.3.1. This includes:

Updating the Xamarin.Forms NuGet package in each project.


Changing the code to use the new Xamarin.Forms Application, FormsApplicationDelegate
(iOS), FormsApplicationActivity (Android), and FormsApplicationPage (Windows Phone)
classes.

These steps are explained below:

2.1 Update NuGet in all Projects

Update Xamarin.Forms to 1.3.1 pre-release using the NuGet Package Manager for all projects in the solution:
PCL (if present), iOS, Android, and Windows Phone. It is recommended that you delete and re-add the
Xamarin.Forms NuGet package to update to version 1.3.

NOTE: Xamarin.Forms version 1.3.1 is currently in pre-release. This means you must select the pre-release
option in NuGet (via a tick-box in Visual Studio for Mac or a drop-down-list in Visual Studio) to see the latest
pre-release version.

⚠️ If you are using Visual Studio, ensure the latest version of the NuGet Package Manager is
installed. Older versions of NuGet in Visual Studio will not correctly install the Unified version of
Xamarin.Forms 1.3.1. Go to Tools > Extensions and Updates... and click on the Installed list to
check that the NuGet Package Manager for Visual Studio is at least version 2.8.5. If it is older,
click on the Updates list to download the latest version.

Once you've updated the NuGet package to Xamarin.Forms 1.3.1, make the following changes in each project
to upgrade to the new Xamarin.Forms.Application class.

2.2 Portable Class Library (or Shared Project)

Change the App.cs file so that:

The App class now inherits from Application.


The MainPage property is set to the first content page you wish to display.

public class App : Application // superclass new in 1.3


{
public App ()
{
// The root page of your application
MainPage = new ContentPage {...}; // property new in 1.3
}

We have completely removed the GetMainPage method, and instead set the MainPage property on the
Application subclass.
This new Application base class also supports the OnStart, OnSleep, and OnResume overrides to help
you manage your application's lifecycle.

The App class is then passed to a new LoadApplication method in each app project, as described below:

2.3 iOS App

Change the AppDelegate.cs file so that:

The class inherits from FormsApplicationDelegate (instead of UIApplicationDelegate


previously).
LoadApplication is called with a new instance of App.

[Register ("AppDelegate")]
public partial class AppDelegate :
global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate // superclass new
in 1.3
{
public override bool FinishedLaunching (UIApplication app, NSDictionary
options)
{
global::Xamarin.Forms.Forms.Init ();

LoadApplication (new App ()); // method is new in 1.3

return base.FinishedLaunching (app, options);


}
}

2.3 Android App

Change the MainActivity.cs file so that:

The class inherits from FormsApplicationActivity (instead of FormsActivity previously).


LoadApplication is called with a new instance of App

[Activity (Label = "YOURAPPNAM", Icon = "@drawable/icon", MainLauncher = true,


ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity :
global::Xamarin.Forms.Platform.Android.FormsApplicationActivity // superclass
new in 1.3
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

global::Xamarin.Forms.Forms.Init (this, bundle);

LoadApplication (new App ()); // method is new in 1.3


}
}

2.4 Windows Phone App

We need to update the MainPage - both the XAML and the codebehind.

Change the MainPage.xaml file so that:

The root XAML element should be winPhone:FormsApplicationPage.


The xmlns:phone attribute should be changed to xmlns:winPhone="clr-
namespace:Xamarin.Forms.Platform.WinPhone;assembly=Xamarin.Forms.Platform.WP8"

An updated example is shown below - you should only have to edit these things (the rest of the attributes
should remain the same):

<winPhone:FormsApplicationPage
...
xmlns:winPhone="clr-
namespace:Xamarin.Forms.Platform.WinPhone;assembly=Xamarin.Forms.Platform.WP8"
...>
</winPhone:FormsApplicationPage>

Change the MainPage.xaml.cs file so that:

The class inherits from FormsApplicationPage (instead of PhoneApplicationPage previously).


LoadApplication is called with a new instance of the Xamarin.Forms App class. You may need to fully
qualify this reference since Windows Phone has it's own App class already defined.

public partial class MainPage :


global::Xamarin.Forms.Platform.WinPhone.FormsApplicationPage // superclass new in
1.3
{
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;

global::Xamarin.Forms.Forms.Init();
LoadApplication(new YOUR_APP_NAMESPACE.App()); // new in 1.3
}
}

Troubleshooting

Occasionally you will see an error similar to this after updating the Xamarin.Forms NuGet package. It occurs
when the NuGet updater does not completely remove references to older versions from your csproj files.

YOUR_PROJECT.csproj: Error: This project references NuGet package(s) that are missing on this
computer. Enable NuGet Package Restore to download them. For more information, see
http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is
../../packages/Xamarin.Forms.1.2.3.6257/build/portable-
win+net45+wp80+MonoAndroid10+MonoTouch10/Xamarin.Forms.targets. (YOUR_PROJECT)

To fix these errors, open the csproj file in a text editor and look for <Target elements that refer to older
versions of Xamarin.Forms, such as the element shown below. You should manually delete this entire element
from the csproj file and save the changes.

<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">


<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this
computer. Enable NuGet Package Restore to download them. For more information,
see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
</ErrorText>
</PropertyGroup>
<Error
Condition="!Exists('..\..\packages\Xamarin.Forms.1.2.3.6257\build\portable-
win+net45+wp80+MonoAndroid10+MonoTouch10\Xamarin.Forms.targets')"
Text="$([System.String]::Format('$(ErrorText)',
'..\..\packages\Xamarin.Forms.1.2.3.6257\build\portable-
win+net45+wp80+MonoAndroid10+MonoTouch10\Xamarin.Forms.targets'))" />
</Target>

The project should build successfully once these old references are removed.
Considerations
The following considerations should be taken into account when converting an existing Xamarin.Forms project
from the Classic API to the new Unified API if that app relies on one or more Component or NuGet Package.

Components

Any component that you have included in your application will also need to be updated to the Unified API or you
will get a conflict when you try to compile. For any included component, replace the current version with a new
version from the Xamarin Component Store that supports the Unified API and do a clean build. Any component
that has not yet been converted by the author, will display a 32 bit only warning in the component store.

NuGet Support

While we contributed changes to NuGet to work with the Unified API support, there has not been a new release
of NuGet, so we are evaluating how to get NuGet to recognize the new APIs.

Until that time, just like the components, you'll need to switch any NuGet Package you have included in your
project to a version that supports the Unified APIs and do a clean build afterwards.

⚠️ NOTE: If you have an error in the form "Error 3 Cannot include both 'monotouch.dll' and
'Xamarin.iOS.dll' in the same Xamarin.iOS project - 'Xamarin.iOS.dll' is referenced explicitly, while
'monotouch.dll' is referenced by 'xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null'" after
converting your application to the Unified APIs, it is typically due to having either a component or
NuGet Package in the project that has not been updated to the Unified API. You'll need to remove
the existing component/NuGet, update to a version that supports the Unified APIs and do a clean
build.

Enabling 64 Bit Builds of Xamarin.iOS Apps


For a Xamarin.iOS mobile application that has been converted to the Unified API, the developer still needs to
enable the building of the application for 64 bit machines from the app's Options. Please see the Enabling 64
Bit Builds of Xamarin.iOS Apps of the 32/64 bit Platform Considerations document for detailed instructions on
enabling 64 bit builds.

Summary
The Xamarin.Forms application should now be updated to version 1.3.1 and the iOS app migrated to the Unified
API (which supports 64-bit architectures on the iOS platform).

As noted above, if your Xamarin.Forms app includes native code such as custom renderers or dependency
services then these may also need updating to use the new Types introduced in the Unified API.
Migrating a Binding to the Unified API

Updating iOS and Mac Library Bindings for the Unified API

Overview
Starting February 1st, 2015 Apple requires that all new submissions to the iTunes and the Mac App Store must
be 64 bit applications. As a result, any new Xamarin.iOS or Xamarin.Mac application will need to be using the
new Unified API instead of the existing Classic MonoTouch and MonoMac APIs to support 64 bit.

Additionally, any Xamarin Binding Project must also support the new Unified APIs to be included in a 64 bit
Xamarin.iOS or Xamarin.Mac project. This article will cover the steps required to update an existing binding
project to use the Unified API.

Requirements
The following is required to complete the steps presented in this article:

Visual Studio for Mac - The latest version of Visual Studio for Mac installed and configured on the
development computer.
Apple Mac - An Apple mac is required to build Binding Projects for iOS and Mac.

Binding projects are not supported in Visual studio on a Windows machine.

Modify the Using Statements


The Unified APIs makes it easier than ever to share code between Mac and iOS as well as allowing you to
support 32 and 64 bit applications with the same binary. By dropping the MonoMac and MonoTouch prefixes
from the namespaces, simpler sharing is achieved across Xamarin.Mac and Xamarin.iOS application projects.

As a result we will need to modify any of our binding contracts (and other .cs files in our binding project) to
remove the MonoMac and MonoTouch prefixes from our using statements.

For example, given the following using statements in a binding contract:

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

We would strip off the MonoTouch prefix resulting in the following:

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

Again, we will need to do this for any .cs file in our binding project. With this change in place, the next step is to
update our binding project to use the new Native Data Types.

For more information on the Unified API, please see the Unified API documentation. For more background on
supporting 32 and 64 bit applications and information about frameworks see the 32 and 64 bit Platform
Considerations documentation.

Update to Native Data Types


Objective-C maps the NSInteger data type to int32_t on 32 bit systems and to int64_t on 64 bit systems.
To match this behavior, the new Unified API replaces the previous uses of int (which in .NET is defined as
always being System.Int32) to a new data type: System.nint.

Along with the new nint data type, the Unified API introduces the nuint and nfloat types, for mapping to the
NSUInteger and CGFloat types as well.

Given the above, we need to review our API and ensure that any instance of NSInteger, NSUInteger and
CGFloat that we previously mapped to int, uint and float get updated to the new nint, nuint and
nfloat types.

For example, given an Objective-C method definition of:

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

If the previous binding contract had the following definition:

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

We would update the new binding to be:

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

If we are mapping to a newer version 3rd party library than what we had initially linked to, we need to review the
.h header files for the library and see if any exiting, explicit calls to int, int32_t, unsigned int, uint32_t
or float have been upgraded to be an NSInteger, NSUInteger or a CGFloat. If so, the same modifications
to the nint, nuint and nfloat types will need to be made to their mappings as well.

To learn more about these data type changes, see the Native Types document.

Update the CoreGraphics Types


The point, size and rectangle data types that are used with CoreGraphics use 32 or 64 bits depending on the
device they are running on. When Xamarin originally bound the iOS and Mac APIs we used existing data
structures that happened to match the data types in System.Drawing (RectangleF for example).

Because of the requirements to support 64 bits and the new native data types, the following adjustments will
need to be made to existing code when calling CoreGraphic methods:

CGRect - Use CGRect instead of RectangleF when defining floating point rectangular regions.
CGSize - Use CGSize instead of SizeF when defining floating point sizes (width and height).
CGPoint - Use CGPoint instead of PointF when defining a floating point location (X and Y coordinates).

Given the above, we will need to review our API and ensure that any instance of CGRect, CGSize or CGPoint
that was previously bound to RectangleF, SizeF or PointF be changed to the native type CGRect, CGSize
or CGPoint directly.

For example, given an Objective-C initializer of:

- (id)initWithFrame:(CGRect)frame;

If our previous binding included the following code:

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

We would update that code to:

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

With all of the code changes now in place, we need to modify our binding project or make file to bind against the
Unified APIs.
Modify the Binding Project
As the final step to updating our binding project to use the Unified APIs, we need to either modify the MakeFile
that we use to build the project or the Xamarin Project Type (if we are binding from within Visual Studio for Mac)
and instruct btouch to bind against the Unified APIs instead of the Classic ones.

Updating a MakeFile

If we are using a makefile to build our binding project into a Xamarin .DLL, we will need to include the --new-
style command line option and call btouch-native instead of btouch.

So given the following 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

We need to switch from calling btouch to btouch-native, so we would adjust our macro definition as follows:

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

We would update the call to btouch and add the --new-style option as follows:

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

We can now execute our MakeFile as normal to build the new 64 bit version of our API.

Updating a Binding Project Type

If we are using a Visual Studio for Mac Binding Project Template to build our API, we'll need to update to the new
Unified API version of the Binding Project Template. The easiest way to do this is to start a new Unified API
Binding Project and copy over all of the existing code and settings.

Do the following:

1. Start Visual Studio for Mac.


2. Select File > New > Solution...

3. In the New Solution Dialog Box, select iOS > Unified API > iOS Binding Project:
4. On 'Configure your new project' dialog enter a Name for the new binding project and click the OK button.
5. Include the 64 bit version of Objective-C library that you are going to be creating bindings for.
6. Copy over the source code from your existing 32 bit Classic API binding project (such as the
ApiDefinition.cs and StructsAndEnums.cs files).
7. Make the above noted changes to the source code files.

With all of these changes in place, you can build the new 64 bit version of the API as you would the 32 bit
version.

Summary
In this article we have shown the changes that need to be made to an existing Xamarin Binding Project to support
the new Unified APIs and 64 bit devices and the steps required to build the new 64 bit compatible version of an
API.
Tips for Updating Code to the Unified API
Using the automated migration tool in Visual Studio for Mac will convert iOS and Mac projects to reference the Unified API (either
Xamarin.iOS.dll or Xamarin.Mac.dll) and make a lot of the required code changes for you (see the Xamarin Studio release notes
section 'Classic to Unified API code migration tool' for specific details).

NSInvalidArgumentException Could Not Find storyboard


Error
There is a bug in the current version of Visual Studio for Mac that can occur after using the automated migration tool to convert your
project to the Unified APIs. After the update, if you get an error message in the form:

Objective-C exception thrown. Name: NSInvalidArgumentException Reason: Could not find a storyboard
named 'xxx' in bundle NSBundle...

You can do the following to solve this issue, locate the following build target file:

/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/2.1/Xamarin.iOS.Common.targets

In this file you need to find the following target declaration:

<Target Name="_CopyContentToBundle"
Inputs = "@(_BundleResourceWithLogicalName)"
Outputs = "@(_BundleResourceWithLogicalName -> '$(_AppBundlePath)%(LogicalName)')" >

And add the DependsOnTargets="_CollectBundleResources" attribute to it. Like this:

<Target Name="_CopyContentToBundle"
DependsOnTargets="_CollectBundleResources"
Inputs = "@(_BundleResourceWithLogicalName)"
Outputs = "@(_BundleResourceWithLogicalName -> '$(_AppBundlePath)%(LogicalName)')" >

Save the file, reboot Visual Studio for Mac, and do a clean & rebuild of your project. A fix for this issue should be released by
Xamarin shortly.

Useful Tips
After using the migration tool, you may still get some compiler errors requiring manual intervention. Some things that might need to
be manually fixed include:

Comparing enums might require an (int) cast.

NSDictionary.IntValue now returns an nint, there is an Int32Value which can be used instead.

nfloat and nint types cannot be marked const; static readonly nint is a reasonable alternative.

Things that used to be directly in the MonoTouch. namespace are now generally in the ObjCRuntime. namespace (e.g.:
MonoTouch.Constants.Version is now ObjCRuntime.Constants.Version).

Code that serializes objects may break when attempting to serialize nint and nfloat types. Be sure to check your
serialization code works as expected after migration.

Sometimes the automated tool misses code inside #if #else conditional compiler directives. In this case you'll need to make
the fixes manually (see the common errors below).

Manually exported methods using [Export] may not be automatically fixed by the migration tool, for example in this code
snippert you must manually update the return type to nfloat:

[Export("tableView:heightForRowAtIndexPath:")]
public nfloat HeightForRow(UITableView tableView, NSIndexPath indexPath)

The Unified API does not provide an implicit conversion between NSDate and .NET DateTime because it's not a lossless
conversion. To prevent errors related to DateTimeKind.Unspecified convert the .NET DateTime to local or UTC before
casting to NSDate.

Objective-C category methods are now generated as extension methods in the Unified API. For example, code that previously
used UIView.DrawString would now reference NSString.DrawString in the Unified API.

Code using AVFoundation classes with VideoSettings should change to use the WeakVideoSettings property. This
requires a Dictionary, which is available as a property on the settings classes, for example:

vidrec.WeakVideoSettings = new AVVideoSettings() { ... }.Dictionary;

The NSObject .ctor(IntPtr) constructor has been changed from public to protected (to prevent improper use).

NSAction has been replaced with the starndard .NET Action. Some simple (single parameter) delegates have also been
replaced with Action<T>.

Finally, refer to the Classic v Unified API differences to look up changes to APIs in your code. Searching this page will help find
Classic APIs and what they've been updated to.

Note: the MonoTouch.Dialog namespace remains the same after migration. If your code uses MonoTouch.Dialog you should
continue to use that namespace - do not change MonoTouch.Dialog to Dialog!

Common Compiler Errors


Other examples of common errors are listed below, along with the solution:

Error CS0012: The type 'MonoTouch.UIKit.UIView' is defined in an assembly that is not referenced.

Fix: This usually means the project references a component or NuGet package that has not been built with the Unified API. You
should delete and re-add all Components and NuGet packages. If this does not fix the error, the external library may not yet support
the Unified API.

Error MT0034: Cannot include both 'monotouch.dll' and 'Xamarin.iOS.dll' in the same Xamarin.iOS project -
'Xamarin.iOS.dll' is referenced explicitly, while 'monotouch.dll' is referenced by 'Xamarin.Mobile, Version=0.6.3.0,
Culture=neutral, PublicKeyToken=null'.
Fix: Delete the component that is causing this error and re-add to the project.

Error CS0234: The type or namespace name 'Foundation' does not exist in the namespace 'MonoTouch'. Are you missing
an assembly reference?

Fix: The automated migration tool in Visual Studio for Mac should update all MonoTouch.Foundation references to Foundation,
however in some instances these will need to be updated manually. Similar errors may appear for the other namespaces previously
contained in MonoTouch, such as UIKit.

Error CS0266: Cannot implicitly convert type 'double' to 'System.float'

Fix: change type and cast to nfloat. This error may also occur for the other types with 64-bit equivalents (such as nint, )

nfloat scale = (nfloat)Math.Min(rect.Width, rect.Height);

Error CS0266: Cannot implicitly convert type 'CoreGraphics.CGRect' to 'System.Drawing.RectangleF'. An explicit


conversion exists (are you missing a cast?)

Fix: Change instances to RectangleF to CGRect, SizeF to CGSize, and PointF to CGPoint. The namespace using
System.Drawing; should be replaced with using CoreGraphics; (if it isn't already present).

error CS1502: The best overloaded method match for 'CoreGraphics.CGContext.SetLineDash(System.nfloat,


System.nfloat[])' has some invalid arguments

Fix: Change array type to nfloat[] and explicitly cast Math.PI.

grphc.SetLineDash (0, new nfloat[] { 0, 3 * (nfloat)Math.PI });

Error CS0115: `WordsTableSource.RowsInSection(UIKit.UITableView, int)' is marked as an override but no suitable method


found to override

Fix: Change the return value and parameter types to nint. This commonly occurs in method overrides such as those on
UITableViewSource, including RowsInSection, NumberOfSections, GetHeightForRow, TitleForHeader,
GetViewForHeader, etc.

public override nint RowsInSection (UITableView tableview, nint section) {

Error CS0508: WordsTableSource.NumberOfSections(UIKit.UITableView)': return type must be


'System.nint' to match overridden memberUIKit.UITableViewSource.NumberOfSections(UIKit.UITableView)'

Fix: When the return type is changed to nint, cast the return value to nint.

public override nint NumberOfSections (UITableView tableView)


{
return (nint)navItems.Count;
}

Error CS1061: Type 'CoreGraphics.CGPath' does not contain a definition for 'AddElipseInRect'

Fix: Correct spelling to AddEllipseInRect. Other name changes include:

Change 'Color.Black' to NSColor.Black.


Change MapKit 'AddAnnotation' to AddAnnotations.
Change AVFoundation 'DataUsingEncoding' to Encode.
Change AVFoundation 'AVMetadataObject.TypeQRCode' to AVMetadataObjectType.QRCode.
Change AVFoundation 'VideoSettings' to WeakVideoSettings.
Change PopViewControllerAnimated to PopViewController.
Change CoreGraphics 'CGBitmapContext.SetRGBFillColor' to SetFillColor.

Error CS0546: cannot override because `MapKit.MKAnnotation.Coordinate' does not have an overridable set accessor
(CS0546)

When creating a custom annotation by subclassing MKAnnotation the Coordinate field has no setter, only a getter.

Fix:

Add a field to keep track of the coordinate


return this field in the getter of the Coordinate property
Override the SetCoordinate method and set your field
Call SetCoordinate in your ctor with the passed in coordinate parameter

It should look similar to the following:

class BasicPinAnnotation : MKAnnotation


{
private CLLocationCoordinate2D _coordinate;

public override CLLocationCoordinate2D Coordinate


{
get
{
return _coordinate;
}
}

public override void SetCoordinate(CLLocationCoordinate2D value)


{
_coordinate = value;
}

public BasicPinAnnotation (CLLocationCoordinate2D coordinate)


{
SetCoordinate(coordinate);
}
}
Binding Objective-C
This section includes a variety of documents that cover creating bindings to Objective-C
libraries, so they can be called from C# applications created with Xamarin.iOS or
Xamarin.Mac.

Overview

This document contains some of the internals of how a binding takes place. It is an
advanced document with some technical information.

Binding Objective-C Libraries

This document describes the process used to create C# bindings of Objective-C APIs and
how the idioms in Objective-C are mapped to the idioms used in .NET. If you are binding just
C APIs, you should use the standard .NET mechanism for this, the P/Invoke framework.

Binding Definition Reference Guide

This is the reference guide that describes all of the attributes available to binding authors to
drive the binding generation process.

Objective Sharpie

Objective Sharpie is a command line tool to help bootstrap the first pass of a binding. It
works by parsing the header files of a native library to map the public API into the binding
definition (a process that can also be done manually).

iOS

The iOS binding page links back to these common binding resources, in addition to the
examples below.

Walkthrough: Binding an Objective-C Library

This article provides a step-by-step walkthrough of creating a binding project using the open
source InfColorPicker Objective-C project as an example. The InfColorPicker library provides
a reusable view controller that allow the user to select a color based on its HSB
representation, making color selection more user-friendly. Objective Sharpie will be used to
assist in the binding process.

Binding Samples

A collection of third-party bindings that can be used a reference when creating new Binding
Projects.

Mac

Historically Mac binding has been a very manual process. There is currently a downloadable
preview of Mac Binding Project support for a future release of Visual Studio for Mac.
Overview
Binding an Objective-C library for use with Xamarin takes of three steps:

1. Write a C# "API definition" to describe how the native API is exposed in .NET, and how
it maps to the underlying Objective-C. This is done using standard C# constructs like
interface and various binding attributes (see this simple example).

2. Once you have written the "API definition" in C#, you compile it to produce a "binding"
assembly. This can be done on the command line or using a binding project in
Visual Studio for Mac or Visual Studio.

3. That "binding" assembly is then added to your Xamarin application project, so you can
access the native functionality using the API you defined. The binding project is
completely separate from your application projects.

NOTE: Step 1 can be automated with the assistance of Objective Sharpie. It examines the
Objective-C API and generates a proposed C# "API definition." You can customize the files
created by Objective Sharpie and use them in a binding project (or on the command line) to
create your binding assembly. Objective Sharpie does not create bindings by itself, it's
merely an optional part of the larger process.

You can also read more technical details of how it works, which will help you to write your
bindings.

Command Line Bindings

You can use the btouch-native for Xamarin.iOS (or bmac-native if you are using
Xamarin.Mac) to build bindings directly. It works by passing the C# API definitions that
you've created by hand (or using Objective Sharpie) to the command line tool (btouch-
native for iOS or bmac-native for Mac).

The general syntax for invoking these tools is:


# Use this for Xamarin.iOS:
bash$ /Developer/MonoTouch/usr/bin/btouch-native -e cocos2d.cs -
s:enums.cs -x:extensions.cs

# Use this for Xamarin.Mac:


bash$ bmac-native -e cocos2d.cs -s:enums.cs -x:extensions.cs

The above command will generate the file cocos2d.dll in the current directory, and it will
contain the fully bound library that you can use in your project. This is the tool that Visual
Studio for Mac uses to create your bindings if you use a binding project (described below).

Binding Project

A binding project can be created in Visual Studio for Mac or Visual Studio (Visual Studio only
supports iOS bindings) and makes it easier to edit and build API definitions for binding
(versus using the command line).

Follow this getting started guide to see how to create and use a binding project to produce a
binding.

Objective Sharpie

Objective Sharpie is another, separate command line tool that helps with the initial stages of
creating a binding. It does not create a binding by itself, rather it automates the initial step of
generating an API definition for the target native library.

Read the Objective Sharpie docs to learn how to parse native libraries, native frameworks,
and CocoaPods into API defintions that can be built into bindings.

How Binding Works


It is possible to use the [Register] attribute, [Export] attribute, and manual Objective-C
selector invocation together to manually bind new (previously unbound) Objective-C types.
First, find a type that you wish to bind. For discussion purposes (and simplicity), we'll bind
the NSEnumerator type (which has already been bound in Foundation.NSEnumerator; the
implementation below is just for example purposes).

Second, we need to create the C# type. We'll likely want to place this into a namespace;
since Objective-C doesn't support namespaces, we'll need to use the [Register] attribute
to change the type name that Xamarin.iOS will register with the Objective-C runtime. The C#
type must also inherit from Foundation.NSObject:

namespace Example.Binding {
[Register("NSEnumerator")]
class NSEnumerator : NSObject
{
// see steps 3-5
}
}

Third, review the Objective-C documentation and create ObjCRuntime.Selector instances for
each selector you wish to use. Place these within the class body:

static Selector selInit = new Selector("init");


static Selector selAllObjects = new Selector("allObjects");
static Selector selNextObject = new Selector("nextObject");

Fourth, your type will need to provide constructors. You must chain your constructor
invocation to the base class constructor. The [Export] attributes permit Objective-C code
to call the constructors with the specified selector name:

[Export("init")]
public NSEnumerator()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(this.Handle,
selInit.Handle);
}
// This constructor must be present so that Xamarin.iOS
// can create instances of your type from Objective-C code.
public NSEnumerator(IntPtr handle)
: base(handle)
{
}

Fifth, provide methods for each of the Selectors declared in Step 3. These will use
objc_msgSend() to invoke the selector on the native object. Note the use of
Runtime.GetNSObject() to convert an IntPtr into an appropriately typed NSObject (sub-
)type. If you want the method to be callable from Objective-C code, the member must be
virtual.

[Export("nextObject")]
public virtual NSObject NextObject()
{
return Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle,
selNextObject.Handle));
}

// Note that for properties, [Export] goes on the get/set method:


public virtual NSArray AllObjects {
[Export("allObjects")]
get {
return (NSArray) Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle,
selAllObjects.Handle));
}
}

Putting it all together:

using System;
using Foundation;
using ObjCRuntime;

namespace Example.Binding {
[Register("NSEnumerator")]
class NSEnumerator : NSObject
{
static Selector selInit = new Selector("init");
static Selector selAllObjects = new Selector("allObjects");
static Selector selNextObject = new Selector("nextObject");

[Export("init")]
public NSEnumerator()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(this.Handle,
selInit.Handle);
}

public NSEnumerator(IntPtr handle)


: base(handle)
{
}

[Export("nextObject")]
public virtual NSObject NextObject()
{
return Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle,
selNextObject.Handle));
}
// Note that for properties, [Export] goes on the get/set
method:
public virtual NSArray AllObjects {
[Export("allObjects")]
get {
return (NSArray) Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle,
selAllObjects.Handle));
}
}
}
}
Binding Objective-C Libraries
When working with Xamarin.iOS or Xamarin.Mac, you might encounter cases where you want to consume
a third-party Objective-C library. In those situations, you can use Xamarin Binding Projects to create a C#
binding to the native Objective-C libraries. The project uses the same tools that we use to bring the iOS
and Mac APIs to C#.

This document describes how to bind Objective-C APIs, if you are binding just C APIs, you should use the
standard .NET mechanism for this, the P/Invoke framework. Details on how to statically link a C library are
available on the Linking Native Libraries page.

See our companion Binding Types Reference Guide. Additionally, if you want to learn more about what
happens under the hood, check our Binding Overview page.

Bindings can be built for both iOS and Mac libraries. This page describes how to work on an iOS binding,
however Mac bindings are very similar.

Sample Code for iOS

You can use the iOS Binding Sample project to experiment with bindings.

Getting Started
[[ide name="xs"]]

The easiest way to create a binding is to create a Xamarin.iOS Binding Project. You can do this from Visual
Studio for Mac by selecting the project type, iOS > Library > Bindings Library:
[[/ide]]

[[ide name="vs"]]

The easiest way to create a binding is to create a Xamarin.iOS Binding Project. You can do this from Visual
Studio on Windows by selecting the project type, Visual C# > iOS > Bindings Library (iOS):

⚠️ Note: Binding Projects for Xamarin.Mac are only supported in Visual Studio for Mac.

[[/ide]]

The generated project contains a small template that you can edit, it contains two files:
ApiDefinition.cs and StructsAndEnums.cs.

The ApiDefinition.cs is where you will define the API contract, this is the file that describes how the
underlying Objective-C API is projected into C#. The syntax and contents of this file are the main topic of
discussion of this document and the contents of it are limited to C# interfaces and C# delegate
declarations. The StructsAndEnums.cs file is the file where you will enter any definitions that are
required by the interfaces and delegates. This includes enumeration values and structures that your code
might use.

Binding an API
To do a comprehensive binding, you will want to understand the Objective-C API definition and familiarize
yourself with the .NET Framework Design guidelines.
To bind your library you will typically start with an API definition file. An API definition file is merely a C#
source file that contains C# interfaces that have been annotated with a handful of attributes that help drive
the binding. This file is what defines what the contract between C# and Objective-C is.

For example, this is a trivial api file for a library:

using Foundation;

namespace Cocos2D {
[BaseType (typeof (NSObject))]
interface Camera {
[Static, Export ("getZEye")]
nfloat ZEye { get; }

[Export ("restore")]
void Restore ();

[Export ("locate")]
void Locate ();

[Export ("setEyeX:eyeY:eyeZ:")]
void SetEyeXYZ (nfloat x, nfloat y, nfloat z);

[Export ("setMode:")]
void SetMode (CameraMode mode);
}
}

The above sample defines a class called Cocos2D.Camera that derives from the NSObject base type
(this type comes from Foundation.NSObject) and which defines a static property (ZEye), two methods
that take no arguments and a method that takes three arguments.

An in-depth discussion of the format of the API file and the attributes that you can use is covered in the API
definition file section below.

To produce a complete binding, you will typically deal with four components:

The API definition file (ApiDefinition.cs in the template).


Optional: any enums, types, structs required by the API definition file (StructsAndEnums.cs in the
template).
Optional: extra sources that might expand the generated binding, or provide a more C# friendly API
(any C# files that you add to the project).
The native library that you are binding.

This chart shows the relationship between the files:

The API Definition file: will only contain namespaces and interface definitions (with any members that an
interface can contain) and should not contain classes, enumerations, delegates or structs. The API
definition file is merely the contract that will be used to generate the API.

Any extra code that you need like enumerations or supporting classes should be hosted on a separate file,
in the example above the "CameraMode" is an enumeration value that does not exist in the CS file and
should be hosted in a separate file, for example StructsAndEnums.cs:

public enum CameraMode {


FlyOver, Back, Follow
}

The APIDefinition.cs file is combined with the StructsAndEnum class and are used to generate the
core binding of the library. You can use the resulting library as-is, but typically, you will want to tune the
resulting library to add some C# features for the benefit of your users. Some examples include
implementing a ToString() method, provide C# indexers, add implicit conversions to and from some
native types or provide strongly-typed versions of some methods. These improvements are stored in extra
C# files. Merely add the C# files to your project and they will be included in this build process.

This shows how you would implement the code in your Extra.cs file. Notice that you will be using partial
classes as these augment the partial classes that are generated from the combination of the
ApiDefinition.cs and the StructsAndEnums.cs core binding:

public partial class Camera {


// Provide a ToString method
public override string ToString ()
{
return String.Format ("ZEye: {0}", ZEye);
}
}

Building the library will produce your native binding.

To complete this binding, you should add the native library to the project. You can do this by adding the
native library to your project, either by dragging and dropping the native library from Finder onto the project
in the solution explorer, or by right-clicking the project and choosing Add > Add Files to select the native
library. Native libraries by convention start with the word "lib" and end with the extension ".a". When you do
this, Visual Studio for Mac will add two files: the .a file and an automatically populated C# file that contains
information about what the native library contains:

The contents of the libMagicChord.linkwith.cs file has information about how this library can be
used and instructs your IDE to package this binary into the resulting DLL file:

using System;
using ObjCRuntime;

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

Full details about how to use the LinkWith attribute are documented in our Binding Types Reference Guide.
Now when you build the project you will end up with a MagicChords.dll file that contains both the
binding and the native library. You can distribute this project or the resulting DLL to other developers for
their own use.

Sometimes you might find that you need a few enumeration values, delegate definitions or other types. Do
not place those in the API definitions file, as this is merely a contract

The API definition file


The API definition file consists of a number of interfaces. The interfaces in the API definition will be turned
into a class declaration and they must be decorated with the [BaseType] attribute to specify the base class
for the class.

You might be wondering why we did not use classes instead of interfaces for the contract definition. We
picked interfaces because it allowed us to write the contract for a method without having to supply a
method body in the API definition file, or having to supply a body that had to throw an exception or return a
meaningful value.

But since we are using the interface as a skeleton to generate a class we had to resort to decorating
various parts of the contract with attributes to drive the binding.

Binding Methods

The simplest binding you can do is to bind a method. Just declare a method in the interface with the C#
naming conventions and decorate the method with the [Export] attribute. The [Export] attribute is what links
your C# name with the Objective-C name in the Xamarin.iOS runtime. The parameter of the Export
attribute is the name of the Objective-C selector, some examples:

// A method, that takes no arguments


[Export ("refresh")]
void Refresh ();

// A method that takes two arguments and return the result


[Export ("add:and:")]
nint Add (nint a, nint b);

// A method that takes a string


[Export ("draw:atColumn:andRow:")]
void Draw (string text, nint column, nint row);

The above samples show how you can bind instance methods. To bind static methods, you must use the
[Static] attribute, like this:

// A static method, that takes no arguments


[Static, Export ("refresh")]
void Beep ();

This is required because the contract is part of an interface, and interfaces have no notion of static vs
instance declarations, so it is necessary once again to resort to attributes. If you want to hide a particular
method from the binding, you can decorate the method with the [Internal] attribute.

The btouch-native command will introduce checks for reference parameters to not be null. If you want
to allow null values for a particular parameter, use the [NullAllowed] attribute on the parameter, like this:

[Export ("setText:")]
string SetText ([NullAllowed] string text);

When exporting a reference type, with the [Export] keyword you can also specify the allocation
semantics. This is necessary to ensure that no data is leaked.

Binding Properties

Just like methods, Objective-C properties are bound using the [Export] attribute and map directly to C#
properties. Just like methods, properties can be decorated with the [Static] and the [Internal] attributes.

When you use the [Export] attribute on a property under the covers btouch-native actually binds two
methods: the getter and the setter. The name that you provide to export is the basename and the the
setter is computed by prepending the word "set", turning the first letter of the basename into upper case
and making the selector take an argument. This means that [Export ("label")] applied on a property
actually binds the "label" and "setLabel:" Objective-C methods.

Sometimes the Objective-C properties do not follow the pattern described above and the name is manually
overwritten. In those cases you can control the way that the binding is generated by using the [Bind]
attribute on the getter or setter, for example:

[Export ("menuVisible")]
bool MenuVisible { [Bind ("isMenuVisible")] get; set; }

This then binds "isMenuVisible" and "setMenuVisible:". Optionally, a property can be bound using the
following syntax:

[Category, BaseType(typeof(UIView))]
interface UIView_MyIn
{
[Export ("name")]
string Name();

[Export("setName:")]
void SetName(string name);
}

Where the getter and setter are explicitly defined as in the name and setName bindings above.

In addition to support for static properties using [Static], you can decorate thread-static properties with
[IsThreadStatic], for example:

[Export ("currentRunLoop")][Static][IsThreadStatic]
NSRunLoop Current { get; }

Just like methods allow some parameters to be flagged with [NullAllowed], you can apply [NullAllowed] to a
property to indicate that null is a valid value for the property, for example:

[Export ("text"), NullAllowed]


string Text { get; set; }

The [NullAllowed] parameter can also be specified directly on the setter:

[Export ("text")]
string Text { get; [NullAllowed] set; }

Caveats of Binding Custom Controls

The following caveats should be considered when setting up the binding for a custom control:

1. Binding properties must be static - When defining the binding of properties, the Static attribute
must be used.
2. Property names must match exactly - The name used to bind the property must match the name
of the property in the custom control exactly.
3. Property types must match exactly - The variable type used to bind the property must match the
type of the property in the custom control exactly.
4. Breakpoints and the getter/setter - Breakpoints placed in the getter or setter methods of the
property will never be hit.
5. Observe Callbacks - You will need to use observation callbacks to be notified of changes in the
property values of custom controls.

Failure to observe any of the above listed caveats can result in the binding silently failing at runtime.

Objective-C Mutable Pattern and Properties

Objective-C frameworks use an idiom where some classes are immutable with a mutable subclass. For
example NSString is the immutable version, while NSMutableString is the subclass that allows
mutation.

In those classes it is common to see the immutable base class contain properties with a getter, but no
setter. And for the mutable version to introduce the setter. Since this is not really possible with C#, we had
to map this idiom into an idiom that would work with C#.

The way that this is mapped to C# is by adding both the getter and the setter on the base class, but
flagging the setter with a [NotImplemented] attribute.

Then, on the mutable subclass, you use the [Override] attribute on the property to ensure that the
property is actually overriding the parent's behavior.

Example:

[BaseType (typeof (NSObject))]


interface MyTree {
string Name { get; [NotImplemented] set; }
}

[BaseType (typeof (MyTree))]


interface MyMutableTree {
[Override]
string Name { get; set; }
}

Binding Constructors

The btouch-native tool will automatically generate fours constructors in your class, for a given class Foo, it
generates:
Foo (): the default constructor (maps to Objective-C's "init" constructor)
Foo (NSCoder): the constructor used during deserialization of NIB files (maps to Objective-C's
"initWithCoder:" constructor).
Foo (IntPtr handle): the constructor for handle-based creation, this is invoked by the runtime
when the runtime needs to expose a managed object from an unmanaged object.
Foo (NSEmptyFlag): this is used by derived classes to prevent double initialization.

For constructors that you define, they need to be declared using the following signature inside the Interface
definition: they must return an IntPtr value and the name of the method should be Constructor. For
example to bind the initWithFrame: constructor, this is what you would use:

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

Binding Protocols

As described in the API design document, in the section discussing Models and Protocols, Xamarin.iOS
maps the Objective-C protocols into classes that have been flagged with the [Model] attribute. This is
typically used when implementing Objective-C delegate classes.

The big difference between a regular bound class and a delegate class is that the delegate class might
have one or more optional methods.

For example consider the UIKit class UIAccelerometerDelegate, this is how it is bound in
Xamarin.iOS:

[BaseType (typeof (NSObject))]


[Model][Protocol]
interface UIAccelerometerDelegate {
[Export ("accelerometer:didAccelerate:")]
void DidAccelerate (UIAccelerometer accelerometer, UIAcceleration
acceleration);
}

Since this is an optional method on the definition for UIAccelerometerDelegate there is nothing else to
do. But if there was a required method on the protocol, you should add the [Abstract] attribute to the
method. This will force the user of the implementation to actually provide a body for the method.

In general, protocols are used in classes that respond to messages. This is typically done in Objective-C by
assigning to the "delegate" property an instance of an object that responds to the methods in the protocol.
The convention in Xamarin.iOS is to support both the Objective-C loosely coupled style where any instance
of an NSObject can be assigned to the delegate, and to also expose a strongly typed version of it. For this
reason, we typically provide both a "Delegate" property that is strongly typed and a "WeakDelegate" that is
loosely typed. We usually bind the loosely typed version with Export, and we use the [Wrap] attribute to
provide the strongly typed version.

This shows how we bound the UIAccelerometer class:

[BaseType (typeof (NSObject))]


interface UIAccelerometer {
[Static] [Export ("sharedAccelerometer")]
UIAccelerometer SharedAccelerometer { get; }

[Export ("updateInterval")]
double UpdateInterval { get; set; }

[Wrap ("WeakDelegate")]
UIAccelerometerDelegate Delegate { get; set; }

[Export ("delegate", ArgumentSemantic.Assign)][NullAllowed]


NSObject WeakDelegate { get; set; }
}

New in MonoTouch 7.0

Starting with MonoTouch 7.0 a new and improved protocol binding functionality has been incorporated.
This new support makes it simpler to use Objective-C idioms for adopting one or more protocols in a given
class.

For every protocol definition MyProtocol in Objective-C, there is now an IMyProtocol interface that lists
all the required methods from the protocol, as well as an extension class that provides all the optional
methods. The above, combined with new support in the Xamarin Studio editor allows developers to
implement protocol methods without having to use the separate subclasses of the previous abstract model
classes.

Any definition that contains the [Protocol] attribute will actually generate three supporting classes that
vastly improve the way that you consume protocols:

// Full method implementation, contains all methods


class MyProtocol : IMyProtocol {
public void Say (string msg);
public void Listen (string msg);
}

// Interface that contains only the required methods


interface IMyProtocol: INativeObject, IDisposable {
[Export ("say:")]
void Say (string msg);
}

// Extension methods
static class IMyProtocol_Extensions {
public static void Optional (this IMyProtocol this, string msg);
}
}

The class implementation provides a complete abstract class that you can override individual methods of
and get full type safety. But due to C# not supporting multiple inheritance, there are scenarios where you
might needs to have a different base class, but you still want to implement an interface, that is where the

The generated interface definition comes in. It is an interface that has all the required methods from the
protocol. This allows developers that want to implement your protocol to merely implement the interface.
The runtime will automatically register the type as adopting the protocol.

Notice that the interface only lists the required methods and does expose the optional methods. This
means that classes that adopt the protocol will get full type checking for the required methods, but will have
to resort to weak typing (manually using Export attributes and matching the signature) for the optional
protocol methods.

To make it convenient to consume an API that uses protocols, the binding tool also will produce an
extensions method class that exposes all of the optional methods. This means that as long as you are
consuming an API, you will be able to treat protocols as having all the methods.

If you want to use the protocol definitions in your API, you will need to write skeleton empty interfaces in
your API definition. If you want to use the MyProtocol in an API, you would need to do this:

[BaseType (typeof (NSObject))]


[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);

[Export ("listen")]
void Listen ();
}

interface IMyProtocol {}

[BaseType (typeof(NSObject))]
interface MyTool {
[Export ("getProtocol")]
IMyProtocol GetProtocol ();
}

The above is needed because at binding time the IMyProtocol would not exist, that is why you need to
provide an empty interface.

Adopting Protocol Generated Interfaces

Whenever you implement one of the interfaces generated for the protocols, like this:

class MyDelegate : NSObject, IUITableViewDelegate {


nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}

The implementation for the interface methods automatically gets exported with the proper name, so it is
equivalent to this:

class MyDelegate : NSObject, IUITableViewDelegate {


[Export ("getRowHeight:")]
nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}

It does not matter if the interface is implemented implicitly or explicitly.

Binding Class Extensions

In Objective-C it is possible to extend classes with new methods, similar in spirit to C#'s extension
methods. When one of these methods is present, you can use the BaseType attribute to flag the method
as being the receiver of the Objective-C message.

For example, in Xamarin.iOS we bound the extension methods that are defined on NSString when UIKit
is imported as methods in the NSStringDrawingExtensions, like this:

[Category, BaseType (typeof (NSString))]


interface NSStringDrawingExtensions {
[Export ("drawAtPoint:withFont:")]
CGSize DrawString (CGPoint point, UIFont font);
}

Binding Objective-C Argument Lists

Objective-C supports variadic arguments, you can use the following technique described by Zach Gris on
this post.

An Objective-C message looks like this:

- (void) appendWorkers:(XWorker *) firstWorker, ...


NS_REQUIRES_NIL_TERMINATION ;

To invoke this method from C# you will want to create a signature like this:

[Export ("appendWorkers"), Internal]


void AppendWorkers (Worker firstWorker, IntPtr workersPtr)

This declares the method as internal, hiding the above API from users, but exposing it to the library. Then
you can write a method like this:

public void AppendWorkers(params Worker[] workers)


{
if (workers == null)
throw new ArgumentNullException ("workers");
var pNativeArr = Marshal.AllocHGlobal(workers.Length * IntPtr.Size);
for (int i = 1; i < workers.Length; ++i)
Marshal.WriteIntPtr (pNativeArr, (i - 1) * IntPtr.Size,
workers[i].Handle);

// Null termination
Marshal.WriteIntPtr (pNativeArr, (workers.Length - 1) * IntPtr.Size,
IntPtr.Zero);

// the signature for this method has gone from (IntPtr, IntPtr) to (Worker,
IntPtr)
WorkerManager.AppendWorkers(workers[0], pNativeArr);
Marshal.FreeHGlobal(pNativeArr);
}

Binding Fields

Sometimes you will want to access public fields that were declared in a library.

Usually these fields contain strings or integers values that must be referenced. They are commonly used as
string that represent a specific notification and as keys in dictionaries.

To bind a field, add a property to your interface definition file, and decorate the property with the [Field]
attribute. This attribute takes one parameter: the C name of the symbol to lookup. For example:

[Field ("NSSomeEventNotification")]
NSString NSSomeEventNotification { get; }

If you want to wrap various fields in a static class that does not derive from NSObject, you can use the
[Static] attribute on the class, like this:

[Static]
interface LonelyClass {
[Field ("NSSomeEventNotification")]
NSString NSSomeEventNotification { get; }
}

The above will generate a LonelyClass which does not derive from NSObject and will contain a binding
to the NSSomeEventNotification NSString exposed as an NSString.
The [Field] attribute can be applied to the following data types:

NSString references (read-only properties only)


NSArray references (read-only properties only)
32-bit ints (System.Int32)
64-bit ints (System.Int64)
32-bit floats (System.Single)
64-bit floats (System.Double)
System.Drawing.SizeF
CGSize

In addition to the native field name, you can specify the library name where the field is located, by passing
the library name:

[Static]
interface LonelyClass {
[Field ("SomeSharedLibrarySymbol", "SomeSharedLibrary")]
NSString SomeSharedLibrarySymbol { get; }
}

If you are linking statically, there is no library to bind to, so you need to use the __Internal name:

[Static]
interface LonelyClass {
[Field ("MyFieldFromALibrary", "__Internal")]
NSString MyFieldFromALibrary { get; }
}

Binding Enums

You can add enum directly in your binding files to makes it easier to use them inside API definitions -
without using a different source file (that needs to be compiled in both the bindings and the final project).

Example:

[Native] // needed for enums defined as NSInteger in ObjC


enum MyEnum {}

interface MyType {
[Export ("initWithEnum:")]
IntPtr Constructor (MyEnum value);
}

It is also possible to create your own enums to replace NSString constants. In this case the generator will
automatically create the methods to convert enums values and NSString constants for you.

Example:

enum NSRunLoopMode {

[DefaultEnumValue]
[Field ("NSDefaultRunLoopMode")]
Default,

[Field ("NSRunLoopCommonModes")]
Common,

[Field (null)]
Other = 1000
}

interface MyType {
[Export ("performForMode:")]
void Perform (NSString mode);

[Wrap ("Perform (mode.GetConstant ())")]


void Perform (NSRunLoopMode mode);
}

In the above example you could decide to decorate void Perform (NSString mode); with an
[Internal] attribute. This will hide the constant-based API from your binding consumers.

However this would limit subclassing the type as the nicer API alternative uses a [Wrap] attribute. Those
generated methods are not virtual, i.e. you won't be able to override them - which may, or not, be a
good choice.

An alternative is to mark the original, NSString-based, definition as [Protected]. This will allow
subclassing to work, when required, and the wrap'ed version will still work and call the overriden method.
Binding NSValue NSNumber and NSString to a better type

The [BindAs] attribute allows binding NSNumber, NSValue and NSString(enums) into more accurate C#
types. The attribute can be used to create better, more accurate, .NET API over the native API.

You can decorate methods (on return value), parameters and properties with [BindAs]. The only restriction
is that your member must not be inside a [Protocol] or [Model] interface.

For example:

[return: BindAs (typeof (bool?))]


[Export ("shouldDrawAt:")]
NSNumber ShouldDraw ([BindAs (typeof (CGRect))] NSValue rect);

Would output:

[Export ("shouldDrawAt:")]
bool? ShouldDraw (CGRect rect) { ... }

Internally we will do the bool? <-> NSNumber and CGRect <-> NSValue conversions.

[BindAs] also supports arrays of NSNumber NSValue and NSString(enums).

For example:

[BindAs (typeof (CAScroll []))]


[Export ("supportedScrollModes")]
NSString [] SupportedScrollModes { get; set; }

Would output:

[Export ("supportedScrollModes")]
CAScroll [] SupportedScrollModes { get; set; }

CAScroll is a NSString backed enum, we will fetch the right NSString value and handle the type
conversion.

Please see [BindAs] documentation to see supported conversion types.

Binding Notifications

Notifications are messages that are posted to the NSNotificationCenter.DefaultCenter and are
used as a mechanism to broadcast messages from one part of the application to another. Developers
subscribe to notifications typically using the NSNotificationCenter's AddObserver method. When an
application posts a message to the notification center, it typically contains a payload stored in the
NSNotification.UserInfo dictionary. This dictionary is weakly typed, and getting information out of it is error
prone, as users typically need to read in the documentation which keys are available on the dictionary and
the types of the values that can be stored in the dictionary. The presence of keys sometimes is used as a
boolean as well.

The Xamarin.iOS binding generator provides support for developers to bind notifications. To do this, you
set the [Notification] attribute on a property that has been also been tagged with a [Field] property (it can be
public or private).

This attribute can be used without arguments for notifications that carry no payload, or you can specify a
System.Type that references another interface in the API definition, typically with the name ending with
"EventArgs". The generator will turn the interface into a class that subclasses EventArgs and will include
all of the properties listed there. The [Export] attribute should be used in the EventArgs class to list the
name of the key used to look up the Objective-C dictionary to fetch the value.

For example:

interface MyClass {
[Notification]
[Field ("MyClassDidStartNotification")]
NSString DidStartNotification { get; }
}

The above code will generate a nested class MyClass.Notifications with the following methods:

public class MyClass {


[..]
public Notifications {
public static NSObject ObserveDidStart
(EventHandler<NSNotificationEventArgs> handler)
}
}

Users of your code can then easily subscribe to notifications posted to the NSDefaultCenter by using code
like this:

var token = MyClass.Notifications.ObserverDidStart ((notification) => {


Console.WriteLine ("Observed the 'DidStart' event!");
});

The returned value from ObserveDidStart can be used to easily stop receiving notifications, like this:

token.Dispose ();

Or you can call NSNotification.DefaultCenter.RemoveObserver and pass the token. If your notification
contains parameters, you should specify a helper EventArgs interface, like this:

interface MyClass {
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}

// The helper EventArgs declaration


interface MyScreenChangedEventArgs {
[Export ("ScreenXKey")]
nint ScreenX { get; set; }

[Export ("ScreenYKey")]
nint ScreenY { get; set; }

[Export ("DidGoOffKey")]
[ProbePresence]
bool DidGoOff { get; }
}

The above will generate a MyScreenChangedEventArgs class with the ScreenX and ScreenY
properties that will fetch the data from the NSNotification.UserInfo dictionary using the keys "ScreenXKey"
and "ScreenYKey" respectively and apply the proper conversions. The [ProbePresence] attribute is
used for the generator to probe if the key is set in the UserInfo, instead of trying to extract the value. This
is used for cases where the presence of the key is the value (typically for boolean values).

This allows you to write code like this:

var token = MyClass.NotificationsObserveScreenChanged ((notification) => {


Console.WriteLine ("The new screen dimensions are {0},{1}",
notification.ScreenX, notification.ScreenY);
});

Binding Categories

Categories are an Objective-C mechanism used to extend the set of methods and properties available in a
class. In practice, they are used to either extend the functionality of a base class (for example NSObject)
when a specific framework is linked in (for example UIKit), making their methods available, but only if the
new framework is linked in. In some other cases, they are used to organize features in a class by
functionality. They are similar in spirit to C# extension methods.This is what a category would look like in
Objective-C:

@interface UIView (MyUIViewExtension)


-(void) makeBackgroundRed;
@end

The above example if found on a library would extend instances of UIView with the method
makeBackgroundRed.

To bind those, you can use the [Category] attribute on an interface definition. When using the Category
attribute, the meaning of the [BaseType] attribute changes from being used to specify the base class to
extend, to be the type to extend.

The following shows how the UIView extensions are bound and turned into C# extension methods:

[BaseType (typeof (UIView))]


[Category]
interface MyUIViewExtension {
[Export ("makeBackgroundRed")]
void MakeBackgroundRed ();
}

The above will create a MyUIViewExtension a class that contains the MakeBackgroundRed extension
method. This means that you can now call "MakeBackgroundRed" on any UIView subclass, giving you the
same functionality you would get on Objective-C. In some other cases, categories are used not to extend a
system class, but to organize functionality, purely for decoration purposes. Like this:

@interface SocialNetworking (Twitter)


- (void) postToTwitter:(Message *) message;
@end
@interface SocialNetworking (Facebook)
- (void) postToFacebook:(Message *) message andPicture: (UIImage*)
picture;
@end

Although you can use the Category attribute also for this decoration style of declarations, you might as
well just add them all to the class definition. Both of these would achieve the same:

[BaseType (typeof (NSObject))]


interface SocialNetworking {
}

[Category]
[BaseType (typeof (SocialNetworking))]
interface Twitter {
[Export ("postToTwitter:")]
void PostToTwitter (Message message);
}

[Category]
[BaseType (typeof (SocialNetworking))]
interface Facebook {
[Export ("postToFacebook:andPicture:")]
void PostToFacebook (Message message, UIImage picture);
}

It is just shorter in these cases to merge the categories:

[BaseType (typeof (NSObject))]


interface SocialNetworking {
[Export ("postToTwitter:")]
void PostToTwitter (Message message);

[Export ("postToFacebook:andPicture:")]
void PostToFacebook (Message message, UIImage picture);
}

Binding Blocks
Blocks are a new construct introduced by Apple to bring the functional equivalent of C# anonymous
methods to Objective-C. For example, the NSSet class now exposes this method:

- (void) enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop) block

The above description declares a method called "enumerateObjectsUsingBlock:" that takes one argument
named block. This block is similar to a C# anonymous method in that it has support for capturing the
current environment (the "this" pointer, access to local variables and parameters). The above method in
NSSet invokes the block with two parameters an NSObject (the "id obj" part) and a pointer to a boolean
(the "BOOL *stop") part.

To bind this kind of API with btouch, you need to first declare the block type signature as a C# delegate and
then reference it from an API entry point, like this:

// This declares the callback signature for the block:


delegate void NSSetEnumerator (NSObject obj, ref bool stop)

// Later, inside your definition, do this:


[Export ("enumerateObjectUsingBlock:")]
void Enumerate (NSSetEnumerator enum)

And now your code can call your function from C#:

var myset = new NSMutableSet ();


myset.Add (new NSString ("Foo"));

s.Enumerate (delegate (NSObject obj, ref bool stop){


Console.WriteLine ("The first object is: {0} and stop is: {1}", obj, stop);
});

You can also use lambdas if you prefer:

var myset = new NSMutableSet ();


mySet.Add (new NSString ("Foo"));

s.Enumerate ((obj, stop) => {


Console.WriteLine ("The first object is: {0} and stop is: {1}", obj, stop);
});

Asynchronous Methods
The binding generator can turn a certain class of methods into async-friendly methods (methods that return
a Task or Task<T>).

You can use the [Async] attribute on methods that return void and whose last argument is a callback.
When you apply this to a method, the binding generator will generate a version of that method with the
suffix Async. If the callback takes no parameters, the return value will be a Task, if the callback takes a
parameter, the result will be a Task<T>. If the callback takes multiple parameters, you should set the
ResultType or ResultTypeName to specify the desired name of the generated type which will hold all
the properties.

Example:

[Export ("loadfile:completed:")]
[Async]
void LoadFile (string file, Action<string> completed);

The above code will generate both the LoadFile method, as well as:

[Export ("loadfile:completed:")]
Task<string> LoadFileAsync (string file);

Surfacing Strong Types for weak NSDictionary parameters

In many places in the Objective-C API, parameters are passed as weakly typed NSDictionary APIs with
specific keys and values, but these are error prone (you can pass invalid keys, and get no warnings; you
can pass invalid values, and get no warnings) and frustrating to use as they require multiple trips to the
documentation to lookup the possible key names and values.

The solution is to provide a strongly typed version that provides the strongly typed version of the API and
behind the scenes maps the various underlying keys and values.

So for example, if the Objective-C API accepted an NSDictionary and it is documented as taking the key
"XyzVolumeKey" which takes an NSNumber with a volume value from 0.0 to 1.0 and a "XyzCaptionKey"
that takes a string, you would want your users to have a nice API that looks like this:

public class XyzOptions {


public nfloat? Volume { get; set; }
public string Caption { get; set; }
}

The Volume property is defined as nullable float, as the convention in Objective-C does not require these
dictionaries to have the value, so there are scenarios where the value might not be set.

To do this, you need to do a few things:

Create a strongly typed class, that subclasses DictionaryContainer and provides the various getters
and setters for each property.
Declare overloads for the methods taking NSDictionary to take the new strongly typed version.

You can create the strongly typed class either manually, or use the generator to do the work for you. We
first explore how to do this manually so you understand what is going on, and then the automatic approach.

You need to create a supporting file for this, it does not go into your contract API. This is what you would
have to write to create your XyzOptions class:

public class XyzOptions : DictionaryContainer {


#if !COREBUILD
public XyzOptions () : base (new NSMutableDictionary ()) {}
public XyzOptions (NSDictionary dictionary) : base (dictionary){}

public nfloat? Volume {


get { return GetFloatValue (XyzOptionsKeys.VolumeKey); }
set { SetNumberValue (XyzOptionsKeys.VolumeKey, value); }
}
public string Caption {
get { return GetStringValue (XyzOptionsKeys.CaptionKey); }
set { SetStringValue (XyzOptionsKeys.CaptionKey, value); }
}
#endif
}

You then should provide a wrapper method that surfaces the high-level API, on top of the low-level API.

[BaseType (typeof (NSObject))]


interface XyzPanel {
[Export ("playback:withOptions:")]
void Playback (string fileName, [NullAllowed] NSDictionary options);

[Wrap ("Playback (fileName, options == null ? null : options.Dictionary")]


void Playback (string fileName, XyzOptions options);
}
If your API does not need to be overwritten, you can safely hide the NSDictionary-based API by using the
Internal attribute.

As you can see, we use the [Wrap] attribute to surface a new API entry point, and we surface it using our
strongly typed XyzOptions class. The wrapper method also allows for null to be passed.

Now, one thing that we did not mention is where the XyzOptionsKeys values came from. You would
typically group the keys that an API surfaces in a static class like XyzOptionsKeys, like this:

[Static]
class XyzOptionKeys {
[Field ("kXyzVolumeKey")]
NSString VolumeKey { get; }

[Field ("kXyzCaptionKey")]
NSString CaptionKey { get; }
}

Let us look at the automatic support for creating these strongly typed dictionaries. This avoids plenty of the
boilerplate, and you can define the dictionary directly in your API contract, instead of using an external file.

To create a strongly typed dictionary, introduce an interface in your API and decorate it with the
StrongDictionary attribute. This tells the generator that it should create a class with the same name as your
interface that will derive from DictionaryContainer and will provide strong typed accessors for it.

The StrongDictionary attribute takes one parameter, which is the name of the static class that contains
your dictionary keys. Then each property of the interface will become a strongly typed accessor. By default,
the code will use the name of the property with the suffix "Key" in the static class to create the accessor.

This means that creating your strongly typed accessor no longer requires an external file, nor having to
manually create getters and setters for every property, nor having to lookup the keys manually yourself.

This is what your entire binding would look like:

[Static]
class XyzOptionKeys {
[Field ("kXyzVolumeKey")]
NSString VolumeKey { get; }

[Field ("kXyzCaptionKey")]
NSString CaptionKey { get; }
}
[StrongDictionary ("XyzOptionKeys")]
interface XyzOptions {
nfloat Volume { get; set; }
string Caption { get; set; }
}

[BaseType (typeof (NSObject))]


interface XyzPanel {
[Export ("playback:withOptions:")]
void Playback (string fileName, [NullAllowed] NSDictionary options);

[Wrap ("Playback (fileName, options == null ? null : options.Dictionary")]


void Playback (string fileName, XyzOptions options);
}

In case you need to reference in your XyzOption members a different field (that is not the name of the
property with the suffix Key), you can decorate the property with an Export attribute with the name that
you want to use.

Type mappings
This section covers how Objective-C types are mapped to C# types.

Simple Types

The following table shows how you should map types from the Objective-C and CocoaTouch world to the
Xamarin.iOS world:

Type mappings

Objective-C type name Xamarin.iOS Unified API type

BOOL, GLboolean bool

NSInteger nint

NSUInteger nuint

CFTimeInterval / NSTimeInterval double

NSString (more on binding NSString) string


char * [PlainString] string

CGRect CGRect

CGPoint CGPoint

CGSize CGSize

CGFloat, GLfloat nfloat

CoreFoundation types (CF*) CoreFoundation.CF*

GLint nint

GLfloat nfloat

Foundation types (NS*) Foundation.NS*

id Foundation.NSObject

NSGlyph nint

NSSize CGSize

NSTextAlignment UITextAlignment

SEL ObjCRuntime.Selector

dispatch_queue_t CoreFoundation.DispatchQueue

CFTimeInterval double

CFIndex nint

NSGlyph nuint

Arrays

The Xamarin.iOS runtime automatically takes care of converting C# arrays to NSArrays and doing the
conversion back, so for example the imaginary Objective-C method that returns an NSArray of UIViews:

// Get the peer views - untyped


- (NSArray *)getPeerViews ();

// Set the views for this container


- (void) setViews:(NSArray *) views

Is bound like this:

[Export ("getPeerViews")]
UIView [] GetPeerViews ();
[Export ("setViews:")]
void SetViews (UIView [] views);

The idea is to use a strongly typed C# array as this will allow the IDE to provide proper code completion
with the actual type without forcing the user to guess, or look up the documentation to find out the actual
type of the objects contained in the array.

In cases where you can not track down the actual most derived type contained in the array, you can use
NSObject [] as the return value.

Selectors

Selectors appear on the Objective-C API as the special type "SEL". When binding a selector, you would
map the type to ObjCRuntime.Selector. Typically selectors are exposed in an API with both an object,
the target object, and a selector to invoke in the target object. Providing both of these basically corresponds
to the C# delegate: something that encapsulates both the method to invoke as well as the object to invoke
the method in.

This is what the binding looks like:

interface Button {
[Export ("setTarget:selector:")]
void SetTarget (NSObject target, Selector sel);
}

And this is how the method would typically be used in an application:

class DialogPrint : UIViewController {


void HookPrintButton (Button b)
{
b.SetTarget (this, new Selector ("print"));
}

[Export ("print")]
void ThePrintMethod ()
{
// This does the printing
}
}
To make the binding nicer to C# developers, you typically will provide a method that takes an NSAction
parameter, which allows C# delegates and lambdas to be used instead of the Target+Selector. To do
this you would typically hide the "SetTarget" method by flagging it with an "Internal" attribute and then you
would expose a new helper method, like this:

// API.cs
interface Button {
[Export ("setTarget:selector:"), Internal]
void SetTarget (NSObject target, Selector sel);
}

// Extensions.cs
public partial class Button {
public void SetTarget (NSAction callback)
{
SetTarget (new NSActionDispatcher (callback),
NSActionDispatcher.Selector);
}
}

So now your user code can be written like this:

class DialogPrint : UIViewController {


void HookPrintButton (Button b)
{
// First Style
b.SetTarget (ThePrintMethod);

// Lambda style
b.SetTarget (() => { /* print here */ });
}

void ThePrintMethod ()
{
// This does the printing
}
}
Strings

When you are binding a method that takes an NSString, you can replace that with a C# string type, both
on return types and parameters.

The only case when you might want to use an NSString directly is when the string is used as a token. For
more information about strings and NSString, read the API Design on NSString document.

In some rare cases, an API might expose a C-like string (char *) instead of an Objective-C string
(NSString *). In those cases, you can annotate the parameter with the [PlainString] attribute.

out/ref parameters

Some APIs return values in their parameters, or pass parameters by reference.

Typically the signature looks like this::

- (void) someting:(int) foo withError:(NSError **) retError


- (void) someString:(NSObject **)byref

The first example shows a common Objective-C idiom to return error codes, a pointer to an NSError
pointer is passed, and upon return the value is set. The second method shows how an Objective-C method
might take an object and modify its contents. This would be a pass by reference, rather than a pure output
value.

Your binding would look like this:

[Export ("something:withError:")]
void Something (nint foo, out NSError error);
[Export ("someString:")]
void SomeString (ref NSObject byref);

Memory management attributes

When you use the [Export] attribute and you are passing data that will be retained by the called method,
you can specify the argument semantics by passing it as a second parameter, for example:

[Export ("method", ArgumentSemantic.Retain)]

The above would flag the value as having the "Retain" semantics. The semantics available are:
Assign:
Copy:

Retain:

Style Guidelines

Using [Internal]

You can use the [Internal] attribute to hide a method from the public API. You might want to do this in cases
where the exposed API is too low-level and you want to provide a high-level implementation in a separate
file based on this method.

You can also use this when you run into limitations in the binding generator, for example some advanced
scenarios might expose types that are not bound and you want to bind in your own way, and you want to
wrap those types yourself in your own way.

Event Handlers and Callbacks


Objective-C classes typically broadcast notifications or request information by sending a message on a
delegate class (Objective-C delegate).

This model, while fully supported and surfaced by Xamarin.iOS can sometimes be cumbersome.
Xamarin.iOS exposes the C# event pattern and a method-callback system on the class that can be used in
these situations. This allows code like this to run:

button.Clicked += delegate {
Console.WriteLine ("I was clicked");
};

The binding generator is capable of reducing the amount of typing required to map the Objective-C pattern
into the C# pattern.

Starting with Xamarin.iOS 1.4 it will be possible to also instruct the generator to produce bindings for a
specific Objective-C delegates and expose the delegate as C# events and properties on the host type.

There are two classes involved in this process, the host class which will is the one that currently emits
events and sends those into the Delegate or WeakDelegate and the actual delegate class.

Considering the following setup:


[BaseType (typeof (NSObject))]
interface MyClass {
[Export ("delegate", ArgumentSemantic.Assign)][NullAllowed]
NSObject WeakDelegate { get; set; }

[Wrap ("WeakDelegate")][NullAllowed]
MyClassDelegate Delegate { get; set; }
}

[BaseType (typeof (NSObject))]


interface MyClassDelegate {
[Export ("loaded:bytes:")]
void Loaded (MyClass sender, int bytes);
}

To wrap the class you must:

In your host class, add to your [BaseType] declaration the type that is acting as its delegate and
the C# name that you exposed. In our example above those are "typeof (MyClassDelegate)" and
"WeakDelegate" respectively.
In your delegate class, on each method that has more than two parameters, you need to specify the
type that you want to use for the automatically generated EventArgs class.

The binding generator is not limited to wrapping only a single event destination, it is possible that some
Objective-C classes to emit messages to more than one delegate, so you will have to provide arrays to
support this setup. Most setups will not need it, but the generator is ready to support those cases.

The resulting code will be:

[BaseType (typeof (NSObject),


Delegates=new string [] {"WeakDelegate"},
Events=new Type [] { typeof (MyClassDelegate) })]
interface MyClass {
[Export ("delegate", ArgumentSemantic.Assign)][NullAllowed]
NSObject WeakDelegate { get; set; }

[Wrap ("WeakDelegate")][NullAllowed]
MyClassDelegate Delegate { get; set; }
}
[BaseType (typeof (NSObject))]
interface MyClassDelegate {
[Export ("loaded:bytes:"), EventArgs ("MyClassLoaded")]
void Loaded (MyClass sender, int bytes);
}

The EventArgs is used to specify the name of the EventArgs class to be generated. You should use
one per signature (in this example, the EventArgs will contain a "With" property of type nint).

With the definitions above, the generator will produce the following event in the generated MyClass:

public MyClassLoadedEventArgs : EventArgs {


public MyClassLoadedEventArgs (nint bytes);
public nint Bytes { get; set; }
}

public event EventHandler<MyClassLoadedEventArgs> Loaded {


add; remove;
}

So you can now use the code like this:

MyClass c = new MyClass ();


c.Loaded += delegate (sender, args){
Console.WriteLine ("Loaded event with {0} bytes", args.Bytes);
};

Callbacks are just like event invocations, the difference is that instead of having multiple potential
subscribers (for example, multiple methods can hook into a "Clicked" event or a "Download Finished"
event) callbacks can only have a single subscriber.

The process is identical, the only difference is that instead of exposing the name of the EventArgs class
that will be generated, the EventArgs actually is used to name the resulting C# delegate name.

If the method in the delegate class returns a value, the binding generator will map this into a delegate
method in the parent class instead of an event. In these cases you need to provide the default value that
should be returned by the method if the user does not hook up to the delegate. You do this using the
[DefaultValue] or [DefaultValueFromArgument] attributes.

DefaultValue will hardcode a return value, while [DefaultValueFromArgument] is used to specify


which input argument will be returned.

Enumerations and Base Types


You can also reference enumerations or base types that are not directly supported by the btouch interface
definition system. To do this, put your enumerations and core types into a separate file and include this as
part of one of the extra files that you provide to btouch.

Linking the Dependencies


If you are binding APIs that are not part of your application, you need to make sure that your executable is
linked against these libraries.

You need to inform Xamarin.iOS how to link your libraries, this can be done either by altering your build
configuration to invoke the mtouch command with some extra build arguments that specify how to link with
the new libraries using the "-gcc_flags" option, followed by a quoted string that contains all the extra
libraries that are required for your program, like this:

-gcc_flags "-L${ProjectDir} -lMylibrary -force_load -lSystemLibrary -framework


CFNetwork -ObjC"

The above example will link libMyLibrary.a, libSystemLibrary.dylib and the CFNetwork
framework library into your final executable.

Or you can take advantage of the assembly-level LinkWithAttribute, that you can embed in your
contract files (such as AssemblyInfo.cs). When you use the LinkWithAttribute, you will need to
have your native library available at the time you make your binding, as this will embed the native library
with your application. For example:

// Specify only the library name as a constructor argument and specify


everything else with properties:
[assembly: LinkWith ("libMyLibrary.a", LinkTarget = LinkTarget.ArmV6 |
LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, IsCxx = true)]

// Or you can specify library name *and* link target as constructor arguments:
[assembly: LinkWith ("libMyLibrary.a", LinkTarget.ArmV6 | LinkTarget.ArmV7 |
LinkTarget.Simulator, ForceLoad = true, IsCxx = true)]

You might be wondering, why do you need "force_load" command, and the reason is that the -ObjC flag
although it compiles the code in, it does not preserve the metadata required to support categories (the
linker/compiler dead code elimination strips it) which you need at runtime for Xamarin.iOS.

Assisted References
Some transient objects like action sheets and alert boxes are cumbersome to keep track of for developers
and the binding generator can help a little bit here.

For example if you had a class that showed a message and then generated a "Done" event, the traditional
way of handling this would be:

class Demo {
MessageBox box;

void ShowError (string msg)


{
box = new MessageBox (msg);
box.Done += { box = null; ... };
}
}

In the above scenario the developer needs to keep the reference to the object himself and either leak or
actively clear the reference for box on his own. While binding code, the generator supports keeping track of
the reference for you and clear it when a special method is invoked, the above code would then become:

class Demo {
void ShowError (string msg)
{
var box = new MessageBox (msg);
box.Done += { ... };
}
}

Notice how it is no longer necessary to keep the variable in an instance, that it works with a local variable
and that it is not necessary to clear the reference when the object dies.

To take advantage of this, your class should have a Events property set in the [BaseType] declaration
and also the KeepUntilRef variable set to the name of the method that is invoked when the object has
completed its work, like this:
[BaseType (typeof (NSObject), KeepUntilRef="Dismiss"), Delegates=new string []
{ "WeakDelegate" }, Events=new Type [] { typeof (SomeDelegate) }) ]
class Demo {
[Export ("show")]
void Show (string message);
}

Inheriting Protocols
As of Xamarin.iOS v3.2, we support inheriting from protocols that have been marked with the [Model]
property. This is useful in certain API patterns, such as in MapKit where the MKOverlay protocol, inherits
from the MKAnnotation protocol, and is adopted by a number of classes which inherit from NSObject.

Historically we required copying the protocol to every implementation, but in these cases now we can have
the MKShape class inherit from the MKOverlay protocol and it will generate all the required methods
automatically.
Binding Types Reference Guide
This document describes the list of attributes that you can use to annotate your API contract
files to drive the binding and the code generated

Xamarin.iOS and Xamarin.Mac API contracts are written in C# mostly as interface definitions
that define the way that Objective-C code is surfaced to C#. The process involves a mix of
interface declarations plus some basic type definitions that the API contract might require.
For an introduction to binding types, see our companion guide Binding Objective-C Libraries.

Type Definitions
Syntax:

[BaseType (typeof (BTYPE))


interface MyType [: Protocol1, Protocol2] {
IntPtr Constructor (string foo);
}

Every interface in your contract definition that has the [BaseType] attribute that declares
the base type for the generated object. In the above declaration a MyType class C# type will
be generated that binds to an Objective-C type called MyType.

If you specify any types after the typename (in the sample above Protocol1 and
Protocol2) using the interface inheritance syntax the contents of those interfaces will be
inlined as if they had been part of the contract for MyType. The way that Xamarin.iOS
surfaces that a type adopts a protocol is by inlining all of the methods and properties that
were declared in the protocol into the type itself.

The following shows how the Objective-C declaration for UITextField would be defined in
a Xamarin.iOS contract:
@interface UITextField : UIControl <UITextInput> {

Would be written like this as a C# API contract:

[BaseType (typeof (UIControl))]


interface UITextField : UITextInput {
}

You can control many other aspects of the code generation by applying other attributes to
the interface as well as configuring the BaseType attribute.

Generating Events

One feature of the Xamarin.iOS and Xamarin.Mac API design is that we map Objective-C
delegate classes as C# events and callbacks. Users can choose in a per-instance basis
whether they want to adopt the Objective-C programming pattern, by assigning to properties
like Delegate an instance of a class that implements the various methods that the Objective-
C runtime would call, or by choosing the C#-style events and properties.

Let us see one example of how to use the Objective-C model:

bool MakeDecision ()
{
return true;
}

void Setup ()
{
var scrollView = new UIScrollView (myRect);
scrollView.Delegate = new MyScrollViewDelegate ();
...
}
class MyScrollViewDelegate : UIScrollViewDelegate {
public override void Scrolled (UIScrollView scrollView)
{
Console.WriteLine ("Scrolled");
}

public override bool ShouldScrollToTop (UIScrollView scrollView)


{
return MakeDecision ();
}
}

In the above example, you can see that we have chosen to overwrite two methods, one a
notification that a scrolling event has taken place, and the second that is a callback that
should return a boolean value instructing the scrollView whether it should scroll to the top or
not.

The C# model allows the user of your library to listen to notifications using the C# event
syntax or the property syntax to hook up callbacks that are expected to return values.

This is how the C# code for the same feature looks like using lambdas:

void Setup ()
{
var scrollview = new UIScrollView (myRect);
// Event connection, use += and multiple events can be connected
scrollView.Scrolled += (sender, eventArgs) { Console.WriteLine
("Scrolled"); }

// Property connection, use = only a single callback can be used


scrollView.ShouldScrollToTop = (sv) => MakeDecision ();
}

Since events do not return values (they have a void return type) you can connect multiple
copies. The ShouldScrollToTop is not an event, it is instead a property with the type
UIScrollViewCondition which has this signature:

public delegate bool UIScrollViewCondition (UIScrollView


scrollView);

It returns a bool value, in this case the lambda syntax allows us to just return the value from
the MakeDecision function.

The binding generator supports generating events and properties that link a class like
UIScrollView with its UIScrollViewDelegate (well call these the Model class), this is
done by annotating your BaseType definition with the Events and Delegates parameters
(described below). In addition to annotating the BaseType with those parameters it is
necessary to inform the generator of a few more components.

For events that take more than one parameter (in Objective-C the convention is that the first
parameter in a delegate class is the instance of the sender object) you must provide the
name that you would like for the generated EventArgs class to be. This is done with the
EventArgs attribute on the method declaration in your Model class. For example:

[BaseType (typeof (UINavigationControllerDelegate))]


[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export
("imagePickerController:didFinishPickingImage:editingInfo:"),
EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker,
UIImage image, NSDictionary editingInfo);
}

The above declaration will generate a UIImagePickerImagePickedEventArgs class


that derives from EventArgs and packs both parameters, the UIImage and the
NSDictionary. The generator produces this:

public partial class UIImagePickerImagePickedEventArgs : EventArgs {


public UIImagePickerImagePickedEventArgs (UIImage image,
NSDictionary editingInfo);
public UIImage Image { get; set; }
public NSDictionary EditingInfo { get; set; }
}

It then exposes the following in the UIImagePickerController class:

public event EventHandler<UIImagePickerImagePickedEventArgs>


FinishedPickingImage { add; remove; }

Model methods that return a value are bound differently. Those require both a name for the
generated C# delegate (the signature for the method) and also a default value to return in
case the user does not provide an implementation himself. For example, the
ShouldScrollToTop definition is this:

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface UIScrollViewDelegate {
[Export ("scrollViewShouldScrollToTop:"), DelegateName
("UIScrollViewCondition"), DefaultValue ("true")]
bool ShouldScrollToTop (UIScrollView scrollView);
}

The above will create a UIScrollViewCondition delegate with the signature that was
shown above, and if the user does not provide an implementation, the return value will be
true.

In addition to the DefaultValue attribute, you can also use the


DefaultValueFromArgument that directs the generator to return the value of the
specified parameter in the call or the NoDefaultValue parameter that instructs the
generator that there is no default value.

BaseTypeAttribute
Syntax:

public class BaseTypeAttribute : Attribute {


public BaseTypeAttribute (Type t);

// Properties
public Type BaseType { get; set; }
public string Name { get; set; }
public Type [] Events { get; set; }
public string [] Delegates { get; set; }
public string KeepRefUntil { get; set; }
}

BaseType.Name

You use the Name property to control the name that this type will bind to in the Objective-C
world. This is typically used to give the C# type a name that is compliant with the .NET
Framework Design Guidelines, but which maps to a name in Objective-C that does not
follow that convention.

Example, in the following case we map the Objective-C NSURLConnection type to


NSUrlConnection, as the .NET Framework Design Guidelines use "Url" instead of "URL":

[BaseType (typeof (NSObject), Name="NSURLConnection")]


interface NSUrlConnection {
}

The specified name is specified is used as the value for the generated [Register]
attribute in the binding. If Name is not specified, the type's short name is used as the value
for the Register attribute in the generated output.

BaseType.Events and BaseType.Delegates

These properties are used to drive the generation of C#-style Events in the generated
classes. They are used to link a given class with its Objective-C delegate class. You will
encounter many cases where a class uses a delegate class to send notifications and events.
For example a BarcodeScanner would have a companion BardodeScannerDelegate
class. The BarcodeScanner class would typically have a "delegate" property that you
would assign an instance of BarcodeScannerDelegate to, while this works, you might
want to expose to your users a C#-like style event interface, and in those cases you would
use the Events and Delegates properties of the BaseType attribute.

These properties are always set together and must have the same number of elements and
be kept in sync. The Delegates array contains one string for each weakly-typed delegate
that you want to wrap, and the Events array contains one type for each type that you want to
associate with it.

[BaseType (typeof (NSObject),


Delegates=new string [] { "WeakDelegate" },
Events=new Type [] {typeof(UIAccelerometerDelegate)})]
public interface UIAccelerometer {
}

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface UIAccelerometerDelegate {
}

BaseType.KeepRefUntil

If you apply this attribute when new instances of this class are created, the instance of that
object will be kept around until the method referenced by the KeepRefUntil has been
invoked. This is useful to improve the usability of your APIs, when you do not want your user
to keep a reference to an object around to use your code. The value of this property is the
name of a method in the Delegate class, so you must use this in combination with the
Events and Delegates properties as well.

The following example show how this is used by UIActionSheet in Xamarin.iOS:


[BaseType (typeof (NSObject), KeepRefUntil="Dismissed")]
[BaseType (typeof (UIView),
KeepRefUntil="Dismissed",
Delegates=new string [] { "WeakDelegate" },
Events=new Type [] {typeof(UIActionSheetDelegate)})]
public interface UIActionSheet {
}

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface UIActionSheetDelegate {
[Export ("actionSheet:didDismissWithButtonIndex:"), EventArgs
("UIButton")]
void Dismissed (UIActionSheet actionSheet, nint buttonIndex);
}

DisableDefaultCtorAttribute

When this attribute is applied to the interface definition it will prevent the generator from
producing the default constructor.

Use this attribute when you need the object to be initialized with one of the other
constructors in the class.

PrivateDefaultCtorAttribute

When this attribute is applied to the interface definition it will flag the default constructor as
private. This means that you can still instantiate object of this class internally from your
extension file, but it just wont be accessible to users of your class.

CategoryAttribute
Use this attribute on a type definition to bind Objective-C categories and to expose those as
C# extension methods to mirror the way Objective-C exposes the functionality.

Categories are an Objective-C mechanism used to extend the set of methods and properties
available in a class. In practice, they are used to either extend the functionality of a base
class (for example NSObject) when a specific framework is linked in (for example UIKit),
making their methods available, but only if the new framework is linked in. In some other
cases, they are used to organize features in a class by functionality. They are similar in spirit
to C# extension methods.

This is what a category would look like in Objective-C:

@interface UIView (MyUIViewExtension)


-(void) makeBackgroundRed;
@end

The above example if found on a library would extend instances of UIView with the method
makeBackgroundRed.

To bind those, you can use the [Category] attribute on an interface definition. When using
the Category attribute, the meaning of the [BaseType] attribute changes from being used
to specify the base class to extend, to be the type to extend.

The following shows how the UIView extensions are bound and turned into C# extension
methods:

[BaseType (typeof (UIView))]


[Category]
interface MyUIViewExtension {
[Export ("makeBackgroundRed")]
void MakeBackgroundRed ();
}

The above will create a MyUIViewExtension a class that contains the


MakeBackgroundRed extension method. This means that you can now call
"MakeBackgroundRed" on any UIView subclass, giving you the same functionality you
would get on Objective-C.

In some cases you will find static members inside categories like in the following example:

@interface FooObject (MyFooObjectExtension)


+ (BOOL)boolMethod:(NSRange *)range;
@end

This will lead to an incorrect Category C# interface definition:

[Category]
[BaseType (typeof (FooObject))]
interface FooObject_Extensions {

// Incorrect Interface definition


[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}

This is incorrect because to use the BoolMethod extension you need an instance of
FooObject but you are binding an ObjC static extension, this is a side effect due to the fact
of how C# extension methods are implemented.

The only way to use the above definitions is by the following ugly code:

(null as FooObject).BoolMethod (range);

The recommendation to avoid this is to inline the BoolMethod definition inside the
FooObject interface definition itself, this will allow you to call this extension like it is
intended FooObject.BoolMethod (range).

[BaseType (typeof (NSObject))]


interface FooObject {
[Static]
[Export ("boolMethod:")]
bool BoolMethod (NSRange range);
}

We will issue a warning (BI1117) whenever we find a [Static] member inside a


[Category] definition. If you really want to have [Static] members inside your
[Category] definitions you can silence the warning by using [Category
(allowStaticMembers: true)] or by decorating either your member or [Category]
interface definition with [Internal].

StaticAttribute

When this attribute is applied to a class it will just generate a static class, one that does not
derive from NSObject so the [BaseType] attribute is ignored. Static classes are used to
host C public variables that you want to expose.

For example:

[Static]
interface CBAdvertisement {
[Field ("CBAdvertisementDataServiceUUIDsKey")]
NSString DataServiceUUIDsKey { get; }

Will generate a C# class with the following API:

public partial class CBAdvertisement {


public static NSString DataServiceUUIDsKey { get; }
}

Model Definitions
Protocol definitions/Model
Models are typically used by protocol implementation. They differ in that the runtime will only
register with Objective-C the methods that actually have been overwritten. Otherwise, the
method will not be registered.

This in general means that when you subclass a class that has been flagged with the
ModelAttribute, you should not call the base method. Calling that method will throw an
exception, you are supposed to implement the entire behavior on your subclass for any
methods you override.

AbstractAttribute

By default, members that are part of a protocol are not mandatory. This allows users to
create a subclass of the Model object by merely deriving from the class in C# and overriding
only the methods they care about. Sometimes the Objective-C contract requires that the user
provides an implementation for this method (those are flagged with the @required directive
in Objective-C). In those cases, you should flag those methods with the Abstract attribute.

The Abstract attribute can be applied to either methods or properties and causes the
generator to flag the generated member as "abstract" and the class to be an abstract class.

The following is taken from Xamarin.iOS:

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface UITableViewDataSource {
[Export ("tableView:numberOfRowsInSection:")]
[Abstract]
nint RowsInSection (UITableView tableView, nint section);
}

DefaultValueAttribute

Specifies the default value to be returned by a model method if the user does not provide a
method for this particular method in the Model object
Syntax:

public class DefaultValueAttribute : Attribute {


public DefaultValueAttribute (object o);
public object Default { get; set; }
}

For example, in the following imaginary delegate class for a Camera class, we provide a
ShouldUploadToServer which would be exposed as a property on the Camera class. If
the user of the Camera class does not explicitly set a the value to a lambda that can respond
true or false, the default value return in this case would be false, the value that we specified
in the DefaultValue attribute:

[BaseType (typeof (NSObject))]


[Model][Protocol]
interface CameraDelegate {
[Export ("camera:shouldPromptForAction:"), DefaultValue (false)]
bool ShouldUploadToServer (Camera camera, CameraAction action);
}

If the user sets a handler in the imaginary class, then this value would be ignored:

var camera = new Camera ();


camera.ShouldUploadToServer = (camera, action) => return
SomeDecision ();

See also: NoDefaultValueAttribute, DefaultValueFromArgumentAttribute.

DefaultValueFromArgumentAttribute

Syntax:

public class DefaultValueFromArgumentAttribute : Attribute {


public DefaultValueFromArgumentAttribute (string argument);
public string Argument { get; }
}

This attribute when provided on a method that returns a value on a model class will instruct
the generator to return the value of the specified parameter if the user did not provide his
own method or lambda.

Example:

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateName
("NSAnimationProgress"), DefaultValueFromArgumentAttribute
("progress")]
float ComputeAnimationCurve (NSAnimation animation, nfloat
progress);
}

In the above case if the user of the NSAnimation class chose to use any of the C#
events/properties, and did not set NSAnimation.ComputeAnimationCurve to a method
or lambda, the return value would be the value passed in the progress parameter.

See also: NoDefaultValueAttribute, DefaultValueAttribute

IgnoredInDelegateAttribute

Sometimes it makes sense not to expose an event or delegate property from a Model class
into the host class so adding this attribute will instruct the generator to avoid the generation
of any method decorated with it.

[BaseType (typeof (UINavigationControllerDelegate))]


[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export
("imagePickerController:didFinishPickingImage:editingInfo:"),
EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker,
UIImage image, NSDictionary editingInfo);

[Export ("imagePickerController:didFinishPickingImage:"),
IgnoredInDelegate)] // No event generated for this method
void FinishedPickingImage (UIImagePickerController picker,
UIImage image);
}

DelegateNameAttribute

This attribute is used in Model methods that return values to set the name of the delegate
signature to use.

Example:

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateName
("NSAnimationProgress"), DefaultValueFromArgumentAttribute
("progress")]
float ComputeAnimationCurve (NSAnimation animation, float
progress);
}

With the above definition, the generator will produce the following public declaration:

public delegate float NSAnimationProgress


(MonoMac.AppKit.NSAnimation animation, float progress);

DelegateApiNameAttribute
This attribute is used to allow the generator to change the name of the property generated in
the host class. Sometimes it is useful when the name of the FooDelegate class method
makes sense for the Delegate class, but would look odd in the host class as a property.

Also this is really useful (and needed) when you have two or more overload methods that
makes sense to keep them named as is in the FooDelegate class but you want to expose
them in the host class with a better given name.

Example:

[BaseType (typeof (NSObject))]


[Model][Protocol]
public interface NSAnimationDelegate {
[Export ("animation:valueForProgress:"), DelegateApiName
("ComputeAnimationCurve"), DelegateName ("Func<NSAnimation, float,
float>"), DefaultValueFromArgument ("progress")]
float GetValueForProgress (NSAnimation animation, float
progress);
}

With the above definition, the generator will produce the following public declaration in the
host class:

public Func<NSAnimation, float, float> ComputeAnimationCurve { get;


set; }

EventArgsAttribute

For events that take more than one parameter (in Objective-C the convention is that the first
parameter in a delegate class is the instance of the sender object) you must provide the
name that you would like for the generated EventArgs class to be. This is done with the
EventArgs attribute on the method declaration in your Model class.

For example:
[BaseType (typeof (UINavigationControllerDelegate))]
[Model][Protocol]
public interface UIImagePickerControllerDelegate {
[Export
("imagePickerController:didFinishPickingImage:editingInfo:"),
EventArgs ("UIImagePickerImagePicked")]
void FinishedPickingImage (UIImagePickerController picker,
UIImage image, NSDictionary editingInfo);
}

The above declaration will generate a UIImagePickerImagePickedEventArgs class


that derives from EventArgs and packs both parameters, the UIImage and the
NSDictionary. The generator produces this:

public partial class UIImagePickerImagePickedEventArgs : EventArgs {


public UIImagePickerImagePickedEventArgs (UIImage image,
NSDictionary editingInfo);
public UIImage Image { get; set; }
public NSDictionary EditingInfo { get; set; }
}

It then exposes the following in the UIImagePickerController class:

public event EventHandler<UIImagePickerImagePickedEventArgs>


FinishedPickingImage { add; remove; }

EventNameAttribute

This attribute is used to allow the generator to change the name of an event or property
generated in the class. Sometimes it is useful when the name of the Model class method
makes sense for the model class, but would look odd in the originating class as an event or
property.

For example, the UIWebView uses the following bit from the UIWebViewDelegate:
[Export ("webViewDidFinishLoad:"), EventArgs ("UIWebView"),
EventName ("LoadFinished")]
void LoadingFinished (UIWebView webView);

The above exposes LoadingFinished as the method in the UIWebViewDelegate, but


LoadFinished as the event to hook up to in a UIWebView:

var webView = new UIWebView (...);


webView.LoadFinished += delegate { Console.WriteLine ("done!"); }

ModelAttribute

When you apply the Model attribute to a type definition in your contract API, the runtime will
generate special code that will only surface invocations to methods in the class if the user
has overwritten a method in the class. This attribute is typically applied to all APIs that wrap
an Objective-C delegate class.

NoDefaultValueAttribute

Specifies that the method on the model does not provide a default return value.

This works with the Objective-C runtime by responding "false" to the Objective-C runtime
request to determine if the specified selector is implemented in this class.

[BaseType (typeof (NSObject))]


[Model][Protocol]
interface CameraDelegate {
[Export ("shouldDisplayPopup"), NoDefaultValue]
bool ShouldUploadToServer ();
}

See also: DefaultValueAttribute and DefaultValueAttribute.

Protocols
The Objective-C protocol concept does not really exist in C#. Protocols are similar to C#
interfaces but they differ in that not all of the methods and properties declared in a protocol
must be implemented by the class that adopts it. Instead some of the methods and
properties are optional.

Some protocols are generally used as Model classes, those should be bound using the
Model attribute.

[BaseType (typeof (NSObject))]


[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required
section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);

[Export ("listen")]
void Listen ();
}

Starting with MonoTouch 7.0 a new and improved protocol binding functionality has been
incorporated. Any definition that contains the [Protocol] attribute will actually generate
three supporting classes that vastly improve the way that you consume protocols:

// Full method implementation, contains all methods


class MyProtocol : IMyProtocol {
public void Say (string msg);
public void Listen (string msg);
}

// Interface that contains only the required methods


interface IMyProtocol: INativeObject, IDisposable {
[Export ("say:")]
void Say (string msg);
}

// Extension methods
static class IMyProtocol_Extensions {
public static void Optional (this IMyProtocol this, string msg);
}
}

The class implementation provides a complete abstract class that you can override
individual methods of and get full type safety. But due to C# not supporting multiple
inheritance, there are scenarios where you might require a different base class, but still want
to implement an interface.

This is where the generated interface definition comes in. It is an interface that has all the
required methods from the protocol. This allows developers that want to implement your
protocol to merely implement the interface. The runtime will automatically register the type
as adopting the protocol.

Notice that the interface only lists the required methods and does expose the optional
methods. This means that classes that adopt the protocol will get full type checking for the
required methods, but will have to resort to weak typing (manually using Export attributes
and matching the signature) for the optional protocol methods.

To make it convenient to consume an API that uses protocols, the binding tool also will
produce an extensions method class that exposes all of the optional methods. This means
that as long as you are consuming an API, you will be able to treat protocols as having all
the methods.

If you want to use the protocol definitions in your API, you will need to write skeleton empty
interfaces in your API definition. If you want to use the MyProtocol in an API, you would need
to do this:
[BaseType (typeof (NSObject))]
[Model, Protocol]
interface MyProtocol {
// Use [Abstract] when the method is defined in the @required
section
// of the protocol definition in Objective-C
[Abstract]
[Export ("say:")]
void Say (string msg);

[Export ("listen")]
void Listen ();
}

interface IMyProtocol {}

[BaseType (typeof(NSObject))]
interface MyTool {
[Export ("getProtocol")]
IMyProtocol GetProtocol ();
}

The above is needed because at binding time the IMyProtocol would not exist, that is why
you need to provide an empty interface.

Adopting Protocol Generated Interfaces

Whenever you implement one of the interfaces generated for the protocols, like this:

class MyDelegate : NSObject, IUITableViewDelegate {


nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}

The implementation for the interface methods automatically gets exported with the proper
name, so it is equivalent to this:

class MyDelegate : NSObject, IUITableViewDelegate {


[Export ("getRowHeight:")]
nint IUITableViewDelegate.GetRowHeight (nint row) {
return 1;
}
}

It does not matter if the interface is implemented implicitly or explicitly.

Protocol Inlining

While you bind existing Objective-C types that have been declared as adopting a protocol,
you will want to inline the protocol directly. To do this, merely declare your protocol as an
interface without any [BaseType] attribute and list the protocol in the list of base interfaces
for your interface.

Example:

interface SpeakProtocol {
[Export ("say:")]
void Say (string msg);
}

[BaseType (typeof (NSObject))]


interface Robot : SpeakProtocol {
[Export ("awake")]
bool Awake { get; set; }
}
Member Definitions
The attributes in this section are applied to individual members of a type: properties and
method declarations.

AlignAttribute

Used to specify the alignment value for property return types. Certain properties take
pointers to addresses that must be aligned at certain boundaries (in Xamarin.iOS this
happens for example with some GLKBaseEffect properties that must be 16-byte aligned).
You can use this property to decorate the getter, and use the alignment value. This is
typically used with the OpenTK.Vector4 and OpenTK.Matrix4 types when integrated
with Objective-C APIs.

Example:

public interface GLKBaseEffect {


[Export ("constantColor")]
Vector4 ConstantColor { [Align (16)] get; set; }
}

AppearanceAttribute

The Appearance attribute is limited to iOS5 where the Appearance manager was
introduced.

The Appearance attribute can be applied to any method or property that participate in the
UIAppearance framework. When this attribute is applied to a method or property in a class,
it will direct the binding generator to create a strongly-typed appearance class that is used to
style all the instances of this class, or the instances that match certain criteria.

Example:

public interface UIToolbar {


[Since (5,0)]
[Export ("setBackgroundImage:forToolbarPosition:barMetrics:")]
[Appearance]
void SetBackgroundImage (UIImage backgroundImage,
UIToolbarPosition position, UIBarMetrics barMetrics);

[Since (5,0)]
[Export ("backgroundImageForToolbarPosition:barMetrics:")]
[Appearance]
UIImage GetBackgroundImage (UIToolbarPosition position,
UIBarMetrics barMetrics);
}

The above would generate the following code in UIToolbar:

public partial class UIToolbar {


public partial class UIToolbarAppearance :
UIView.UIViewAppearance {
public virtual void SetBackgroundImage (UIImage
backgroundImage, UIToolbarPosition position, UIBarMetrics
barMetrics);
public virtual UIImage GetBackgroundImage (UIToolbarPosition
position, UIBarMetrics barMetrics)
}
public static new UIToolbarAppearance Appearance { get; }
public static new UIToolbarAppearance AppearanceWhenContainedIn
(params Type [] containers);
}

AutoReleaseAttribute (Xamarin.iOS 5.4)

Use the AutoReleaseAttribute on methods and properties to wrap the method


invocation to the method in an NSAutoReleasePool.
In Objective-C there are some methods that return values that are added to the default
NSAutoReleasePool. By default, these would go to your thread NSAutoReleasePool,
but since Xamarin.iOS also keeps a reference to your objects as long as the managed object
lives, you might not want to keep an extra reference in the NSAutoReleasePool which will
only get drained until your thread returns control to the next thread, or you go back to the
main loop.

This attribute is applied for example on heavy properties (for example UIImage.FromFile)
that returns objects that have been added to the default NSAutoReleasePool. Without this
attribute, the images would be retained as long as your thread did not return control to the
main loop. Uf your thread was some sort of background downloader that is always alive and
waiting for work, the images would never be released.

ForcedTypeAttribute

The ForcedTypeAttribute is used to enforce the creation of a managed type even if the
returned unmanaged object does not match the type described in the binding definition.

This is useful when the type described in a header does not match the returned type of the
native method, for example take the following Objective-C definition from NSURLSession:

- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest
*)request

It clearly states that it will return an NSURLSessionDownloadTask instance, but yet it


returns a NSURLSessionTask, which is a superclass and thus not convertible to
NSURLSessionDownloadTask. Since we are in a type-safe context an
InvalidCastException will happen.

To comply with the header description and avoid the InvalidCastException, the
ForcedTypeAttribute is used.

[BaseType (typeof (NSObject), Name="NSURLSession")]


interface NSUrlSession {
[Export ("downloadTaskWithRequest:")]
[return: ForcedType]
NSUrlSessionDownloadTask CreateDownloadTask (NSUrlRequest
request);
}

The ForcedTypeAttribute also accepts a boolean value named Owns that is false by
default [ForcedType (owns: true)]. The owns parameter is used to follow the
Ownership Policy for Core Foundation objects.

The ForcedTypeAttribute is only valid on parameters, properties and return


value.

BindAsAttribute

The BindAsAttribute allows binding NSNumber, NSValue and NSString(enums) into


more accurate C# types. The attribute can be used to create better, more accurate, .NET
API over the native API.

You can decorate methods (on return value), parameters and properties with BindAs. The
only restriction is that your member must not be inside a [Protocol] or [Model]
interface.

For example:

[return: BindAs (typeof (bool?))]


[Export ("shouldDrawAt:")]
NSNumber ShouldDraw ([BindAs (typeof (CGRect))] NSValue rect);

Would output:

[Export ("shouldDrawAt:")]
bool? ShouldDraw (CGRect rect) { ... }
Internally we will do the bool? <-> NSNumber and CGRect <-> NSValue conversions.

The current supported encapsulation types are:

NSValue
NSNumber
NSString

NSValue

The following C# data types are supported to be encapsulated from/into NSValue:

CGAffineTransform
NSRange
CGVector
SCNMatrix4
CLLocationCoordinate2D
SCNVector3
SCNVector4
CGPoint / PointF
CGRect / RectangleF
CGSize / SizeF
UIEdgeInsets
UIOffset
MKCoordinateSpan
CMTimeRange
CMTime
CMTimeMapping
CATransform3D

NSNumber

The following C# data types are supported to be encapsulated from/into NSNumber:

bool
byte
double
float
short
int
long
sbyte
ushort
uint
ulong
nfloat
nint
nuint
Enums

NSString

[BindAs] works in conjuntion with enums backed by a NSString constant so you can
create better .NET API, for example:

[BindAs (typeof (CAScroll))]


[Export ("supportedScrollMode")]
NSString SupportedScrollMode { get; set; }

Would output:

[Export ("supportedScrollMode")]
CAScroll SupportedScrollMode { get; set; }

We will handle the enum <-> NSString conversion only if the provided enum type to
[BindAs] is backed by a NSString constant.

Arrays

[BindAs] also supports arrays of any of the supported types, you can have the following
API definition as an example:

[return: BindAs (typeof (CAScroll []))]


[Export ("getScrollModesAt:")]
NSString [] GetScrollModes ([BindAs (typeof (CGRect []))] NSValue []
rects);

Would output:

[Export ("getScrollModesAt:")]
CAScroll? [] GetScrollModes (CGRect [] rects) { ... }

The rects parameter will be encapsulated into a NSArray that contains an NSValue for
each CGRect and in return you will get an array of CAScroll? which has been created
using the values of the returned NSArray containing NSStrings.

BindAttribute

The Bind attribute has two uses one when applied to a method or property declaration, and
another one when applied to the individual getter or setter in a property.

When used for a method or property, the effect of the Bind attribute is to generate a method
that invokes the specified selector. But the resulting generated method is not decorated with
the [Export] attribute, which means that it can not participate in method overriding. This is
typically used in combination with the Target attribute for implementing Objective-C
extension methods.

For example:

public interface UIView {


[Bind ("drawAtPoint:withFont:")]
SizeF DrawString ([Target] string str, CGPoint point, UIFont
font);
}
When used in a getter or setter, the Bind attribute is used to alter the defaults inferred by
the code generator when generating the getter and setter Objective-C selector names for a
property. By default when you flag a property with the name "fooBar", the generator would
generate a "fooBar" export for the getter and "setFooBar:" for the setter. In a few cases,
Objective-C does not follow this convention, usually they change the getter name to be
"isFooBar". You would use this attribute to inform the generator of this.

For example:

// Default behavior
[Export ("active")]
bool Active { get; set; }

// Custom naming with the Bind attribute


[Export ("visible")]
bool Visible { [Bind ("isVisible")] get; set; }

AsyncAttribute

Only available on Xamarin.iOS 6.3 and newer.

This attribute can be applied to methods that take a completion handler as their last
argument.

You can use the [Async] attribute on methods whose last argument is a callback. When
you apply this to a method, the binding generator will generate a version of that method with
the suffix Async. If the callback takes no parameters, the return value will be a Task, if the
callback takes a parameter, the result will be a Task<T>.

[Export ("upload:complete:")]
[Async]
void LoadFile (string file, NSAction complete)

The following will generate this async method:


Task LoadFileAsync (string file);

If the callback takes multiple parameters, you should set the ResultType or
ResultTypeName to specify the desired name of the generated type which will hold all the
properties.

delegate void OnComplete (string [] files, nint byteCount);

[Export ("upload:complete:")]
[Async (ResultTypeName="FileLoading")]
void LoadFiles (string file, OnComplete complete)

The following will generate this async method, where FileLoading contains properties to
access both "files" and "byteCount":

Task<FileLoading> LoadFile (string file);

If the last parameter of the callback is an NSError, then the generated Async method will
check if the value is not null, and if that is the case, the generated async method will set the
task exception.

[Export ("upload:onComplete:")]
[Async]
void Upload (string file, Action<string,NSError> onComplete);

The above generates the following async method:

Task<string> UploadAsync (string file);

And on error, the resulting Task will have the exception set to an NSErrorException that
wraps the resulting NSError.

AsyncAttribute.ResultType

Use this property to specify the value for the returning Task object. This parameter takes an
existing type, thus it needs to be defined in one of your core api definitions.
AsyncAttribute.ResultTypeName

Use this property to specify the value for the returning Task object. This parameter takes the
name of your desired type name, the generator will produce a series of properties, one for
each parameter that the callback takes.

AsyncAttribute.MethodName

Use this property to customize the name of the generated async methods. The default is to
use the name of the method and append the text "Async", you can use this to change this
default.

DisableZeroCopyAttribute

This attribute is applied to string parameters or string properties and instructs the code
generator to not use the zero-copy string marshaling for this parameter, and instead create a
new NSString instance from the C# string. This attribute is only required on strings if you
instruct the generator to use zero-copy string marshaling using either the --zero-copy
command line option or setting the assembly-level attribute ZeroCopyStringsAttribute.

This is necessary in cases where the property is declared in Objective-C to be a "retain" or


"assign" property instead of a "copy" property. These typically happen in third-party libraries
that have been wrongly "optimized" by developers. In general, "retain" or "assign" NSString
properties are incorrect since NSMutableString or user-derived classes of NSString
might alter the contents of the strings without the knowledge of the library code, subtly
breaking the application. Typically this happens due to premature optimization.

The following shows two such properties in Objective-C:

@property(nonatomic,retain) NSString *name;


@property(nonatomic,assign) NSString *name2;

DisposeAttribute
When you apply the DisposeAttribute to a class, you provide a code snippet that will be
added to the Dispose() method implementation of the class.

Since the Dispose method is automatically generated by the bmac-native and btouch-
native tools, you need to use the Dispose attribute to inject some code in the generated
Dispose method implementation.

For example:

[BaseType (typeof (NSObject))]


[Dispose ("if (OpenConnections > 0) CloseAllConnections ();")]
interface DatabaseConnection {
}

ExportAttribute

The Export attribute is used to flag a method or property to be exposed to the Objective-C
runtime. This attribute is shared between the binding tool and the actual Xamarin.iOS and
Xamarin.Mac runtimes. For methods, the parameter is passed verbatim to the generated
code, for properties, a getter and setter Exports are generated based on the base
declaration (see the section on the BindAttribute for information on how to alter the
behavior of the binding tool).

Syntax:

public enum ArgumentSemantic {


None, Assign, Copy, Retain.
}

[AttributeUsage (AttributeTargets.Method |
AttributeTargets.Constructor | AttributeTargets.Property)]
public class ExportAttribute : Attribute {
public ExportAttribute();
public ExportAttribute (string selector);
public ExportAttribute (string selector, ArgumentSemantic
semantic);
public string Selector { get; set; }
public ArgumentSemantic ArgumentSemantic { get; set; }
}

The selector and it represents the underlying Objective-C name of the method or property
that is being bound.

ExportAttribute.ArgumentSemantic

FieldAttribute

This attribute is used to expose a C global variable as a field that is loaded on demand and
exposed to C# code. Usually this is required to get the values of constants that are defined
in C or Objective-C and that could be either tokens used in some APIs, or whose values are
opaque and must be used as-is by user code.

Syntax:

public class FieldAttribute : Attribute {


public FieldAttribute (string symbolName);
public FieldAttribute (string symbolName, string libraryName);
public string SymbolName { get; set; }
public string LibraryName { get; set; }
}

The symbolName is the C symbol to link with. By default this will be loaded from a library
whose name is inferred from the namespace where the type is defined. If this is not the
library where the symbol is looked up, you should pass the libraryName parameter. If
you're linking a static library, use "__Internal" as the libraryName parameter.

The generated properties are always static.

Properties flagged with the Field attribute can be of type NSString, NSArray, nint,
double, nfloat or System.IntPtr.

Example:

[Static]
interface CameraEffects {
[Field ("kCameraEffectsZoomFactorKey", "CameraLibrary")]
NSString ZoomFactorKey { get; }
}

InternalAttribute

The Internal attribute can be applied to methods or properties and it has the effect of
flagging the generated code with the "internal" C# keyword making the code only accessible
to code in the generated assembly. This is typically used to hide APIs that are too low-level
or provide a suboptimal public API that you want to improve upon or for APIs that are not
supported by the generator and require some hand-coding.

When you design the binding, you would typically hide the method or property using this
attribute and provide a different name for the method or property, and then on your C#
complementary support file, you would add a strongly typed wrapper that exposes the
underlying functionality.

For example:

[Internal]
[Export ("setValue:forKey:");
void _SetValueForKey (NSObject value, NSObject key);

[Internal]
[Export ("getValueForKey:")]
NSObject _GetValueForKey (NSObject key);

Then, in your supporting file, you could have some code like this:
public NSObject this [NSObject idx] {
get {
return _GetValueForKey (idx);
}
set {
_SetValueForKey (value, idx);
}
}

IsThreadStaticAttribute

This attribute flags the backing field for a property to be annotated with the .NET
[ThreadStatic] attribute. This is useful if the field is a thread static variable.

MarshalNativeExceptions (Xamarin.iOS 6.0.6)

This attribute will make a method support native (ObjectiveC) exceptions. Instead of calling
objc_msgSend directly, the invocation will go through a custom trampoline which catches
ObjectiveC exceptions and marshals them into managed exceptions.

Currently only a few objc_msgSend signatures are supported (you will find out if a
signature isn't supported when native linking of an app that uses the binding fails with a
missing monotouch*objc_msgSend* symbol), but more can be added at request.

NewAttribute

This attribute is applied to methods and properties to have the generator generate the "new"
keyword in front of the declaration.

It is used to avoid compiler warnings when the same method or property name is introduced
in a subclass that already existed in a base class.

NotificationAttribute
You can apply this attribute to fields to have the generator produce a strongly typed helper
Notifications class.

This attribute can be used without arguments for notifications that carry no payload, or you
can specify a System.Type that references another interface in the API definition, typically
with the name ending with "EventArgs". The generator will turn the interface into a class that
subclasses EventArgs and will include all of the properties listed there. The [Export]
attribute should be used in the EventArgs class to list the name of the key used to look up
the Objective-C dictionary to fetch the value.

For example:

interface MyClass {
[Notification]
[Field ("MyClassDidStartNotification")]
NSString DidStartNotification { get; }
}

The above code will generate a nested class MyClass.Notifications with the following
methods:

public class MyClass {


[..]
public Notifications {
public static NSObject ObserveDidStart
(EventHandler<NSNotificationEventArgs> handler)
public static NSObject ObserveDidStart (NSObject
objectToObserve, EventHandler<NSNotificationEventArgs> handler)
}
}

Users of your code can then easily subscribe to notifications posted to the NSDefaultCenter
by using code like this:

var token = MyClass.Notifications.ObserverDidStart ((notification)


=> {
Console.WriteLine ("Observed the 'DidStart' event!");
});

Or to set a specific object to observe. If you pass null to objectToObserve this method
will behave just like its other peer.

var token = MyClass.Notifications.ObserverDidStart (objectToObserve,


(notification) => {
Console.WriteLine ("Observed the 'DidStart' event on
objectToObserve!");
});

The returned value from ObserveDidStart can be used to easily stop receiving
notifications, like this:

token.Dispose ();

Or you can call NSNotification.DefaultCenter.RemoveObserver and pass the token. If your


notification contains parameters, you should specify a helper EventArgs interface, like this:

interface MyClass {
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}

// The helper EventArgs declaration


interface MyScreenChangedEventArgs {
[Export ("ScreenXKey")]
nint ScreenX { get; set; }

[Export ("ScreenYKey")]
nint ScreenY { get; set; }
[Export ("DidGoOffKey")]
[ProbePresence]
bool DidGoOff { get; }
}

The above will generate a MyScreenChangedEventArgs class with the ScreenX and
ScreenY properties that will fetch the data from the NSNotification.UserInfo dictionary using
the keys ScreenXKey and ScreenYKey respectively and apply the proper conversions. The
[ProbePresence] attribute is used for the generator to probe if the key is set in the
UserInfo, instead of trying to extract the value. This is used for cases where the presence
of the key is the value (typically for boolean values).

This allows you to write code like this:

var token = MyClass.NotificationsObserveScreenChanged


((notification) => {
Console.WriteLine ("The new screen dimensions are {0},{1}",
notification.ScreenX, notification.ScreenY);
});

In some cases, there is no constant associated with the value passed on the dictionary.
Apple sometimes uses public symbol constants and sometimes uses string constants. By
default the [Export] attribute in your provided EventArgs class will use the specified
name as a public symbol to be looked up at runtime. If this is not the case, and instead it is
supposed to be looked up as a string constant then pass the ArgumentSemantic.Assign
value to the Export attribute.

New in Xamarin.iOS 8.4

Sometimes, notifications will begin life without any arguments, so the use of
[Notification] without arguments is acceptable. But sometimes, parameters to the
notification will be introduced. To support this scenario, the attribute can be applied more
than once.

If you are developing a binding, and you want to avoid breaking existing user code, you
would turn an existing notification from:

interface MyClass {
[Notification]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}

Into a version that lists the notification attribute twice, like this:

interface MyClass {
[Notification]
[Notification (typeof (MyScreenChangedEventArgs)]
[Field ("MyClassScreenChangedNotification")]
NSString ScreenChangedNotification { get; }
}

NullAllowedAttribute

When this is applied to a property it flags the property as allowing the value null to be
assigned to it. This is only valid for reference types.

When this is applied to a parameter in a method signature it indicates that the specified
parameter can be null and that no check should be performed for passing null values.

If the reference type does not have this attribute, the binding tool will generate a check for
the value being assigned before passing it to Objective-C and will generate a check that will
throw an ArgumentNullException if the value assigned is null.

For example:

// In properties

[NullAllowed]
UIImage IconFile { get; set; }
// In methods
void SetImage ([NullAllowed] UIImage image, State forState);

OverrideAttribute

Use this attribute to instruct the binding generator that the binding for this particular method
should be flagged with an "override" keyword.

PreSnippetAttribute

You can use this attribute to inject some code to be inserted after the input parameters have
been validated, but before the code calls into Objective-C

Example:

[Export ("demo")]
[PreSnippet ("var old = ViewController;")]
void Demo ();

PrologueSnippetAttribute

You can use this attribute to inject some code to be inserted before any of the parameters
are validated in the generated method.

Example:

[Export ("demo")]
[Prologue ("Trace.Entry ();")]
void Demo ();

PostGetAttribute

Instructs the binding generator to invoke the specified property from this class to fetch a
value from it.
This property is typically used to refresh the cache that points to reference objects that keep
the object graph referenced. Usually it shows up in code that has operations like
Add/Remove. This method is used so that after elements are added or removed that the
internal cache be updated to ensure that we are keeping managed references to objects that
are actually in use. This is possible because the binding tool generates a backing field for all
reference objects in a given binding.

Example:

[BaseType (typeof (NSObject))]


[Since (4,0)]
public interface NSOperation {
[Export ("addDependency:")][PostGet ("Dependencies")]
void AddDependency (NSOperation op);

[Export ("removeDependency:")][PostGet ("Dependencies")]


void RemoveDependency (NSOperation op);

[Export ("dependencies")]
NSOperation [] Dependencies { get; }
}

In this case, the Dependencies property will be invoked after adding or removing
dependencies from the NSOperation object, ensuring that we have a graph that represents
the actual loaded objects, preventing both memory leaks as well as memory corruption.

PostSnippetAttribute

You can use this attribute to inject some C# source code to be inserted after the code has
invoked the underlying Objective-C method

Example:

[Export ("demo")]
[PostSnippet ("if (old != null) old.DemoComplete ();")]
void Demo ();

ProxyAttribute

This attribute is applied to return values to flag them as being proxy objects. Some
Objective-C APIs return proxy objects that can not be differentiated from user bindings. The
effect of this attribute is to flag the object as being a DirectBinding object. For a scenario
in Xamarin.Mac, you can see the discussion on this bug.

RetainListAttribute

Instructs the generator to keep a managed reference to the parameter or remove an internal
reference to the parameter. This is used to keep objects referenced.

Syntax:

public class RetainListAttribute: Attribute {


public RetainListAttribute (bool doAdd, string listName);
}

If the value of "doAdd" is true, then the parameter is added to the __mt_{0}_var
List<NSObject>;. Where {0} is replaced with the given listName. You must declare
this backing field in your complementary partial class to the API.

For an example see foundation.cs and NSNotificationCenter.cs

ReleaseAttribute (Xamarin.iOS 6.0)

This can be applied to return types to indicate that the generator should call Release on the
object before returning it. This is only needed when a method gives you a retained object (as
opposed to an autoreleased object, which is the most common scenario)

Example:
[Export ("getAndRetainObject")]
[return: Release ()]
NSObject GetAndRetainObject ();

Additionally this attribute is propagated to the generated code, so that the Xamarin.iOS
runtime knows it must retain the object upon returning to Objective-C from such a function.

SealedAttribute

Instructs the generator to flag the generated method as sealed. If this attribute is not
specified, the default is to generate a virtual method (either a virtual method, an abstract
method or an override depending on how other attributes are used).

StaticAttribute

When the Static attribute is applied to a method or property this generates a static method
or property. If this attribute is not specified, then the generator produces an instance method
or property.

TransientAttribute

Use this attribute to flag properties whose values are transient, that is, objects that are
created temporarily by iOS but are not long lived. When this attribute is applied to a property,
the generator does not create a backing field for this property, which means that the
managed class does not keep a reference to the object.

WrapAttribute

In the design of the Xamarin.iOS/Xamarin.Mac bindings, the Wrap attribute is used to wrap a
weakly typed object with a strongly typed object. This comes into play mostly with Objective-
C "delegate" objects which are typically declared as being of type id or NSObject. The
convention used by Xamarin.iOS and Xamarin.Mac is to expose those delegates or data
sources as being of type NSObject and are named using the convention "Weak" + the
name being exposed. An "id delegate" property from Objective-C would be exposed as an
NSObject WeakDelegate { get; set; } property in the API contract file.

But typically the value that is assigned to this delegate is of a strong type, so we surface the
strong type and apply the Wrap attribute, this means that users can choose to use weak
types if they need some fine-control or if they need to resort to low-level tricks, or they can
use the strongly typed property for most of their work.

Example:

[BaseType (typeof (NSObject))]


interface Demo {
[Export ("delegate"), NullAllowed]
NSObject WeakDelegate { get; set; }

[Wrap ("WeakDelegate")]
DemoDelegate Delegate { get; set; }
}

[BaseType (typeof (NSObject))]


[Model][Protocol]
interface DemoDelegate {
[Export ("doDemo")]
void DoDemo ();
}

This is how the user would use the weakly-typed version of the Delegate:

// The weak case, user has to roll his own


class SomeObject : NSObject {
[Export ("doDemo")]
void CallbackForDoDemo () {}

}
var demo = new Demo ();
demo.WeakDelegate = new SomeObject ();

And this is how the user would use the strongly typed version, notice that the user takes
advantage of C#'s type system and is using the override keyword to declare his intent and
that he does not have to manually decorate the method with Export, since we did that work
in the binding for the user:

// This is the strong case,


class MyDelegate : DemoDelegate {
override void Demo DoDemo () {}
}

var strongDemo = new Demo ();


demo.Delegate = new MyDelegate ();

Another use of the Wrap attribute is to support strongly typed version of methods. For
example:

[BaseType (typeof (NSObject))]


interface XyzPanel {
[Export ("playback:withOptions:")]
void Playback (string fileName, [NullAllowed] NSDictionary
options);

[Wrap ("Playback (fileName, options == null ? null :


options.Dictionary")]
void Playback (string fileName, XyzOptions options);
}

The members generated by [Wrap] are not virtual by default, if you need a virtual
member you can set to true the optional isVirtual parameter.
[BaseType (typeof (NSObject))]
interface FooExplorer {
[Export ("fooWithContentsOfURL:")]
void FromUrl (NSUrl url);

[Wrap ("FromUrl (NSUrl.FromString (url))", isVirtual: true)]


void FromUrl (string url);
}

Parameter Attributes
This section describes the attributes that you can apply to the parameters in a method
definition as well as the NullAttribute that applies to a property as a whole.

BlockCallback

This attribute is applied to parameter types in C# delegate declarations to notify the binder
that the parameter in question conforms to the Objective-C block calling convention and
should marshal it in this way.

This is typically used for callbacks that are defined like this in Objective-C:

typedef returnType (^SomeTypeDefinition) (int parameter1, NSString


*parameter2);

See also: CCallback.

CCallback

This attribute is applied to parameter types in C# delegate declarations to notify the binder
that the parameter in question conforms to the C ABI function pointer calling convention and
should marshal it in this way.

This is typically used for callbacks that are defined like this in Objective-C:
typedef returnType (*SomeTypeDefinition) (int parameter1, NSString
*parameter2);

See also: BlockCallback.

Params

You can use the [Params] attribute on the last array parameter of a method definition to
have the generator inject a "params" in the definition. This allows the binding to easily allow
for optional parameters.

For example, the following definition:

[Export ("loadFiles:")]
void LoadFiles ([Params]NSUrl [] files);

Allows the following code to be written:

foo.LoadFiles (new NSUrl (url));


foo.LoadFiles (new NSUrl (url1), new NSUrl (url2), new NSUrl
(url3));

This has the added advantage that it does not require users to create an array purely for
passing elements.

PlainString

You can use the [PlainString] attribute in front of string parameters to instruct the
binding generator to pass the string as a C string, instead of passing the parameter as an
NSString.

Most Objective-C APIs consume NSString parameters, but a handful of APIs expose a
char * API for passing strings, instead of the NSString variation. Use [PlainString] in
those cases.
For example, the following Objective-C declarations:

- (void) setText: (NSString *) theText;


- (void) logMessage: (char *) message;

Should be bound like this:

[Export ("setText:")]
void SetText (string theText);

[Export ("logMessage:")]
void LogMessage ([PlainString] string theText);

RetainAttribute

Instructs the generator to keep a reference to the specified parameter. The generator will
provide the backing store for this field or you can specify a name (the WrapName) to store
the value at. This is useful to hold a reference to a managed object that is passed as a
parameter to Objective-C and when you know that Objective-C will only keep this copy of the
object. For instance, an API like SetDisplay (SomeObject) would use this attribute as it
is likely that the SetDisplay could only display one object at a time. If you need to keep track
of more than one object (for example, for a Stack-like API) you would use the RetainList
attribute.

Syntax:

public class RetainAttribute {


public RetainAttribute ();
public RetainAttribute (string wrapName);
public string WrapName { get; }
}

RetainListAttribute

Instructs the generator to keep a managed reference to the parameter or remove an internal
reference to the parameter. This is used to keep objects referenced.

Syntax:

public class RetainListAttribute: Attribute {


public RetainListAttribute (bool doAdd, string listName);
}

If the value of "doAdd" is true, then the parameter is added to the __mt_{0}_var
List<NSObject>. Where {0} is replaced with the given listName. You must declare this
backing field in your complementary partial class to the API.

For an example see foundation.cs and NSNotificationCenter.cs

TransientAttribute

This attribute is applied to parameters and is only used when transitioning from Objective-C
to C#. During those transitions the various Objective-C NSObjects parameters are wrapped
into a managed representation of the object.

The runtime will take a reference to the native object and keep the reference until the last
managed reference to the object is gone, and the GC has a chance to run.

In a few cases, it is important for the C# runtime to not keep a reference to the native object.
This sometimes happens when the underlying native code has attached a special behavior
to the lifecycle of the parameter. For example: the destructor for the parameter will perform
some cleanup action, or dispose some precious resource.

This attribute informs the runtime that you desire the object to be disposed if possible when
returning back to Objective-C from your overwritten method.

The rule is simple: if the runtime had to create a new managed representation from the
native object, then at the end of the function, the retain count for the native object will be
dropped, and the Handle property of the managed object will be cleared. This means that if
you kept a reference to the managed object, that reference will become useless (invoking
methods on it will throw an exception).
If the object passed was not created, or if there was already an outstanding managed
representation of the object, the forced dispose does not take place.

Property Attributes

NotImplementedAttribute

This attribute is used to support an Objective-C idiom where a property with a getter is
introduced in a base class, and a mutable subclass introduces a setter.

Since C# does not support this model, the base class needs to have both the setter and the
getter, and a subclass can use the OverrideAttribute.

This attribute is only used in property setters, and is used to support the mutable idiom in
Objective-C.

Example:

[BaseType (typeof (NSObject))]


interface MyString {
[Export ("initWithValue:")]
IntPtr Constructor (string value);

[Export ("value")]
string Value {
get;

[NotImplemented ("Not available on MyString, use MyMutableString


to set")]
set;
}
}
[BaseType (typeof (MyString))]
interface MyMutableString {
[Export ("value")]
[Override]
string Value { get; set; }
}

Enum Attributes
Mapping NSString constants to enum values is a easy way to create better .NET API. It:

allows code completion to be more useful, by showing only the correct values for the
API;
adds type safety, you cannot use another NSString constant in a incorrect context;
and
allows to hide some constants, making code completion show shorter API list without
losing functionality.

Example:

enum NSRunLoopMode {

[DefaultEnumValue]
[Field ("NSDefaultRunLoopMode")]
Default,

[Field ("NSRunLoopCommonModes")]
Common,

[Field (null)]
Other = 1000
}
From the above binding definition the generator will create the enum itself and will also
create a *Extensions static type that includes two-ways conversion methods between the
enum values and the NSString constants. This means the constants remains available to
developers even if they are not part of the API.

Examples:

// using the NSString constant in a different API / framework / 3rd


party code
CallApiRequiringAnNSString (NSRunLoopMode.Default.GetConstant ());

// converting the constants from a different API / framework / 3rd


party code
var constant = CallApiReturningAnNSString ();
// back into an enum value
CallApiWithEnum (NSRunLoopModeExtensions.GetValue (constant));

DefaultEnumValueAttribute

You can decorate one enum value with this attribute. This will become the constant being
returned if the enum value is not known.

From the example above:

var x = (NSRunLoopMode) 99;


Call (x.GetConstant ()); // NSDefaultRunLoopMode will be used

If no enum value is decorated then a NotSupportedException will be thrown.

ErrorDomainAttribute

Error codes are bound as an enum values. There's generally an error domain for them and
it's not always easy to find which one applies (or if one even exists).

You can use this attribute to associate the error domain with the enum itself.
Example:

[Native]
[ErrorDomain ("AVKitErrorDomain")]
public enum AVKitError : nint {
None = 0,
Unknown = -1000,
PictureInPictureStartFailed = -1001
}

You can then call the extension method GetDomain to get the domain constant of any error.

FieldAttribute

This is the same [Field] attribute used for constants inside type. It can also be used inside
enums to map a value with a specific constant.

A null value can be used to specify which enum value should be returned if a null
NSString constant is specified.

From the example above:

var constant = NSRunLoopMode.NewInWatchOS3; // will be null in


watchOS 2.x
Call (NSRunLoopModeExtensions.GetValue (constant)); // will return
1000

If no null value is present then an ArgumentNullException will be thrown.

Global Attributes
Global attributes are either applied using the [assembly:] attribute modifier like the
LinkWithAttribute or can be used anywhere, like the Lion and Since attributes.
LinkWithAttribute

This is an assembly-level attribute which allows developers to specify the linking flags
required to reuse a bound library without forcing the consumer of the library to manually
configure the gcc_flags and extra mtouch arguments passed to a library.

Syntax:

// In properties
[Flags]
public enum LinkTarget {
Simulator = 1,
ArmV6 = 2,
ArmV7 = 4,
Thumb = 8,
}

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true)]
public class LinkWithAttribute : Attribute {
public LinkWithAttribute ();
public LinkWithAttribute (string libraryName);
public LinkWithAttribute (string libraryName, LinkTarget
target);
public LinkWithAttribute (string libraryName, LinkTarget target,
string linkerFlags);
public bool ForceLoad { get; set; }
public string Frameworks { get; set; }
public bool IsCxx { get; set; }
public string LibraryName { get; }
public string LinkerFlags { get; set; }
public LinkTarget LinkTarget { get; set; }
public bool NeedsGccExceptionHandling { get; set; }
public bool SmartLink { get; set; }
public string WeakFrameworks { get; set; }
}

This attribute is applied at the assembly level, for example, this is what the CorePlot bindings
use:

[assembly: LinkWith ("libCorePlot-CocoaTouch.a", LinkTarget.ArmV7 |


LinkTarget.ArmV7s | LinkTarget.Simulator, Frameworks = "CoreGraphics
QuartzCore", ForceLoad = true)]

When you use the LinkWith attribute, the specified libraryName is embedded into the
resulting assembly, allowing users to ship a single DLL that contains both the unmanaged
dependencies as well as the command line flags necessary to properly consume the library
from Xamarin.iOS.

It's also possible to not provide a libraryName, in which case the LinkWith attribute can
be used to only specify additional linker flags:

[assembly: LinkWith (LinkerFlags = "-lsqlite3")]

LinkWithAttribute Constructors

These constructors allow you to specify the library to link with and embed into your resulting
assembly, the supported targets that the library supports and any optional library flags that
are necessary to link with the library.

Note that the LinkTarget argument is inferred by Xamarin.iOS and does not need to be set.

Examples:

// Specify additional linker:


[assembly: LinkWith (LinkerFlags = "-sqlite3")]

// Specify library name for the constructor:


[assembly: LinkWith ("libDemo.a");
// Specify library name, and link target for the constructor:
[assembly: LinkWith ("libDemo.a", LinkTarget.Thumb |
LinkTarget.Simulator);

// Specify only the library name, link target and linker flags for
the constructor:
[assembly: LinkWith ("libDemo.a", LinkTarget.Thumb |
LinkTarget.Simulator, SmartLink = true, ForceLoad = true, IsCxx =
true);

LinkWithAttribute.ForceLoad

The ForceLoad property is used to decide whether or not the -force_load link flag is
used for linking the native library. For now, this should always be true.

LinkWithAttribute.Frameworks

If the library being bound has a hard requirement on any frameworks (other than
Foundation and UIKit), you should set the Frameworks property to a string containing a
space-delimited list of the required platform frameworks. For example, if you are binding a
library that requires CoreGraphics and CoreText, you would set the Frameworks
property to "CoreGraphics CoreText".

LinkWithAttribute.IsCxx

Set this property to true if the resulting executable needs to be compiled using a C++
compiler instead of the default, which is a C compiler. Use this if the library that you are
binding was written in C++.

LinkWithAttribute.LibraryName

The name of the unmanaged library to bundle. This is a file with the extension ".a" and it can
contain object code for multiple platforms (for example, ARM and x86 for the simulator).

Earlier versions of Xamarin.iOS checked the LinkTarget property to determine the


platform your library supported, but this is now auto-detected, and the LinkTarget property
is ignored.

LinkWithAttribute.LinkerFlags

The LinkerFlags string provides a way for binding authors to specify any additional linker
flags needed when linking the native library into the application.

For example, if the native library requires libxml2 and zlib, you would set the LinkerFlags
string to "-lxml2 -lz".

LinkWithAttribute.LinkTarget

Earlier versions of Xamarin.iOS checked the LinkTarget property to determine the


platform your library supported, but this is now auto-detected, and the LinkTarget property
is ignored.

LinkWithAttribute.NeedsGccExceptionHandling

Set this property to true if the library that you are linking requires the GCC Exception
Handling library (gcc_eh)

LinkWithAttribute.SmartLink

The SmartLink property should be set to true to let Xamarin.iOS determine whether
ForceLoad is required or not.

LinkWithAttribute.WeakFrameworks

The WeakFrameworks property works the same way as the Frameworks property, except
that at link-time, the -weak_framework specifier is passed to gcc for each of the listed
frameworks.

WeakFrameworks makes it possible for libraries and applications to weakly link against
platform frameworks so that they can optionally use them if they are available but do not
take a hard dependency on them which is useful if your library is meant to add extra features
on newer versions of iOS. For more information on weak linking, see Apple's documentation
on Weak Linking.

Good candidates for weak linking would be Frameworks like Accounts, CoreBluetooth,
CoreImage, GLKit, NewsstandKit and Twitter since they are only available in iOS 5.

SinceAttribute (iOS) and LionAttribute (MacOS X)

You use the Since Attribute to flag APIs as having being introduced at a certain point in
time. The attribute should only be used to flag types and methods that could cause a runtime
problem if the underlying class, method or property is not available.

Syntax:

public SinceAttribute : Attribute {


public SinceAttribute (byte major, byte minor);
public byte Major, Minor;
}

It should in general not be applied to enumerations, constraints or new structures as those


would not cause a runtime error if they are executed on a device with an older version of the
operating system.

Example when applied to a type:

// Type introduced with iOS 4.2


[Since (4,2)]
[BaseType (typeof (UIPrintFormatter))]
interface UIViewPrintFormatter {
[Export ("view")]
UIView View { get; }
}

Example when applied to a new member:


[BaseType (typeof (UIViewController))]
public interface UITableViewController {
[Export ("tableView", ArgumentSemantic.Retain)]
UITableView TableView { get; set; }

[Since (3,2)]
[Export ("clearsSelectionOnViewWillAppear")]
bool ClearsSelectionOnViewWillAppear { get; set; }

The Lion attribute is applied in the same way but for types introduced with Lion. The reason
to use Lion versus the more specific version number that is used in iOS is that iOS is
revised very often, while major OS X releases happen rarely and it is easier to remember the
operating system by their codename than by their version number

AdviceAttribute

Use this attribute to give developers a hint about other APIs that might be more convenient
for them to use. For example, if you provide a strongly typed version of an API, you could
use this attribute on the weakly typed attribute to direct the developer to the better API.

The information from this attribute is shown in the documentation and tools can be
developed to give user suggestions on how to improve his code.

ZeroCopyStringsAttribute

Only available in Xamarin.iOS 5.4 and newer.

This attribute instructs the generator that the binding for this specific library (if applied with
[assembly:]) or type should use the fast zero-copy string marshaling. This attribute is
equivalent to passing the command line option --zero-copy to the generator.

When using zero-copy for strings, the generator effectively uses the same C# string as the
string that Objective-C consumes without incurring the creation of a new NSString object
and avoiding copying the data from the C# strings to the Objective-C string. The only
drawback of using Zero Copy strings is that you must ensure that any string property that
you wrap that happens to be flagged as "retain" or "copy" has the DisableZeroCopy
attribute set. This is require because the handle for zero-copy strings is allocated on the
stack and is invalid upon the function return.

Example:

[ZeroCopyStrings]
[BaseType (typeof (NSObject))]
interface MyBinding {
[Export ("name")]
string Name { get; set; }

[Export ("domain"), NullAllowed]


string Domain { get; set; }

[DisablZeroCopy]
[Export ("someRetainedNSString")]
string RetainedProperty { get; set; }
}

You can also apply the attribute at the assembly level, and it will apply to all the types of the
assembly:

[assembly:ZeroCopyStrings]

Strongly Typed Dictionaries


With Xamarin.iOS 8.0 we introduced support for easily creating Strongly Typed classes that
wrap NSDictionaries.

While it has always been possible to use the DictionaryContainer data type together with a
manual API, it is now a lot simpler to do this. For more information, see Surfacing Strong
Types.
StrongDictionary

When this attribute is applied to an interface, the generator will produce a class with the
same name as the interface that derives from DictionaryContainer and turns each property
defined in the interface into a strongly typed getter and setter for the dictionary.

This automatically generates a class that can be instantiated from an existing


NSDictionary or that has been created new.

This attribute takes one parameter, the name of the class containing the keys that are used
to access the elements on the dictionary. By default each property in the interface with the
attribute will lookup a member in the specified type for a name with the suffix "Key".

For example:

[StrongDictionary ("MyOptionKeys")]
interface MyOption {
string Name { get; set; }
nint Age { get; set; }
}

[Static]
interface MyOptionKeys {
// In Objective-C this is "NSString *MYOptionNameKey;"
[Field ("MYOptionNameKey")]
NSString NameKey { get; }

// In Objective-C this is "NSString *MYOptionAgeKey;"


[Field ("MYOptionAgeKey")]
NSString AgeKey { get; }
}

In the above case, the MyOption class will produce a string property for Name that will use
the MyOptionKeys.NameKey as the key into the dictionary to retrieve a string. And will use
the MyOptionKeys.AgeKey as the key into the dictionary to retrieve an NSNumber which
contains an int.

If you want to use a different key, you can use the export attribute on the property, for
example:

[StrongDictionary ("MyColoringKeys")]
interface MyColoringOptions {
[Export ("TheName")] // Override the default which would be
NameKey
string Name { get; set; }

[Export ("TheAge")] // Override the default which would be


AgeKey
nint Age { get; set; }
}

[Static]
interface MyColoringKeys {
// In Objective-C this is "NSString *MYColoringNameKey"
[Field ("MYColoringNameKey")]
NSString TheName { get; }

// In Objective-C this is "NSString *MYColoringAgeKey"


[Field ("MYColoringAgeKey")]
NSString TheAge { get; }
}

Strong Dictionary Types

The following data types are supported in the StrongDictionary definition:

C# Interface Type NSDictionary Storage Type


bool Boolean stored in an NSNumber

Enumeration values integer stored in an NSNumber

int 32-bit integer stored in an NSNumber

32-bit unsigned integer stored in an


uint
NSNumber

nint NSInteger stored in an NSNumber

nuint NSUInteger stored in an NSNumber

long 64-bit integer stored in an NSNumber

float 32-bit integer stored as an NSNumber

double 64-bit integer stored as an NSNumber

NSObject and
NSObject
subclasses

NSDictionary NSDictionary

string NSString

NSString NSString

C# Array of NSObject NSArray

C# Array of NSArray containing NSNumbers with the


enumerations value
Objective Sharpie

Automated Binding Definitions using Objective Sharpie

Overview & History


Getting Started
Tools & Commands
Features
Examples
Complete Walkthrough
Release History

Overview
Objective Sharpie is a command line tool to help bootstrap the first pass of a binding. It
works by parsing the header files of a native library to map the public API into the binding
definition (a process that previously was manually done).

Objective Sharpie uses Clang parse header files, so the binding is as exact and thorough as
possible. This can greatly reduce the time and effort it takes to produce a quality binding.

⚠️ WARNING: Objective Sharpie is a tool for experienced Xamarin developers


with advanced knowledge of Objective-C (and by extension, C). Before
attempting to bind an Objective-C library you should have solid knowledge of
how to build the native library on the command line (and a good understanding
of how the native library works).

History
We have been evolving and using the Objective Sharpie internally at Xamarin for the last
three years. As a testament to the power of Objective Sharpie, APIs introduced in
Xamarin.iOS and Xamarin.Mac since iOS 8, Mac OS X 10.10, and watchOS 2.0 were
bootstrapped entirely with Objective Sharpie. Xamarin relies heavily on Objective Sharpie
internally for building its own products.

However, Objective Sharpie is a very advanced tool that requires advanced knowledge of
Objective-C and C, how to use the clang compiler on the command line, and generally how
native libraries are put together. Because of this high bar, we felt that having a GUI wizard
sets the wrong expectations, and as such, Objective Sharpie is currently only available as a
command line tool.
Getting Started
⚠️ WARNING: Objective Sharpie is a tool for experienced Xamarin developers
with advanced knowledge of Objective-C (and by extension, C). Before
attempting to bind an Objective-C library you should have solid knowledge of
how to build the native library on the command line (and a good understanding
of how the native library works).

Installing Objective Sharpie


Objective Sharpie is currently a standalone command line tool for Mac OS X 10.10 and
newer, and is not a fully supported Xamarin product. It should only be used by advanced
developers to assist in creating a binding project to a 3rd party Objective-C library.

Objective Sharpie can be downloaded as a standard OS X package installer. Run the


installer and follow all of the on-screen prompts from the installation wizard:

Current Version: 3.4


Download Latest Release
Forum Announcement

️ Tip: use the sharpie update command to update to the latest version.

Basic Walkthrough
Objective Sharpie is a command line tool provided by Xamarin that assists in creating the
definitions required to bind a 3rd party Objective-C library to C#. Even when using Objective
Sharpie, the developer will need to modify the generated files after Objective Sharpie
finishes to address any issues that could not be automatically handled by the tool.

Where possible, Objective Sharpie will annotate APIs with which it has some doubt on how
to properly bind (many constructs in the native code are ambiguous). These annotations will
appear as [Verify] attributes.

The output of Objective Sharpie is a pair of files - ApiDefinition.cs and


StructsAndEnums.cs - that can be used to create a binding project which compiles into a
library you can use in Xamarin apps.

⚠️ Objective Sharpie comes with one major rule for proper usage: you must
absolutely pass it the correct clang compiler command line arguments in order to
ensure proper parsing. This is because the Objective Sharpie parsing phase is
simply a tool implemented against the clang libtooling API.

This means that Objective Sharpie has the full power of Clang (the C/Objective-C/C++
compiler that actually compiles the native library you would bind) and all of its internal
knowledge of the header files for binding. Instead of translating the parsed AST to object
code, Objective Sharpie translates the AST to a C# binding "scaffold" suitable for input to the
bmac and btouch Xamarin binding tools.

If Objective Sharpie errors out during parsing, it means that clang errored out during its
parsing phase trying to construct the AST, and you need to figure out why.

NEW! version 3.0 attempts address some of this complexity by supporting Xcode projects
directly. If a native library has a valid Xcode project, Objective Sharpie can evaluate the
project for a specified target and configuration to deduce the necessary input header files
and compiler flags.

If no Xcode project is available, you will need to be more familiar with the project by
deducing the correct input header files, header file search paths, and other necessary
compiler flags. It is important to realize that the compiler flags used to build the native library
are the same that must be passed to Objective Sharpie. This is a more manual process, and
one that does require a bit of familiarity with compiling native code on the command line with
the Clang toolchain.

NEW! version 3.0 also introduces a tool for easily binding CocoaPods via the sharpie pod
command. If the library you're interested in is available as a CocoaPod, we recommend you
start by attempting to bind the CocoaPod with Objective Sharpie (versus attempting to bind
against the source directly).
Tools & Commands
Once Objective Sharpie is successfully installed, open a terminal and familiarize yourself
with the commands Objective Sharpie has to offer:

$ sharpie -help
usage: sharpie [OPTIONS] TOOL [TOOL_OPTIONS]

Options:
-h, -help Show detailed help
-v, -version Show version information

Telemetry Options:
-tlm-about Show a detailed overview of what usage
and binding
information will be submitted to
Xamarin by
default when using Objective Sharpie.
-tlm-do-not-submit Do not submit any usage or binding
information to
Xamarin. Run 'sharpie -tml-about' for
more
information.
-tlm-do-not-identify Do not submit Xamarin account information
when
submitting usage or binding information
to Xamarin
for analysis. Binding attempts and
usage data will
be submitted anonymously if this option
is
specified.

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

Objective Sharpie provides the following tools:

Tool Description

Provides information about the current Xcode installation and the versions of iOS
xcode and Mac SDKs that are available. We will be using this information later when we
generate our bindings.

Searches for, configures, installs (in a local directory), and binds Objective-C
CocoaPod libraries available from the master Spec repository. This tool evaluates
pod
the installed CocoaPod to automatically deduce the correct input to pass to the
bind tool below. New in 3.0!

Parses the header files (*.h) in the Objective-C library into the initial
bind
ApiDefinition.cs and StructsAndEnums.cs files.

Checks for newer versions of Objective Sharpie and downloads and launches the
update
installer if one is available.

verify-
Shows detailed information about [Verify] attributes.
docs

docs Navigates to this document in your default web browser.


To get help on a specific Objective Sharpie tool, enter the name of the tool and the -help
option. For example, sharpie xcode -help returns the following output:

$ 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.

Before we can start the binding process, we need to get information about our current
installed SDKs by entering the following command into the Terminal sharpie xcode -
sdks. Your output may differ depending on which version(s) of Xcode you have installed.
Objective Sharpie looks for SDKs installed in any Xcode*.app under the /Applications
directory:

$ sharpie xcode -sdks


sdk: appletvos9.0 arch: arm64
sdk: iphoneos9.1 arch: arm64 armv7
sdk: iphoneos9.0 arch: arm64 armv7
sdk: iphoneos8.4 arch: arm64 armv7
sdk: macosx10.11 arch: x86_64 i386
sdk: macosx10.10 arch: x86_64 i386
sdk: watchos2.0 arch: armv7

From the above, we can see that we have the iphoneos9.1 SDK installed on our machine
and it has arm64 architecture support. We will be using this value for all the samples in this
section. With this information in place, we are ready to parse an Objective-C library header
files into the initial ApiDefinition.cs and StructsAndEnums.cs for the Binding
project.
Objective Sharpie Features
Read through these pages to better understand Objective Sharpie's features:

ApiDefinitions.cs & StructsAndEnums.cs

These two files are emitted by Objective Sharpie, to be included in your binding project.
Learn more about them here.

Native Frameworks

Some libraries are distributed as frameworks rather than as source. Objective Sharpie lets
you use these libraries with the -framework option.

Verify

Objective Sharpie add Verify attributes to signal that you need to manually inspect and
update the generated binding.
ApiDefinitions & StructsAndEnums Files
When Objective Sharpie has run successfully, it generates Binding/ApiDefinitions.cs and
Binding/StructsAndEnums.cs files. These two files are added to a binding project in Visual Studio for
Mac or passed directly to the btouch or bmac tools to produce the final binding.

In some cases these generated files might be all you need, however more often the developer will need to
manually modify these generated files to fix any issues that could not be automatically handled by the tool
(such as those flagged with a Verify attribute).

Some of the next steps include:

Adjusting Names: Sometimes you will want to adjust the names of methods and classes to match
the .NET Framework Design Guidelines.
Methods or Properties: The heuristics used by Objective Sharpie sometimes will pick a method to
be turned into a property. At this point, you could decide whether this is the intended behavior or not.
Hook up Events: You could link your classes with your delegate classes and automatically generate
events for those.
Hook up Notifications: It is not possible to extract the API contract of notifications from the pure
header files, this will require a trip to the API documentation. If you want strongly typed notifications,
you will need to update the result.
API Curation: At this point, you might choose to provide extra constructors, add methods (to allow
for C# initialize-on-construction syntax), operator overloading and implement your own interfaces on
the extra definitions file.

See the binding an API description to see how these files fit into the binding process, as shown in the
diagram below:
Refer to the binding Types reference for more information on the contents of these files.
Binding Native Frameworks
Sometimes a native library is distributed as a framework. Objective Sharpie provides a
convenience feature for binding properly defined frameworks through the -framework option.

For example, binding the Adobe Creative SDK Framework for iOS is straightforward:

$ sharpie bind \
-framework AdobeCreativeSDKFoundation.framework \
-sdk iphoneos8.1

In some cases, a framework will specify an Info.plist which indicates against which SDK the
framework should be compiled. If this information exists and no explicit -sdk option is passed,
Objective Sharpie will infer it from the framework's Info.plist (either the DTSDKName key or a
combination of the DTPlatformName and DTPlatformVersion keys).

The -framework option does not allow explicit header files to be passed. The umbrella header file
is chosen by convention based on the framework name. If an umbrella header cannot be found,
Objective Sharpie will not attempt to bind the framework and you must manually perform the
binding by providing the correct umbrella header file(s) to parse, along with any framework
arguments for clang (such as the -F framework search path option).

Under the hood, specifying -framework is just a shortcut. The following bind arguments are
identical to the -framework shorthand above. Of special importance is the -F . framework
search path provided to clang (note the space and period, which are required as part of the
command).

$ sharpie bind \
-sdk iphoneos8.1 \

AdobeCreativeSDKFoundation.framework/Headers/AdobeCreativeSDKFoundation.h
\
-scope AdobeCreativeSDKFoundation.framework/Headers \
-c -F .
Verify Attributes
You will often find that bindings produced by Objective Sharpie will be annotated with the
[Verify] attribute. These attributes indicate that you should verify that Objective Sharpie
did the correct thing by comparing the binding with the original C/Objective-C declaration
(which will be provided in a comment above the bound declaration).

Verification is recommended for all bound declarations, but is most likely required for
declarations annotated with the [Verify] attribute. This is because in many situations,
there is not enough metadata in the original native source code to infer how to best produce
a binding. You may need to reference documentation or code comments inside the header
files to make the best binding decision.

Once you have verified that the binding is correct or have fixed it to be correct, remove the
[Verify] attribute from the binding.

⚠️ [Verify] attributes intentionally cause C# compilation errors so that you


are forced to verify the binding. You should remove the [Verify] attribute
when you have reviewed (and possibly corrected) the code.

Verify Hints Reference

The hint argument supplied to the attribute can be cross referenced with documentation
below. Documentation for any produced [Verify] attributes will be provided on the
console as well after the binding has completed.

Verify Hint Description

The name of this declaration was inferred by common


convention from the immediately preceeding typedef in
InferredFromPreceedingTypedef
the original native source code. Verify that the inferred
name is correct as this convention is ambiguous.

There's no fool-proof way to determine with which


Verify Hint Description

Objective-C interface an extern variable declaration may


be associated. Instances of these are bound as [Field]
ConstantsInterfaceAssociation
properties in a partial interface into a near-by concrete
interface to produce a more intuitive API, possibly
eliminating the 'Constants' interface altogether.

An Objective-C method was bound as a C# property due


to convention such as taking no parameters and returning
a value (non-void return). Often methods like these should
MethodToProperty
be bound as properties to surface a nicer API, but
sometimes false-positives can occur and the binding
should actually be a method.

A native NSArray* was bound as NSObject[]. It might


be possible to more strongly type the array in the binding
based on expectations set through API documentation
StronglyTypedNSArray (e.g. comments in the header file) or by examining the
array contents through testing. For example, an NSArray*
containing only NSNumber* instancescan be bound as
NSNumber[] instead of NSObject[].

You can also quickly receive documentation for a hint using the sharpie verify-docs
tool, for example:

sharpie verify-docs InferredFromPreceedingTypedef

You might also like