Xamarin.iOS の新しい参照カウント システムNew Reference Counting System in Xamarin.iOS

Xamarin.iOS 9.2.1 では、すべてのアプリケーションに対する拡張参照カウント システムが既定で導入されました。Xamarin.iOS 9.2.1 introduced the enhanced reference counting system to all applications by default. これは、以前のバージョンの Xamarin.iOS で追跡して修正するのが困難だった多くのメモリの問題を排除するために使用できます。It can be used to eliminate many memory problems that were difficult to track and fix in earlier versions of Xamarin.iOS.

新しい参照カウント システムの有効化Enabling the New Reference Counting System

Xamarin 9.2.1 の現在、新しい ref カウント システムは既定で すべてのアプリケーションに 対して有効になっています。As of Xamarin 9.2.1 the new ref counting system is enabled to all applications by default.

既存のアプリケーションを開発している場合は、.csproj ファイルを確認して、 のすべての出現箇所が に設定されている必要があります。次に MtouchUseRefCounting true 示します。If you are developing an existing application, you can check the .csproj file to ensure that all occurrences of MtouchUseRefCounting are set to true, like below:


アプリケーションに設定されている false 場合、新しいツールは使用されます。If it is set to false your application will not be using the new tooling.

古いバージョンの Xamarin の使用Using older versions of Xamarin

Xamarin.iOS 7.2.1 以上では、新しい参照カウント システムのプレビューが強化されています。Xamarin.iOS 7.2.1 and above features a enhanced preview of our new reference counting system.

Classic API:Classic API:

この新しい参照カウント システムを有効にするには、次に示すように、プロジェクトの iOS ビルド オプションの [詳細設定] タブにある [参照カウント拡張機能を使用する] チェック ボックスをオンにします。 To enable this new Reference Counting System, check the Use the reference counting extension checkbox found in the Advanced tab of your project's iOS Build options, as shown below:

新しい参照カウント システムを有効にするEnable the new Reference Counting System

これらのオプションは、新しいバージョンの Visual Studio for Mac。Note that these options have been removed in newer versions of Visual Studio for Mac.

Unified API:Unified API:

新しい参照カウント拡張機能は、既定で有効Unified APIに必要です。The new reference counting extension is required for the Unified API and should be enabled by default. 以前のバージョンの IDE では、この値が自動的にチェックされない場合があります。また、自分でチェックを行う必要がある場合があります。Older versions of your IDE may not have this value checked automatically and you might have to place a check by it yourself.


この機能の以前のバージョンは MonoTouch 5.2 以降ですが、試験段階のプレビューとして sgen でのみ使用できます。An earlier version of this feature has been around since MonoTouch 5.2 but was only available for sgen as an experimental preview. この新しい拡張バージョンは 、Hm ガベージ コレクターでも使用できます。This new, enhanced version is now also available for the Boehm garbage collector.

これまで、Xamarin.iOS によって管理されるオブジェクトには、ネイティブ オブジェクト (ピア オブジェクト) のラッパーに過ごしたオブジェクトと、新しい機能 (派生オブジェクト) を拡張または組み込んだオブジェクト (通常はメモリ内の追加状態を維持する) の 2 種類がありました。Historically there have been two kinds of objects managed by Xamarin.iOS: those that were merely a wrapper around a native object (peer objects) and those that extended or incorporated new functionality (derived objects) - usually by keeping extra in-memory state. 以前は、状態でピア オブジェクトを拡張できますが (たとえば、C# イベント ハンドラーを追加することで)、オブジェクトを参照解除してから収集することができます。Previously it was possible that we could augment a peer object with state (for example by adding a C# event handler) but that we let the object go unreferenced and then collected. これにより、後で クラッシュが発生する可能性があります (ランタイムがマネージド オブジェクトに呼び出された Objective-C 場合など)。This could cause a crash later on (e.g. if the Objective-C runtime called back into the managed object).

新しいシステムは、追加の情報を格納するときに、ランタイムによって管理されるオブジェクトにピア オブジェクトを自動的にアップグレードします。The new system automatically upgrades peer objects into objects that are managed by the runtime when they store any extra information.

これにより、次のような状況で発生したさまざまなクラッシュが解決されます。This solves various crashes that happened in situations such as this one:

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 クラッシュします。Without the reference count extension this code would crash because cell becomes collectible, and so its TouchDown delegate, which will translate into a dangling pointer.

ネイティブ オブジェクトがネイティブ コードによって保持されている場合、参照カウント拡張機能により、マネージド オブジェクトが確実に維持され、そのコレクションが防止されます。The reference count extension ensures the managed object stays alive and prevents its collection, provided the native object is retained by native code.

新しいシステムでは、バインディングで使用されるほとんどのプライベート バッキング フィールドの必要性も削除されます。これは、インスタンスを維持するための既定のアプローチです。The new system also removes the need for most private backing fields used in bindings - which is the default approach to keep instance alive. マネージド リンカーは、新しい参照カウント拡張機能を使用して、不要なすべてのフィールドをアプリケーションから削除するのに十分なスマートです。The managed linker is smart enough to remove all those unneeded fields from applications using the new reference count extension.

つまり、各マネージド オブジェクト インスタンスは、以前よりも少ないメモリを消費します。This means that each managed object instances consume less memory than before. また、一部のバッキング フィールドにランタイムで不要な参照が保持され、一部のメモリを再利用しにくいする、関連する Objective-C 問題も解決されます。It also solves a related problem where some backing fields would hold references that were not needed anymore by the Objective-C runtime, making it hard to reclaim some memory.