Xamarin.iOS の制限事項
Xamarin.iOS を使用するアプリケーションは静的コードにコンパイルされるため、実行時にコード生成を必要とする機能を使用することはできません。
デスクトップ Mono と比較した Xamarin.iOS の制限事項は次のとおりです。
制限付きジェネリックのサポート
従来の Mono/.NET とは異なり、iPhone 上のコードは、JIT コンパイラによってオンデマンドでコンパイルされるのではなく、事前に静的にコンパイルされます。
Mono の 完全な AOT テクノロジにはジェネリックに関するいくつかの制限があります。これは、すべての可能なジェネリックインスタンス化がコンパイル時に前もって決定できるとは限らないためです。 コードは常に Just In Time コンパイラを使用して実行時にコンパイルされるため、これは通常の .NET ランタイムまたは Mono ランタイムでは問題になりません。 しかし、これは Xamarin.iOS のような静的コンパイラにとって課題となります。
開発者が実行する一般的な問題には、次のようなものがあります。
NSObjects のジェネリック サブクラスは制限されています
現在、Xamarin.iOS では、ジェネリック メソッドのサポートがないなど、NSObject クラスのジェネリック サブクラスを作成するためのサポートが制限されています。 7.2.1 の時点で、次のように、NSObjects のジェネリック サブクラスを使用できます。
class Foo<T> : UIView {
[..]
}
注意
NSObjects のジェネリック サブクラスは可能ですが、いくつかの制限があります。 詳細については、 NSObject の Generic サブクラス に関するドキュメントを参照してください
動的コード生成なし
iOS カーネルでは、アプリケーションでコードが動的に生成されるのを防ぐため、Xamarin.iOS ではどのような形式の動的コード生成もサポートされていません。 これには以下が含まれます。
- System.Reflection.Emit は使用できません。
- System.Runtime.Remoting はサポートされません。
- 型を動的に作成するためのサポートはありません (Type.GetType ("MyType'1"))、既存の型 (Type.GetType ("System.String") を検索しても問題ありません)。
- リバース コールバックは、コンパイル時にランタイムに登録する必要があります。
System.Reflection.Emit
System.Reflection の欠如。 出力 とは、ランタイム コード生成に依存するコードが機能しないということです。 これには次のものが含まれます。
動的言語ランタイム。
動的言語ランタイムの上に構築された任意の言語。
リモート処理の TransparentProxy、またはランタイムがコードを動的に生成する原因となるその他の何か。
重要
Reflection.Emit とリフレクションを混同しないでください。 Reflection.Emit は、コードを動的に生成し、そのコードを JITed してネイティブ コードにコンパイルすることです。 iOS (JIT コンパイルなし) の制限により、これはサポートされていません。
ただし、Type.GetType ("someClass")、メソッドの一覧表示、プロパティの一覧表示、属性と値のフェッチなど、リフレクション API 全体は正常に動作します。
デリゲートを使用したネイティブ関数の呼び出し
C# デリゲートを使用してネイティブ関数を呼び出すには、デリゲートの宣言を次のいずれかの属性で修飾する必要があります。
- UnmanagedFunctionPointerAttribute (クロスプラットフォームであり、.NET Standard 1.1 以降と互換性があるため、推奨)
- MonoNativeFunctionWrapperAttribute
これらの属性のいずれかを指定しないと、次のような実行時エラーが発生します。
System.ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native) YourClass/YourDelegate:wrapper_aot_native(object,intptr,intptr)' while running in aot-only mode.
コールバックの反転
標準の Mono では、関数ポインターの代わりに、C# デリゲート インスタンスをアンマネージ コードに渡すことができます。 ランタイムは通常、これらの関数ポインターを小さなサンクに変換し、アンマネージ コードがマネージド コードにコールバックできるようにします。
Mono では、これらのブリッジは Just-In-Time コンパイラによって実装されます。 iPhone で必要な事前コンパイラを使用する場合、この時点で 2 つの重要な制限があります。
- MonoPInvokeCallbackAttribute を使用して、すべてのコールバック メソッドにフラグを設定する必要があります
- メソッドは静的メソッドである必要があります。インスタンス メソッドはサポートされません。
リモート処理なし
リモート処理スタックは Xamarin.iOS では使用できません。
ランタイムの無効な機能
Mono の iOS ランタイムでは、次の機能が無効になっています。
- プロファイラー
- Reflection.Emit
- Reflection.Emit.Save 機能
- COM バインド
- JIT エンジン
- メタデータ検証ツール (JIT がないため)
.NET API の制限事項
公開されている .NET API は、iOS ですべてが利用できるわけではないので、完全なフレームワークのサブセットです。 現在サポートされているアセンブリの一覧については、FAQ を参照してください。
特に、Xamarin.iOS で使用される API プロファイルには System.Configuration が含まれていないため、外部 XML ファイルを使用してランタイムの動作を構成することはできません。