Xamarin.iOS の新しい参照カウント システム

Xamarin.iOS 9.2.1 では、既定ですべてのアプリケーションに拡張参照カウント システムが導入されました。 これを使用して、以前のバージョンの Xamarin.iOS では追跡および修正が困難だった多くのメモリの問題を排除できます。

新しい参照カウント システムの有効化

Xamarin 9.2.1 の時点で、新しい参照カウント システムは既定ですべてのアプリケーションに対して有効になっています。

既存のアプリケーションを開発している場合は、.csproj ファイルを確認して、次のように、MtouchUseRefCounting のすべての出現箇所が true に設定されていることを確認できます。

<MtouchUseRefCounting>true</MtouchUseRefCounting>

false に設定されている場合、アプリケーションでは新しいツールは使用されません。

以前のバージョンの Xamarin の使用

Xamarin.iOS 7.2.1 以降には、新しい参照カウント システムの拡張プレビューが用意されています。

Classic API:

この新しい参照カウント システムを有効にするには、次に示すように、プロジェクトの [iOS ビルド] オプションの [詳細] タブにある [参照カウント拡張機能の使用] チェックボックスをオンにします。

Enable the new Reference Counting System

これらのオプションは、新しいバージョンの Visual Studio for Mac で削除されていることに注意してください。

Unified API:

Unified API には新しい参照カウント拡張機能が必要であり、既定で有効である必要があります。 古いバージョンの IDE では、この値が自動的に確認されていない可能性があり、自分自身で横にチェック マークを付けなければならない場合があります。

重要

この機能の以前のバージョンは MonoTouch 5.2 以降のバージョンで用意されていますが、試験段階のプレビューとして sgen でのみ使用できます。 この新しい拡張バージョンは、Boehm ガベージ コレクターでも使用できるようになりました。

これまで、通常は余分なメモリ内の状態を維持することで Xamarin.iOS によって管理されるオブジェクトには、ネイティブ オブジェクトのラッパーに過ぎなかったオブジェクト (ピア オブジェクト) と、新しい機能を拡張したか組み込んだオブジェクト (派生オブジェクト) の 2 種類がありました。 以前は、(C# イベント ハンドラーを追加するなどして) 状態を持つピア オブジェクトを拡張できましたが、オブジェクトが参照されずに収集できるようにしました。 これが原因で、後でクラッシュが発生する可能性が生じました (たとえば、Objective-C ランタイムがマネージド オブジェクトにコールバックされるなど)。

この新しいシステムdは、追加情報を格納するときにランタイムによって管理されるオブジェクトにピア オブジェクトが自動的にアップグレードされます。

これにより、次のような状況で発生したさまざまなクラッシュが解決されます。

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

参照カウント拡張機能がない場合、cell が収集可能になるため、TouchDown が delegate になり、ダングリング ポインターに変換されることが原因で、このコードはクラッシュします。

参照カウント拡張機能は、ネイティブ オブジェクトがネイティブ コードによって保持されることを前提として、マネージド オブジェクトが確実に存続するようにし、その収集を防ぎます。

新しいシステムでは、バインディングで使用されるほとんどのプライベート バッキング フィールドも不要になります。これは、インスタンスを存続させるための既定のアプローチです。 マネージド リンカーは、新しい参照カウント拡張機能を使用して、これらすべての不要なフィールドをアプリケーションから削除できるほど十分にスマートです。

つまり、各マネージド オブジェクト インスタンスのメモリ消費量は以前よりも少なくなります。 また、これにより、Objective-C ランタイムで不要になった参照を一部のバッキング フィールドが保持するため、一部のメモリの再利用が困難になるという、関連する問題も解決されます。