Neues Referenzzählsystem in Xamarin.iOS

Xamarin.iOS 9.2.1 hat standardmäßig das erweiterte Verweiszählsystem für alle Anwendungen eingeführt. Es kann verwendet werden, um viele Speicherprobleme zu beseitigen, die in früheren Versionen von Xamarin.iOS schwer nachzuverfolgen und zu beheben waren.

Aktivieren des neuen Verweiszählsystems

Ab Xamarin 9.2.1 ist das neue Verweiszählungssystem standardmäßig für alle Anwendungen aktiviert.

Wenn Sie eine vorhandene Anwendung entwickeln, können Sie die CSPROJ-Datei überprüfen, um sicherzustellen, dass alle Vorkommen von MtouchUseRefCounting wie unten auf truefestgelegt sind:

<MtouchUseRefCounting>true</MtouchUseRefCounting>

Wenn sie auf false festgelegt ist, verwendet Ihre Anwendung die neuen Tools nicht.

Verwenden älterer Versionen von Xamarin

Xamarin.iOS 7.2.1 und höher bietet eine verbesserte Vorschau unseres neuen Referenzzählsystems.

Klassische API:

Aktivieren Sie zum Aktivieren dieses neuen Referenzzählsystems das Kontrollkästchen Verweiszählungserweiterung verwenden auf der Registerkarte Erweitert der iOS-Buildoptionen Ihres Projekts, wie unten gezeigt:

Aktivieren des neuen Referenzzählsystems

Beachten Sie, dass diese Optionen in neueren Versionen von Visual Studio für Mac entfernt wurden.

Einheitliche API:

Die neue Erweiterung für die Verweiszählung ist für die einheitliche API erforderlich und sollte standardmäßig aktiviert sein. In älteren Versionen Ihrer IDE wird dieser Wert möglicherweise nicht automatisch überprüft, und Sie müssen möglicherweise selbst eine Überprüfung durchführen.

Wichtig

Eine frühere Version dieses Features gibt es seit MonoTouch 5.2, war jedoch nur für sgen als experimentelle Vorschau verfügbar. Diese neue, erweiterte Version ist jetzt auch für den Boehm Garbage Collector verfügbar.

In der Vergangenheit gab es zwei Arten von Objekten, die von Xamarin.iOS verwaltet werden: solche, die nur ein Wrapper um ein natives Objekt (Peerobjekte) waren, und solche, die neue Funktionen erweitert oder integriert haben (abgeleitete Objekte), in der Regel durch Beibehaltung des zusätzlichen In-Memory-Zustands. Bisher war es möglich, dass wir ein Peerobjekt mit dem Status erweitern konnten (z. B. durch Hinzufügen eines C#-Ereignishandlers), aber dass wir das Objekt nicht referenziert und dann gesammelt haben. Dies kann später zu einem Absturz führen (z. B. wenn die Objective-C Runtime in das verwaltete Objekt zurückruft).

Das neue System aktualisiert automatisch Peerobjekte in Objekte, die von der Runtime verwaltet werden, wenn sie zusätzliche Informationen speichern.

Dadurch werden verschiedene Abstürze behoben, die in Situationen wie dieser aufgetreten sind:

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;
   }
}

Ohne die Erweiterung für die Verweisanzahl würde dieser Code abstürzen, da cell er sammelbar wird, und somit sein TouchDown Delegat, der in einen hängenden Zeiger übersetzt wird.

Die Erweiterung für die Verweisanzahl stellt sicher, dass das verwaltete Objekt aktiv bleibt und seine Auflistung verhindert wird, vorausgesetzt, das systemeigene Objekt wird von systemeigenem Code beibehalten.

Das neue System entfällt auch die Notwendigkeit für die meisten privaten Sicherungsfelder, die in Bindungen verwendet werden. Dies ist der Standardansatz, um instance am Leben zu halten. Der verwaltete Linker ist intelligent genug, um alle nicht benötigten Felder mithilfe der neuen Verweisanzahlerweiterung aus Anwendungen zu entfernen.

Dies bedeutet, dass jede verwaltete Objektinstanz weniger Arbeitsspeicher beansprucht als zuvor. Es löst auch ein verwandtes Problem, bei dem einige Unterstützungsfelder Verweise enthalten, die von der Objective-C Runtime nicht mehr benötigt wurden, was die Rückgewinnung von Arbeitsspeicher erschwert.