Udostępnij za pośrednictwem


Nowy system zliczania odwołań w środowisku Xamarin.iOS

Program Xamarin.iOS 9.2.1 domyślnie wprowadził ulepszony system zliczania odwołań do wszystkich aplikacji. Może służyć do wyeliminowania wielu problemów z pamięcią, które były trudne do śledzenia i naprawiania we wcześniejszych wersjach platformy Xamarin.iOS.

Włączanie nowego systemu zliczania odwołań

Od wersji Xamarin 9.2.1 nowy system zliczania ref jest domyślnie włączony dla wszystkich aplikacji.

Jeśli tworzysz istniejącą aplikację, możesz sprawdzić plik csproj, aby upewnić się, że wszystkie wystąpienia programu MtouchUseRefCounting są ustawione na true, jak pokazano poniżej:

<MtouchUseRefCounting>true</MtouchUseRefCounting>

Jeśli jest ona ustawiona na false aplikację, nie będzie używać nowego narzędzia.

Korzystanie ze starszych wersji platformy Xamarin

Platforma Xamarin.iOS 7.2.1 lub nowsza oferuje ulepszoną wersję zapoznawcza nowego systemu zliczania odwołań.

Klasyczny interfejs API:

Aby włączyć ten nowy system zliczania odwołań, zaznacz pole wyboru Użyj rozszerzenia zliczania odwołań znalezione na karcie Zaawansowane opcji kompilacji systemu iOS projektu, jak pokazano poniżej:

Enable the new Reference Counting System

Należy pamiętać, że te opcje zostały usunięte w nowszych wersjach Visual Studio dla komputerów Mac.

Ujednolicony interfejs API:

Nowe rozszerzenie zliczania odwołań jest wymagane dla ujednoliconego interfejsu API i powinno być domyślnie włączone. Starsze wersje środowiska IDE mogą nie mieć tej wartości zaznaczonej automatycznie i może być konieczne samodzielne sprawdzenie.

Ważne

Wcześniejsza wersja tej funkcji była dostępna od wersji MonoTouch 5.2, ale była dostępna tylko dla oprogramowania sgen jako wersja zapoznawcza eksperymentalna. Ta nowa, ulepszona wersja jest teraz również dostępna dla modułu odśmiecającego pamięci Boehm .

Historycznie istnieją dwa rodzaje obiektów zarządzanych przez platformę Xamarin.iOS: te, które były jedynie otoką wokół obiektu natywnego (obiektów równorzędnych) i tych, które rozszerzają lub włączały nowe funkcje (obiekty pochodne) — zwykle przez zachowanie dodatkowego stanu w pamięci. Wcześniej można było rozszerzyć obiekt równorzędny o stan (na przykład dodając procedurę obsługi zdarzeń języka C#), ale pozwoliliśmy obiektowi przejść bez wnioskowania, a następnie zbierać je. Może to spowodować awarię później (np. jeśli Objective-C środowisko uruchomieniowe wywołane z powrotem do zarządzanego obiektu).

Nowy system automatycznie uaktualnia obiekty równorzędne do obiektów zarządzanych przez środowisko uruchomieniowe podczas przechowywania dodatkowych informacji.

Rozwiązuje to różne awarie, które wystąpiły w takich sytuacjach jak ten:

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

Bez rozszerzenia licznika odwołań ten kod ulega awarii, ponieważ cell staje się zbieralny, a więc jego TouchDown delegat, który przełoży się na zwisające wskaźnik.

Rozszerzenie liczby odwołań zapewnia, że zarządzany obiekt pozostaje aktywny i zapobiega jego kolekcji, pod warunkiem, że obiekt macierzysty jest zachowywany przez kod macierzysty.

Nowy system eliminuje również potrzebę obsługi większości prywatnych pól zapasowych używanych w powiązaniach — co jest domyślnym podejściem do utrzymania aktywności wystąpienia. Zarządzany konsolidator jest wystarczająco inteligentny, aby usunąć wszystkie niepotrzebne pola z aplikacji przy użyciu nowego rozszerzenia liczby odwołań.

Oznacza to, że każde wystąpienia obiektów zarządzanych zużywają mniej pamięci niż wcześniej. Rozwiązuje to również powiązany problem polegający na tym, że niektóre pola zapasowe będą przechowywać odwołania, które nie były już potrzebne przez Objective-C środowisko uruchomieniowe, co utrudnia odzyskanie pamięci.