Nuevo sistema de recuento de referencias en Xamarin.iOS

Xamarin.iOS 9.2.1 introdujo el sistema mejorado de recuento de referencias en todas las aplicaciones de forma predeterminada. Se puede usar para eliminar muchos problemas de memoria difíciles de supervisar y corregir en versiones anteriores de Xamarin.iOS.

Habilitación del nuevo sistema de recuento de referencias

A partir de Xamarin 9.2.1, el nuevo sistema de recuento de referencias está habilitado para todas las aplicaciones de forma predeterminada.

Si está desarrollando una aplicación existente, puede comprobar el archivo .csproj para asegurarse de que todas las incidencias de MtouchUseRefCounting están establecidas en true, como se indica a continuación:

<MtouchUseRefCounting>true</MtouchUseRefCounting>

Si se establece en false, la aplicación no usará las nuevas herramientas.

Uso de versiones anteriores de Xamarin

Xamarin.iOS 7.2.1 y versiones posteriores presentan una vista previa mejorada de nuestro nuevo sistema de recuento de referencias.

Classic API:

Para habilitar este nuevo sistema de recuento de referencias, active la casilla Usar la extensión de recuento de referencias que se encuentra en la pestaña Avanzadas de las opciones de compilación de iOS del proyecto, como se muestra a continuación:

Enable the new Reference Counting System

Tenga en cuenta que estas opciones se han quitado en versiones más recientes de Visual Studio para Mac.

Unified API:

La nueva extensión de recuento de referencias es necesaria para Unified API y debe estar habilitada de forma predeterminada. Es posible que el valor de las versiones anteriores del IDE no esté activado automáticamente y es posible que tenga que realizar una comprobación usted mismo.

Importante

Lleva existiendo una versión anterior de esta característica desde MonoTouch 5.2, pero solo estaba disponible para sgen como una versión preliminar experimental. Esta nueva versión mejorada ahora también está disponible para el recolector de elementos no utilizados de Boehm.

Históricamente se habido dos tipos de objetos administrados por Xamarin.iOS: aquellos que eran simplemente un contenedor alrededor de un objeto nativo (objetos del mismo nivel) y los que extendieron o incorporaron nuevas funciones (objetos derivados), normalmente manteniendo un estado adicional en memoria. Anteriormente era posible que se pudiera aumentar un objeto del mismo nivel con estado (por ejemplo, agregando un controlador de eventos de C#), pero que dejáramos que el objeto quedase sin referencia y, a continuación, se recopilase. Esto podría provocar un bloqueo más adelante (por ejemplo, si el tiempo de ejecución de Objective-C llamase de nuevo al objeto administrado).

El nuevo sistema actualiza automáticamente los objetos del mismo nivel en objetos administrados por el tiempo de ejecución cuando almacenan información adicional.

Esto resuelve varios bloqueos que se produjeron en situaciones como esta:

class MyTableSource : UITableViewSource {
   public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) {
        var cell = tableView.DequeueReusableCell ("myId");
        if (cell != null)
                return cell;

        cell = new UITableViewCell (UITableViewCellStyle.Default, "myId");
        var txt = new UITextField ();
        txt.TouchDown += delegate { Console.WriteLine ("...."); };
        cell.ContentView.AddSubview (txt);
        return cell;
   }
}

Sin la extensión de recuento de referencias, este código se bloquearía porque cell se vuelve recopilable y, por tanto, su TouchDown delegado, que se traducirá en un puntero pendiente.

La extensión de recuento de referencias garantiza que el objeto administrado permanezca activo y evita su colección, siempre que el código nativo conserve el objeto nativo.

El nuevo sistema también elimina la necesidad de la mayoría de los campos de respaldo privados que se usan en los enlaces, que es el enfoque predeterminado para mantener activa la instancia. El enlazador administrado es lo suficientemente inteligente como para quitar todos los campos innecesarios de las aplicaciones mediante la nueva extensión de recuento de referencias.

Esto significa que cada instancia de objeto administrado consume menos memoria que antes. También resuelve un problema relacionado en el que algunos campos de respaldo contienen referencias que ya no eran necesarias para el tiempo de ejecución de Objective-C, lo que dificulta la recuperación de memoria.